1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #include "lint.h" 31 #include "file64.h" 32 #include "mtlib.h" 33 #include <stdio.h> 34 #include <stddef.h> 35 #include <values.h> 36 #include <memory.h> 37 #include <thread.h> 38 #include <synch.h> 39 #include <errno.h> 40 #include <sys/types.h> 41 #include "stdiom.h" 42 #include "mse.h" 43 44 size_t 45 fread(void *ptr, size_t size, size_t count, FILE *iop) 46 { 47 ssize_t s; 48 int c; 49 char *dptr = (char *)ptr; 50 rmutex_t *lk; 51 52 FLOCKFILE(lk, iop); 53 54 _SET_ORIENTATION_BYTE(iop); 55 56 /* is it a readable stream */ 57 if (!(iop->_flag & (_IOREAD | _IORW))) { 58 iop->_flag |= _IOERR; 59 errno = EBADF; 60 FUNLOCKFILE(lk); 61 return (0); 62 } 63 64 if (iop->_flag & _IOEOF) { 65 FUNLOCKFILE(lk); 66 return (0); 67 } 68 69 /* These checks are here to avoid the multiply */ 70 if (count == 1) 71 s = size; 72 else if (size == 1) 73 s = count; 74 else 75 s = size * count; 76 77 while (s > 0) { 78 if (iop->_cnt < s) { 79 if (iop->_cnt > 0) { 80 (void) memcpy((void*)dptr, iop->_ptr, 81 iop->_cnt); 82 dptr += iop->_cnt; 83 s -= iop->_cnt; 84 } 85 /* 86 * filbuf clobbers _cnt & _ptr, 87 * so don't waste time setting them. 88 */ 89 if ((c = __filbuf(iop)) == EOF) 90 break; 91 *dptr++ = (char)c; 92 s--; 93 } 94 if (iop->_cnt >= s) { 95 char *tmp = (char *)iop->_ptr; 96 switch (s) { 97 case 8: 98 *dptr++ = *tmp++; 99 /*FALLTHRU*/ 100 case 7: 101 *dptr++ = *tmp++; 102 /*FALLTHRU*/ 103 case 6: 104 *dptr++ = *tmp++; 105 /*FALLTHRU*/ 106 case 5: 107 *dptr++ = *tmp++; 108 /*FALLTHRU*/ 109 case 4: 110 *dptr++ = *tmp++; 111 /*FALLTHRU*/ 112 case 3: 113 *dptr++ = *tmp++; 114 /*FALLTHRU*/ 115 case 2: 116 *dptr++ = *tmp++; 117 /*FALLTHRU*/ 118 case 1: 119 *dptr++ = *tmp++; 120 break; 121 default: 122 (void) memcpy((void*)dptr, iop->_ptr, 123 (size_t)s); 124 } 125 iop->_ptr += s; 126 iop->_cnt -= s; 127 FUNLOCKFILE(lk); 128 return (count); 129 } 130 } 131 FUNLOCKFILE(lk); 132 return (size != 0 ? count - ((s + size - 1) / size) : 0); 133 } 134