diff options
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r-- | lib/libc/stdio/fseek.3 | 6 | ||||
-rw-r--r-- | lib/libc/stdio/fseek.c | 28 | ||||
-rw-r--r-- | lib/libc/stdio/local.h | 2 | ||||
-rw-r--r-- | lib/libc/stdio/rewind.c | 10 |
4 files changed, 36 insertions, 10 deletions
diff --git a/lib/libc/stdio/fseek.3 b/lib/libc/stdio/fseek.3 index b37aa17..1b5d397 100644 --- a/lib/libc/stdio/fseek.3 +++ b/lib/libc/stdio/fseek.3 @@ -185,7 +185,11 @@ The resulting file-position indicator would be set to a negative value. .It Bq Er EOVERFLOW The resulting file offset would be a value which -cannot be represented correctly in an object of type requested. +cannot be represented correctly in an object of type off_t +for +.Fn fseeko +or long for +.Fn fseek . .El .Pp The functions diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c index c357370..e0a1648 100644 --- a/lib/libc/stdio/fseek.c +++ b/lib/libc/stdio/fseek.c @@ -62,7 +62,16 @@ fseek(fp, offset, whence) long offset; int whence; { - return (fseeko(fp, offset, whence)); + int ret; + + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + + FLOCKFILE(fp); + ret = _fseeko(fp, (off_t)offset, whence, 1); + FUNLOCKFILE(fp); + return (ret); } int @@ -78,7 +87,7 @@ fseeko(fp, offset, whence) __sinit(); FLOCKFILE(fp); - ret = _fseeko(fp, offset, whence); + ret = _fseeko(fp, offset, whence, 0); FUNLOCKFILE(fp); return (ret); } @@ -88,10 +97,11 @@ fseeko(fp, offset, whence) * `Whence' must be one of the three SEEK_* macros. */ int -_fseeko(fp, offset, whence) +_fseeko(fp, offset, whence, ltest) FILE *fp; off_t offset; int whence; + int ltest; { register fpos_t (*seekfn) __P((void *, fpos_t, int)); fpos_t target, curoff; @@ -134,7 +144,8 @@ _fseeko(fp, offset, whence) curoff += fp->_p - fp->_bf._base; /* curoff always >= 0 */ - if (offset > 0 && curoff > OFF_MAX - offset) { + if (offset > 0 && + curoff > (ltest ? LONG_MAX : OFF_MAX) - offset) { errno = EOVERFLOW; return (EOF); } @@ -197,7 +208,8 @@ _fseeko(fp, offset, whence) if (_fstat(fp->_file, &st)) goto dumb; /* st.st_size always >= 0 */ - if (offset > 0 && st.st_size > OFF_MAX - offset) { + if (offset > 0 && + st.st_size > (ltest ? LONG_MAX : OFF_MAX) - offset) { errno = EOVERFLOW; return (EOF); } @@ -290,6 +302,12 @@ dumb: if (__sflush(fp) || (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) return (EOF); + /* POSIX require long type resulting offset for fseek() */ + if (ltest && fp->_offset != (long)fp->_offset) { + fp->_flags &= ~__SOFF; + errno = EOVERFLOW; + return (EOF); + } /* success: clear EOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index 06fecc9..5c0d347 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -46,7 +46,7 @@ * in particular, macros and private variables. */ -extern int _fseeko __P((FILE *, off_t, int)); +extern int _fseeko __P((FILE *, off_t, int, int)); extern int __fflush __P((FILE *fp)); extern int __sflush __P((FILE *)); extern FILE *__sfp __P((void)); diff --git a/lib/libc/stdio/rewind.c b/lib/libc/stdio/rewind.c index c4de2c1..af9232a 100644 --- a/lib/libc/stdio/rewind.c +++ b/lib/libc/stdio/rewind.c @@ -52,9 +52,13 @@ static const char rcsid[] = void rewind(FILE *fp) { + /* make sure stdio is set up */ + if (!__sdidinit) + __sinit(); + FLOCKFILE(fp); - (void) _fseeko(fp, (off_t)0, SEEK_SET); - clearerr(fp); + if (_fseeko(fp, (off_t)0, SEEK_SET, 1) == 0) + clearerr_unlocked(fp); FUNLOCKFILE(fp); - errno = 0; /* not required, but seems reasonable */ + /* errno required by POSIX to sense error, don't zero it here */ } |