6069 libdisasm: instrlen arch op should have a sane default
[illumos-gate.git] / usr / src / lib / libc / port / stdio / fwrite.c
blobdb5928f9f492c17dcbb31c2ce37d7f36f79a35e1
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "lint.h"
33 #include "file64.h"
34 #include "mtlib.h"
35 #include <sys/types.h>
36 #include <stdio.h>
37 #include <values.h>
38 #include <memory.h>
39 #include <thread.h>
40 #include <synch.h>
41 #include <unistd.h>
42 #include "stdiom.h"
43 #include "mse.h"
45 size_t
46 _fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop);
48 size_t
49 fwrite(const void *ptr, size_t size, size_t count, FILE *iop)
51 rmutex_t *lk;
52 size_t retval;
54 FLOCKFILE(lk, iop);
56 _SET_ORIENTATION_BYTE(iop);
58 retval = _fwrite_unlocked(ptr, size, count, iop);
59 FUNLOCKFILE(lk);
61 return (retval);
64 size_t
65 _fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop)
67 ssize_t s, n;
68 unsigned char *dptr = (unsigned char *)ptr;
69 unsigned char *bufend;
71 if (_WRTCHK(iop))
72 return (0);
75 * This test is here to avoid the expensive multiply
77 if (count == 1)
78 s = size;
79 else if (size == 1)
80 s = count;
81 else
82 s = size * count;
84 if (iop->_flag & _IOLBF) {
85 bufend = _bufend(iop);
86 iop->_cnt = iop->_base - iop->_ptr;
87 while (s > 0) {
88 ssize_t buflen = bufend - iop->_base;
89 if (--iop->_cnt >= (-buflen) && *dptr != '\n')
90 *iop->_ptr++ = *dptr++;
91 else if (__flsbuf(*dptr++, iop) == EOF)
92 break;
93 s--;
95 } else if (iop->_flag & _IONBF) {
96 ssize_t bytes;
97 ssize_t written = 0;
98 char *data;
100 if (size < 1 || count < 1)
101 return (0);
103 if (iop->_base != iop->_ptr) {
105 * Flush any existing data. Doesn't count towards return
106 * value.
108 bytes = iop->_ptr - iop->_base;
109 data = (char *)iop->_base;
111 while ((n = write(fileno(iop), data, (size_t)bytes))
112 != bytes) {
113 if (n == -1) {
114 if (!cancel_active())
115 iop->_flag |= _IOERR;
116 return (0);
117 } else {
118 data += n;
119 bytes -= n;
122 iop->_cnt = 0;
123 iop->_ptr = iop->_base;
126 * written is in bytes until the return.
127 * Then it is divided by size to produce items.
129 while ((n = write(fileno(iop), dptr, s)) != s) {
130 if (n == -1) {
131 if (!cancel_active())
132 iop->_flag |= _IOERR;
133 return (written / size);
134 } else {
135 dptr += n;
136 s -= n;
137 written += n;
140 written += n;
141 return (written / size);
142 } else while (s > 0) {
143 if (iop->_cnt < s) {
144 if (iop->_cnt > 0) {
145 (void) memcpy(iop->_ptr, (void *)dptr,
146 iop->_cnt);
147 dptr += iop->_cnt;
148 iop->_ptr += iop->_cnt;
149 s -= iop->_cnt;
151 if (_xflsbuf(iop) == EOF)
152 break;
154 if (iop->_cnt >= s) {
155 char *tmp = (char *)iop->_ptr;
157 switch (s) {
158 case 8:
159 *tmp++ = *dptr++;
160 /*FALLTHRU*/
161 case 7:
162 *tmp++ = *dptr++;
163 /*FALLTHRU*/
164 case 6:
165 *tmp++ = *dptr++;
166 /*FALLTHRU*/
167 case 5:
168 *tmp++ = *dptr++;
169 /*FALLTHRU*/
170 case 4:
171 *tmp++ = *dptr++;
172 /*FALLTHRU*/
173 case 3:
174 *tmp++ = *dptr++;
175 /*FALLTHRU*/
176 case 2:
177 *tmp++ = *dptr++;
178 /*FALLTHRU*/
179 case 1:
180 *tmp++ = *dptr++;
181 break;
182 case 0:
183 return (count);
184 default:
185 (void) memcpy(iop->_ptr, (void *)dptr, s);
187 iop->_ptr += s;
188 iop->_cnt -= s;
190 return (count);
194 return (size != 0 ? count - ((s + size - 1) / size) : 0);