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.
This commit is contained in:
parent
8f95e37de3
commit
5610a6ae63
@ -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,9 +211,16 @@ _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
|
||||
@ -220,28 +228,29 @@ _fseeko(fp, offset, whence, ltest)
|
||||
* 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;
|
||||
|
||||
|
@ -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 @@ _ftello(fp)
|
||||
* 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 @@ _ftello(fp)
|
||||
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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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 ,
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user