/* * Helper function for `fprintf to unbuffered unix file': creates a * temporary buffer. We only work on write-only files; this avoids * worries about ungetc buffers and so forth. */ static int __sbprintf(FILE *fp, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; unsigned char buf[BUFSIZ]; /* XXX This is probably not needed. */ if (prepwrite(fp) != 0) return (EOF); /* copy the important variables */ fake._flags = fp->_flags & ~__SNBF; fake._file = fp->_file; fake._cookie = fp->_cookie; fake._write = fp->_write; fake._orientation = fp->_orientation; fake._mbstate = fp->_mbstate; /* set up the buffer */ fake._bf._base = fake._p = buf; fake._bf._size = fake._w = sizeof(buf); fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ ret = __vfprintf(&fake, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) fp->_flags |= __SERR; return (ret); }
/* * Write some memory regions. Return zero on success, EOF on error. * * This routine is large and unsightly, but most of the ugliness due * to the three different kinds of output buffering is handled here. */ int __sfvwrite(FILE *fp, struct __suio *uio) { size_t len; char *p; struct __siov *iov; int w, s; char *nl; int nlknown, nldist; if ((len = uio->uio_resid) == 0) return (0); /* make sure we can write */ if (prepwrite(fp) != 0) return (EOF); #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define COPY(n) memcpy((void *)fp->pub._p, (void *)p, (size_t)(n)) iov = uio->uio_iov; p = iov->iov_base; len = iov->iov_len; iov++; #define GETIOV(extra_work) \ while (len == 0) { \ extra_work; \ p = iov->iov_base; \ len = iov->iov_len; \ iov++; \ } if (fp->pub._flags & __SNBF) { /* * Unbuffered: write up to BUFSIZ bytes at a time. */ do { GETIOV(;); w = _swrite(fp, p, MIN(len, BUFSIZ)); if (w <= 0) goto err; p += w; len -= w; } while ((uio->uio_resid -= w) != 0); } else if ((fp->pub._flags & __SLBF) == 0) {
/* * Write the given character into the (probably full) buffer for * the given file. Flush the buffer out if it is or becomes full, * or if c=='\n' and the file is line buffered. * * Non-MT-safe */ int __swbuf(int c, FILE *fp) { int n; /* * In case we cannot write, or longjmp takes us out early, * make sure _w is 0 (if fully- or un-buffered) or -_bf._size * (if line buffered) so that we will get called again. * If we did not do this, a sufficient number of putc() * calls might wrap _w from negative to positive. */ fp->_w = fp->_lbfsize; if (prepwrite(fp) != 0) return (EOF); c = (unsigned char)c; ORIENT(fp, -1); /* * If it is completely full, flush it out. Then, in any case, * stuff c into the buffer. If this causes the buffer to fill * completely, or if c is '\n' and the file is line buffered, * flush it (perhaps a second time). The second flush will always * happen on unbuffered streams, where _bf._size==1; fflush() * guarantees that putc() will always call wbuf() by setting _w * to 0, so we need not do anything else. */ n = fp->_p - fp->_bf._base; if (n >= fp->_bf._size) { if (__fflush(fp)) return (EOF); n = 0; } fp->_w--; *fp->_p++ = c; if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) if (__fflush(fp)) return (EOF); return (c); }