From 5610a6ae63a163468769d8b1400a386115b53ddf Mon Sep 17 00:00:00 2001 From: ache Date: Sat, 1 Sep 2001 01:56:54 +0000 Subject: Back out disabling ungetc() at 0, use different solution: keep negative offset internally, but return 0 externally in ftell*() I.e. use 0 now as 'unspecified value' per POSIX ungetc() description. --- lib/libc/stdio/fseek.c | 29 +++++++++++++++++++---------- lib/libc/stdio/ftell.c | 40 ++++++++++++++++++++++++++-------------- lib/libc/stdio/local.h | 4 ++-- lib/libc/stdio/ungetc.3 | 5 +---- lib/libc/stdio/ungetc.c | 4 ---- 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c index 7cf117a..a3c80c1 100644 --- a/lib/libc/stdio/fseek.c +++ b/lib/libc/stdio/fseek.c @@ -129,9 +129,10 @@ _fseeko(fp, offset, whence, ltest) * we have to first find the current stream offset via * ftell (see ftell for details). */ - if ((curoff = _ftello(fp)) == -1) + if (_ftello(fp, &curoff)) return (-1); - if (offset > 0 && curoff > OFF_MAX - offset) { + if ((offset > 0 && curoff > OFF_MAX - offset) || + (offset < 0 && curoff < OFF_MIN - offset)) { errno = EOVERFLOW; return (-1); } @@ -210,38 +211,46 @@ _fseeko(fp, offset, whence, ltest) } } - if (!havepos && (curoff = _ftello(fp)) == -1) + if (!havepos && _ftello(fp, &curoff)) goto dumb; /* + * (If the buffer was modified, we have to + * skip this; see fgetln.c.) + */ + if (fp->_flags & __SMOD) + goto abspos; + + /* * Compute the number of bytes in the input buffer (pretending * that any ungetc() input has been discarded). Adjust current * offset backwards by this count so that it represents the * file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { - if (curoff > OFF_MAX - fp->_r) + if (curoff > 0 && fp->_r > OFF_MAX - curoff) goto abspos; curoff += fp->_r; /* kill off ungetc */ n = fp->_extra->_up - fp->_bf._base; + if (curoff < 0 && -((off_t)n) < OFF_MIN - curoff) + goto abspos; curoff -= n; n += fp->_ur; } else { n = fp->_p - fp->_bf._base; + if (curoff < 0 && -((off_t)n) < OFF_MIN - curoff) + goto abspos; curoff -= n; n += fp->_r; } - /* curoff can be negative at this point. */ /* * If the target offset is within the current buffer, * simply adjust the pointers, clear EOF, undo ungetc(), - * and return. (If the buffer was modified, we have to - * skip this; see fgetln.c.) + * and return. */ - if ((fp->_flags & __SMOD) == 0 && - target >= curoff && - (curoff <= 0 || curoff <= OFF_MAX - n) && + if (target >= curoff && + (curoff <= 0 || n <= OFF_MAX - curoff) && target < curoff + n) { size_t o = target - curoff; diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index 61cd27c..a0fd175 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -75,28 +75,34 @@ off_t ftello(fp) register FILE *fp; { - register off_t rv; + fpos_t rv; + int ret; /* make sure stdio is set up */ if (!__sdidinit) __sinit(); FLOCKFILE(fp); - rv = _ftello(fp); + ret = _ftello(fp, &rv); FUNLOCKFILE(fp); + if (ret) + return (-1); + if (rv < 0) /* Unspecified value because of ungetc() at 0 */ + rv = 0; return (rv); } -off_t -_ftello(fp) +int +_ftello(fp, offset) register FILE *fp; + fpos_t *offset; { register fpos_t pos, spos; size_t n; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ - return (-1); + return (1); } /* @@ -110,7 +116,7 @@ _ftello(fp) get_real_pos: spos = pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR); if (pos == -1) - return (-1); + return (1); } if (fp->_flags & __SRD) { /* @@ -118,16 +124,21 @@ get_real_pos: * those from ungetc) cause the position to be * smaller than that in the underlying object. */ - if ((pos -= fp->_r) < 0 || - (HASUB(fp) && (pos -= fp->_ur) < 0)) { - fp->_p = fp->_bf._base; - fp->_r = 0; - if (HASUB(fp)) - FREEUB(fp); + if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) { + /* Lost position, resync. */ + if (HASUB(fp)) { + fp->_extra->_up = fp->_bf._base; + fp->_ur = 0; + } else { + fp->_p = fp->_bf._base; + fp->_r = 0; + } if (spos == -1) goto get_real_pos; pos = spos; } + if (HASUB(fp)) + pos -= fp->_r; /* Can be negative at this point. */ } else if ((fp->_flags & __SWR) && fp->_p != NULL) { /* * Writing. Any buffered characters cause the @@ -137,9 +148,10 @@ get_real_pos: n = fp->_p - fp->_bf._base; if (pos > OFF_MAX - n) { errno = EOVERFLOW; - return (-1); + return (1); } pos += n; } - return (pos); + *offset = pos; + return (0); } diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index 00ec2d8..d37a540 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -46,8 +46,8 @@ * in particular, macros and private variables. */ -extern off_t _ftello __P((FILE *)); -extern int _fseeko __P((FILE *, off_t, int, int)); +extern int _ftello __P((FILE *, fpos_t *)); +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/ungetc.3 b/lib/libc/stdio/ungetc.3 index 6d657a8..83483be 100644 --- a/lib/libc/stdio/ungetc.3 +++ b/lib/libc/stdio/ungetc.3 @@ -83,10 +83,7 @@ if the operation fails. If the value of the argument .Fa c character equals -.Dv EOF -or current -.Fa stream -offset equals 0, +.Dv EOF , the operation will fail and the stream will remain unchanged. .Sh SEE ALSO .Xr fseek 3 , diff --git a/lib/libc/stdio/ungetc.c b/lib/libc/stdio/ungetc.c index 092debd..f70fb42 100644 --- a/lib/libc/stdio/ungetc.c +++ b/lib/libc/stdio/ungetc.c @@ -132,10 +132,6 @@ __ungetc(int c, FILE *fp) } fp->_flags |= __SRD; } - - if (!(fp->_flags & __SSTR) && _ftello(fp) == 0) - return (EOF); - c = (unsigned char)c; /* -- cgit v1.1