1:
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
33:
34: #include <stdio.h>
35: #include <stdlib.h>
36: #include <string.h>
37: #include <errno.h>
38: #include "local.h"
39: #include "fvwrite.h"
40:
41: 42: 43: 44: 45: 46:
47: int
48: __sfvwrite(FILE *fp, struct __suio *uio)
49: {
50: size_t len;
51: char *p;
52: struct __siov *iov;
53: int w, s;
54: char *nl;
55: int nlknown, nldist;
56:
57: if ((len = uio->uio_resid) == 0)
58: return (0);
59:
60: if (cantwrite(fp)) {
61: __sseterr(fp, EBADF);
62: return (EOF);
63: }
64:
65: #define MIN(a, b) ((a) < (b) ? (a) : (b))
66: #define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
67:
68: iov = uio->uio_iov;
69: p = iov->iov_base;
70: len = iov->iov_len;
71: iov++;
72: #define GETIOV(extra_work) \
73: while (len == 0) { \
74: extra_work; \
75: p = iov->iov_base; \
76: len = iov->iov_len; \
77: iov++; \
78: }
79: if (fp->_flags & __SNBF) {
80: 81: 82:
83: do {
84: GETIOV(;);
85: w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
86: if (w <= 0)
87: goto err;
88: p += w;
89: len -= w;
90: } while ((uio->uio_resid -= w) != 0);
91: } else if ((fp->_flags & __SLBF) == 0) {
92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102:
103: do {
104: GETIOV(;);
105: if ((fp->_flags & (__SALC | __SSTR)) ==
106: (__SALC | __SSTR) && fp->_w < len) {
107: size_t blen = fp->_p - fp->_bf._base;
108: unsigned char *_base;
109: int _size;
110:
111:
112: _size = fp->_bf._size;
113: do {
114: _size = (_size << 1) + 1;
115: } while (_size < blen + len);
116: _base = realloc(fp->_bf._base, _size + 1);
117: if (_base == NULL)
118: goto err;
119: fp->_w += _size - fp->_bf._size;
120: fp->_bf._base = _base;
121: fp->_bf._size = _size;
122: fp->_p = _base + blen;
123: }
124: w = fp->_w;
125: if (fp->_flags & __SSTR) {
126: if (len < w)
127: w = len;
128: COPY(w);
129: fp->_w -= w;
130: fp->_p += w;
131: w = len;
132: } else if (fp->_p > fp->_bf._base && len > w) {
133:
134: COPY(w);
135:
136: fp->_p += w;
137: if (__sflush(fp))
138: goto err;
139: } else if (len >= (w = fp->_bf._size)) {
140:
141: w = (*fp->_write)(fp->_cookie, p, w);
142: if (w <= 0)
143: goto err;
144: } else {
145:
146: w = len;
147: COPY(w);
148: fp->_w -= w;
149: fp->_p += w;
150: }
151: p += w;
152: len -= w;
153: } while ((uio->uio_resid -= w) != 0);
154: } else {
155: 156: 157: 158: 159: 160: 161:
162: nlknown = 0;
163: nldist = 0;
164: do {
165: GETIOV(nlknown = 0);
166: if (!nlknown) {
167: nl = memchr((void *)p, '\n', len);
168: nldist = nl ? nl + 1 - p : len + 1;
169: nlknown = 1;
170: }
171: s = MIN(len, nldist);
172: w = fp->_w + fp->_bf._size;
173: if (fp->_p > fp->_bf._base && s > w) {
174: COPY(w);
175:
176: fp->_p += w;
177: if (__sflush(fp))
178: goto err;
179: } else if (s >= (w = fp->_bf._size)) {
180: w = (*fp->_write)(fp->_cookie, p, w);
181: if (w <= 0)
182: goto err;
183: } else {
184: w = s;
185: COPY(w);
186: fp->_w -= w;
187: fp->_p += w;
188: }
189: if ((nldist -= w) == 0) {
190:
191: if (__sflush(fp))
192: goto err;
193: nlknown = 0;
194: }
195: p += w;
196: len -= w;
197: } while ((uio->uio_resid -= w) != 0);
198: }
199: return (0);
200:
201: err:
202: fp->_flags |= __SERR;
203: return (EOF);
204: }