summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2001-09-01 01:56:54 +0000
committerache <ache@FreeBSD.org>2001-09-01 01:56:54 +0000
commit5610a6ae63a163468769d8b1400a386115b53ddf (patch)
tree7df1c1e8cadd1748528a154d73547f9a81702dae
parent8f95e37de3db8c34682949479172b82e88dbacc5 (diff)
downloadFreeBSD-src-5610a6ae63a163468769d8b1400a386115b53ddf.zip
FreeBSD-src-5610a6ae63a163468769d8b1400a386115b53ddf.tar.gz
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.
-rw-r--r--lib/libc/stdio/fseek.c29
-rw-r--r--lib/libc/stdio/ftell.c40
-rw-r--r--lib/libc/stdio/local.h4
-rw-r--r--lib/libc/stdio/ungetc.35
-rw-r--r--lib/libc/stdio/ungetc.c4
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;
/*
OpenPOWER on IntegriCloud