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
fwrite(const void * ptr,size_t size,size_t count,FILE * iop)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
_fwrite_unlocked(const void * ptr,size_t size,size_t count,FILE * iop)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