diff options
Diffstat (limited to 'lib/libc/stdio/fseek.c')
-rw-r--r-- | lib/libc/stdio/fseek.c | 44 |
1 files changed, 41 insertions, 3 deletions
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); +} |