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 <sys/types.h> 34 #include <stdio.h> 35 #include <values.h> 36 #include <memory.h> 37 #include <thread.h> 38 #include <synch.h> 39 #include <unistd.h> 40 #include "stdiom.h" 41 #include "mse.h" 42 43 size_t 44 _fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop); 45 46 size_t 47 fwrite(const void *ptr, size_t size, size_t count, FILE *iop) 48 { 49 rmutex_t *lk; 50 size_t retval; 51 52 FLOCKFILE(lk, iop); 53 54 _SET_ORIENTATION_BYTE(iop); 55 56 retval = _fwrite_unlocked(ptr, size, count, iop); 57 FUNLOCKFILE(lk); 58 59 return (retval); 60 } 61 62 size_t 63 _fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop) 64 { 65 ssize_t s, n; 66 unsigned char *dptr = (unsigned char *)ptr; 67 unsigned char *bufend; 68 69 if (_WRTCHK(iop)) 70 return (0); 71 72 /* 73 * This test is here to avoid the expensive multiply 74 */ 75 if (count == 1) 76 s = size; 77 else if (size == 1) 78 s = count; 79 else 80 s = size * count; 81 82 if (iop->_flag & _IOLBF) { 83 bufend = _bufend(iop); 84 iop->_cnt = iop->_base - iop->_ptr; 85 while (s > 0) { 86 ssize_t buflen = bufend - iop->_base; 87 if (--iop->_cnt >= (-buflen) && *dptr != '\n') 88 *iop->_ptr++ = *dptr++; 89 else if (__flsbuf(*dptr++, iop) == EOF) 90 break; 91 s--; 92 } 93 } else if (iop->_flag & _IONBF) { 94 ssize_t bytes; 95 ssize_t written = 0; 96 char *data; 97 98 if (size < 1 || count < 1) 99 return (0); 100 101 if (iop->_base != iop->_ptr) { 102 /* 103 * Flush any existing data. Doesn't count towards return 104 * value. 105 */ 106 bytes = iop->_ptr - iop->_base; 107 data = (char *)iop->_base; 108 109 while ((n = _xwrite(iop, data, (size_t)bytes)) != 110 bytes) { 111 if (n <= 0) { 112 if (!cancel_active()) 113 iop->_flag |= _IOERR; 114 return (0); 115 } else { 116 data += n; 117 bytes -= n; 118 } 119 } 120 iop->_cnt = 0; 121 iop->_ptr = iop->_base; 122 } 123 /* 124 * written is in bytes until the return. 125 * Then it is divided by size to produce items. 126 */ 127 while ((n = _xwrite(iop, dptr, s)) != s) { 128 if (n <= 0) { 129 if (!cancel_active()) 130 iop->_flag |= _IOERR; 131 return (written / size); 132 } else { 133 dptr += n; 134 s -= n; 135 written += n; 136 } 137 } 138 written += n; 139 return (written / size); 140 } else while (s > 0) { 141 if (iop->_cnt < s) { 142 if (iop->_cnt > 0) { 143 (void) memcpy(iop->_ptr, (void *)dptr, 144 iop->_cnt); 145 dptr += iop->_cnt; 146 iop->_ptr += iop->_cnt; 147 s -= iop->_cnt; 148 } 149 if (_xflsbuf(iop) == EOF) 150 break; 151 } 152 if (iop->_cnt >= s) { 153 char *tmp = (char *)iop->_ptr; 154 155 switch (s) { 156 case 8: 157 *tmp++ = *dptr++; 158 /*FALLTHRU*/ 159 case 7: 160 *tmp++ = *dptr++; 161 /*FALLTHRU*/ 162 case 6: 163 *tmp++ = *dptr++; 164 /*FALLTHRU*/ 165 case 5: 166 *tmp++ = *dptr++; 167 /*FALLTHRU*/ 168 case 4: 169 *tmp++ = *dptr++; 170 /*FALLTHRU*/ 171 case 3: 172 *tmp++ = *dptr++; 173 /*FALLTHRU*/ 174 case 2: 175 *tmp++ = *dptr++; 176 /*FALLTHRU*/ 177 case 1: 178 *tmp++ = *dptr++; 179 break; 180 case 0: 181 return (count); 182 default: 183 (void) memcpy(iop->_ptr, (void *)dptr, s); 184 } 185 iop->_ptr += s; 186 iop->_cnt -= s; 187 188 return (count); 189 } 190 } 191 192 return (size != 0 ? count - ((s + size - 1) / size) : 0); 193 } 194