Annotation of prex-old/usr/lib/libc/stdio/fvwrite.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 1990, 1993
3: * The Regents of the University of California. All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Chris Torek.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #include <stdio.h>
34: #include <string.h>
35: #include "local.h"
36: #include "fvwrite.h"
37:
38: /*
39: * Write some memory regions. Return zero on success, EOF on error.
40: *
41: * This routine is large and unsightly, but most of the ugliness due
42: * to the three different kinds of output buffering is handled here.
43: */
44: int
45: __sfvwrite(fp, uio)
46: FILE *fp;
47: struct __suio *uio;
48: {
49: size_t len;
50: char *p;
51: struct __siov *iov;
52: int w, s;
53: char *nl;
54: int nlknown, nldist;
55:
56: if ((len = uio->uio_resid) == 0)
57: return (0);
58: /* make sure we can write */
59: if (cantwrite(fp))
60: return (EOF);
61:
62: #define MIN(a, b) ((a) < (b) ? (a) : (b))
63: #define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
64:
65: iov = uio->uio_iov;
66: p = iov->iov_base;
67: len = iov->iov_len;
68: iov++;
69: #define GETIOV(extra_work) \
70: while (len == 0) { \
71: extra_work; \
72: p = iov->iov_base; \
73: len = iov->iov_len; \
74: iov++; \
75: }
76: if (fp->_flags & __SNBF) {
77: /*
78: * Unbuffered: write up to BUFSIZ bytes at a time.
79: */
80: do {
81: GETIOV(;);
82: w = __swrite(fp, p, MIN(len, BUFSIZ));
83: if (w <= 0)
84: goto err;
85: p += w;
86: len -= w;
87: } while ((uio->uio_resid -= w) != 0);
88: } else if ((fp->_flags & __SLBF) == 0) {
89: /*
90: * Fully buffered: fill partially full buffer, if any,
91: * and then flush. If there is no partial buffer, write
92: * one _bf._size byte chunk directly (without copying).
93: *
94: * String output is a special case: write as many bytes
95: * as fit, but pretend we wrote everything. This makes
96: * snprintf() return the number of bytes needed, rather
97: * than the number used, and avoids its write function
98: * (so that the write function can be invalid).
99: */
100: do {
101: GETIOV(;);
102: w = fp->_w;
103: if (fp->_flags & __SSTR) {
104: if (len < w)
105: w = len;
106: COPY(w); /* copy MIN(fp->_w,len), */
107: fp->_w -= w;
108: fp->_p += w;
109: w = len; /* but pretend copied all */
110: } else if (fp->_p > fp->_bf._base && len > w) {
111: /* fill and flush */
112: COPY(w);
113: /* fp->_w -= w; */ /* unneeded */
114: fp->_p += w;
115: if (fflush(fp))
116: goto err;
117: } else if (len >= (w = fp->_bf._size)) {
118: /* write directly */
119: w = __swrite(fp, p, w);
120: if (w <= 0)
121: goto err;
122: } else {
123: /* fill and done */
124: w = len;
125: COPY(w);
126: fp->_w -= w;
127: fp->_p += w;
128: }
129: p += w;
130: len -= w;
131: } while ((uio->uio_resid -= w) != 0);
132: } else {
133: /*
134: * Line buffered: like fully buffered, but we
135: * must check for newlines. Compute the distance
136: * to the first newline (including the newline),
137: * or `infinity' if there is none, then pretend
138: * that the amount to write is MIN(len,nldist).
139: */
140: nlknown = 0;
141: nldist = 0; /* XXX just to keep gcc happy */
142: do {
143: GETIOV(nlknown = 0);
144: if (!nlknown) {
145: nl = memchr((void *)p, '\n', len);
146: nldist = nl ? nl + 1 - p : len + 1;
147: nlknown = 1;
148: }
149: s = MIN(len, nldist);
150: w = fp->_w + fp->_bf._size;
151: if (fp->_p > fp->_bf._base && s > w) {
152: COPY(w);
153: /* fp->_w -= w; */
154: fp->_p += w;
155: if (fflush(fp))
156: goto err;
157: } else if (s >= (w = fp->_bf._size)) {
158: w = __swrite(fp, p, w);
159: if (w <= 0)
160: goto err;
161: } else {
162: w = s;
163: COPY(w);
164: fp->_w -= w;
165: fp->_p += w;
166: }
167: if ((nldist -= w) == 0) {
168: /* copied the newline: flush and forget */
169: if (fflush(fp))
170: goto err;
171: nlknown = 0;
172: }
173: p += w;
174: len -= w;
175: } while ((uio->uio_resid -= w) != 0);
176: }
177: return (0);
178:
179: err:
180: fp->_flags |= __SERR;
181: return (EOF);
182: }
CVSweb