diff options
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r-- | lib/libc/stdio/fdopen.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/fflush.c | 6 | ||||
-rw-r--r-- | lib/libc/stdio/fopen.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/fseek.c | 44 | ||||
-rw-r--r-- | lib/libc/stdio/ftell.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/fvwrite.c | 27 | ||||
-rw-r--r-- | lib/libc/stdio/local.h | 1 | ||||
-rw-r--r-- | lib/libc/stdio/refill.c | 9 | ||||
-rw-r--r-- | lib/libc/stdio/stdio.c | 49 |
9 files changed, 89 insertions, 55 deletions
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c index 2e72e71..30bf5b9 100644 --- a/lib/libc/stdio/fdopen.c +++ b/lib/libc/stdio/fdopen.c @@ -78,8 +78,8 @@ fdopen(fd, mode) fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have - * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to - * end before each write. + * O_APPEND bit set, assert __SAPP so that __swrite() caller + * will _sseek() to the end before write. */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->_flags |= __SAPP; diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index 5c1eaa1..55a6a2a 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -113,9 +113,15 @@ __sflush(FILE *fp) fp->_p = p; fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + if (n <= 0) + return (0); + if ((fp->_flags & __SAPP) && _sseek(fp, (fpos_t)0, SEEK_END) == -1) + goto err; + fp->_flags &= ~__SOFF; /* In case FAPPEND mode is set. */ for (; n > 0; n -= t, p += t) { t = (*fp->_write)(fp->_cookie, (char *)p, n); if (t <= 0) { + err: fp->_flags |= __SERR; return (EOF); } diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c index f09fe8a..709316d 100644 --- a/lib/libc/stdio/fopen.c +++ b/lib/libc/stdio/fopen.c @@ -85,6 +85,6 @@ fopen(file, mode) * fseek and ftell.) */ if (oflags & O_APPEND) - (void) __sseek((void *)fp, (fpos_t)0, SEEK_END); + (void)_sseek(fp, (fpos_t)0, SEEK_END); return (fp); } diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c index 38a8bf5..0cbf798 100644 --- a/lib/libc/stdio/fseek.c +++ b/lib/libc/stdio/fseek.c @@ -274,7 +274,7 @@ abspos: * ensures that we only read one block, rather than two. */ curoff = target & ~(fp->_blksize - 1); - if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR) + if (_sseek(fp, curoff, SEEK_SET) == POS_ERR) goto dumb; fp->_r = 0; fp->_p = fp->_bf._base; @@ -295,8 +295,7 @@ abspos: * do it. Allow the seek function to change fp->_bf._base. */ dumb: - if (__sflush(fp) || - (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) + if (__sflush(fp) || _sseek(fp, (fpos_t)offset, whence) == POS_ERR) return (-1); if (ltest && fp->_offset > LONG_MAX) { fp->_flags |= __SERR; @@ -312,3 +311,42 @@ dumb: fp->_flags &= ~__SEOF; return (0); } + + +fpos_t +_sseek(fp, offset, whence) + FILE *fp; + fpos_t offset; + int whence; +{ + fpos_t ret; + int serrno, errret; + + if (fp->_seek == NULL) { + errno = ESPIPE; + return (-1); + } + serrno = errno; + errno = 0; + ret = (*fp->_seek)(fp->_cookie, offset, whence); + errret = errno; + if (errno == 0) + errno = serrno; + /* + * Disallow negative seeks per POSIX. + * It is needed here to help upper level caller + * in the cases it can't detect. + */ + if (ret < 0) { + if (errret == 0) { + fp->_flags |= __SERR; + errno = EINVAL; + } + fp->_flags &= ~__SOFF; + ret = -1; + } else { + fp->_flags |= __SOFF; + fp->_offset = ret; + } + return (ret); +} diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index e355a20..174eaa8 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -110,7 +110,7 @@ _ftello(fp, offset) if (fp->_flags & __SOFF) pos = fp->_offset; else { - pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR); + pos = _sseek(fp, (fpos_t)0, SEEK_CUR); if (pos == -1) return (1); } diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c index 82a49cb..efcfffb 100644 --- a/lib/libc/stdio/fvwrite.c +++ b/lib/libc/stdio/fvwrite.c @@ -64,7 +64,7 @@ __sfvwrite(fp, uio) register struct __siov *iov; register int w, s; char *nl; - int nlknown, nldist; + int nlknown, nldist, firsttime; if ((len = uio->uio_resid) == 0) return (0); @@ -86,12 +86,21 @@ __sfvwrite(fp, uio) len = iov->iov_len; \ iov++; \ } + firsttime = 1; if (fp->_flags & __SNBF) { /* * Unbuffered: write up to BUFSIZ bytes at a time. */ do { GETIOV(;); + if (firsttime) { + if ((fp->_flags & __SAPP) && + _sseek(fp, (fpos_t)0, SEEK_END) == -1) + goto err; + /* In case FAPPEND mode is set. */ + fp->_flags &= ~__SOFF; + firsttime = 0; + } w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ)); if (w <= 0) goto err; @@ -147,6 +156,14 @@ __sfvwrite(fp, uio) goto err; } else if (len >= (w = fp->_bf._size)) { /* write directly */ + if (firsttime) { + if ((fp->_flags & __SAPP) && + _sseek(fp, (fpos_t)0, SEEK_END) == -1) + goto err; + /* In case FAPPEND mode is set. */ + fp->_flags &= ~__SOFF; + firsttime = 0; + } w = (*fp->_write)(fp->_cookie, p, w); if (w <= 0) goto err; @@ -186,6 +203,14 @@ __sfvwrite(fp, uio) if (__fflush(fp)) goto err; } else if (s >= (w = fp->_bf._size)) { + if (firsttime) { + if ((fp->_flags & __SAPP) && + _sseek(fp, (fpos_t)0, SEEK_END) == -1) + goto err; + /* In case FAPPEND mode is set. */ + fp->_flags &= ~__SOFF; + firsttime = 0; + } w = (*fp->_write)(fp->_cookie, p, w); if (w <= 0) goto err; diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index d37a540..e074273 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -46,6 +46,7 @@ * in particular, macros and private variables. */ +extern fpos_t _sseek __P((FILE *, fpos_t, int)); extern int _ftello __P((FILE *, fpos_t *)); extern int _fseeko __P((FILE *, off_t, int, int)); extern int __fflush __P((FILE *fp)); diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c index fa46d78..2d30e81 100644 --- a/lib/libc/stdio/refill.c +++ b/lib/libc/stdio/refill.c @@ -44,6 +44,7 @@ static const char rcsid[] = #include "namespace.h" #include <errno.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include "un-namespace.h" @@ -141,10 +142,18 @@ __srefill(FILE *fp) if (fp->_r == 0) fp->_flags |= __SEOF; else { + err: fp->_r = 0; fp->_flags |= __SERR; + fp->_flags &= ~__SOFF; } return (EOF); + } else if (fp->_flags & __SOFF) { + if (fp->_offset > OFF_MAX - fp->_r) { + errno = EOVERFLOW; + goto err; + } else + fp->_offset += fp->_r; } return (0); } diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c index ea8a4c1..b4bf299 100644 --- a/lib/libc/stdio/stdio.c +++ b/lib/libc/stdio/stdio.c @@ -45,7 +45,6 @@ static const char rcsid[] = #include "namespace.h" #include <errno.h> #include <fcntl.h> -#include <limits.h> #include <stdio.h> #include <unistd.h> #include "un-namespace.h" @@ -53,7 +52,6 @@ static const char rcsid[] = /* * Small standard I/O/seek/close functions. - * These maintain the `known seek offset' for seek optimisation. */ int __sread(cookie, buf, n) @@ -62,24 +60,8 @@ __sread(cookie, buf, n) int n; { register FILE *fp = cookie; - register int ret; - ret = _read(fp->_file, buf, (size_t)n); - /* if the read succeeded, update the current offset */ - if (ret >= 0) { - if (fp->_flags & __SOFF) { - if (fp->_offset > OFF_MAX - ret) { - errno = EOVERFLOW; - ret = -1; - } else { - fp->_offset += ret; - return (ret); - } - } else - return (ret); - } - fp->_flags &= ~__SOFF; - return (ret); + return(_read(fp->_file, buf, (size_t)n)); } int @@ -90,9 +72,6 @@ __swrite(cookie, buf, n) { register FILE *fp = cookie; - if (fp->_flags & __SAPP) - (void) lseek(fp->_file, (off_t)0, SEEK_END); - fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */ return (_write(fp->_file, buf, (size_t)n)); } @@ -103,32 +82,8 @@ __sseek(cookie, offset, whence) int whence; { register FILE *fp = cookie; - register off_t ret; - int serrno, errret; - serrno = errno; - errno = 0; - ret = lseek(fp->_file, (off_t)offset, whence); - errret = errno; - if (errno == 0) - errno = serrno; - /* - * Disallow negative seeks per POSIX. - * It is needed here to help upper level caller - * (fseek) in the cases it can't detect. - */ - if (ret < 0) { - if (errret == 0) { - fp->_flags |= __SERR; - errno = EINVAL; - } - fp->_flags &= ~__SOFF; - ret = -1; - } else { - fp->_flags |= __SOFF; - fp->_offset = ret; - } - return (ret); + return (lseek(fp->_file, (off_t)offset, whence)); } int |