summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/fseek.c
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2001-09-02 19:10:10 +0000
committerache <ache@FreeBSD.org>2001-09-02 19:10:10 +0000
commit245c459c3f4dcbc6da4c66aebc8879251e9af682 (patch)
treebe15c0be354e09f766522b411a1ad2af5d566a99 /lib/libc/stdio/fseek.c
parentb3ac07522908287b53a4f7e77f2e5205c4f72fb7 (diff)
downloadFreeBSD-src-245c459c3f4dcbc6da4c66aebc8879251e9af682.zip
FreeBSD-src-245c459c3f4dcbc6da4c66aebc8879251e9af682.tar.gz
Move all stdio internal flags processing and setting out of __sread(),
__swrite() and __sseek() to higher level. According to funopen(3) they all are just wrappers to something like standard read(2), write(2) and lseek(2), i.e. must not touch stdio internals because they are replaceable with any other functions knows nothing about stdio internals. See example of funopen(3) usage in sendmail sources f.e. NOTE: this is original stdio bug, not result of my range checkin added.
Diffstat (limited to 'lib/libc/stdio/fseek.c')
-rw-r--r--lib/libc/stdio/fseek.c44
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);
+}
OpenPOWER on IntegriCloud