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.
This commit is contained in:
Andrey A. Chernov 2001-09-02 19:10:10 +00:00
parent 9c552a1fd7
commit 924888f977
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=82807
9 changed files with 89 additions and 55 deletions

View File

@ -78,8 +78,8 @@ fdopen(fd, mode)
fp->_flags = flags;
/*
* If opened for appending, but underlying descriptor does not have
* O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
* end before each write.
* O_APPEND bit set, assert __SAPP so that __swrite() caller
* will _sseek() to the end before write.
*/
if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
fp->_flags |= __SAPP;

View File

@ -113,9 +113,15 @@ __sflush(FILE *fp)
fp->_p = p;
fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
if (n <= 0)
return (0);
if ((fp->_flags & __SAPP) && _sseek(fp, (fpos_t)0, SEEK_END) == -1)
goto err;
fp->_flags &= ~__SOFF; /* In case FAPPEND mode is set. */
for (; n > 0; n -= t, p += t) {
t = (*fp->_write)(fp->_cookie, (char *)p, n);
if (t <= 0) {
err:
fp->_flags |= __SERR;
return (EOF);
}

View File

@ -85,6 +85,6 @@ fopen(file, mode)
* fseek and ftell.)
*/
if (oflags & O_APPEND)
(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
(void)_sseek(fp, (fpos_t)0, SEEK_END);
return (fp);
}

View File

@ -274,7 +274,7 @@ _fseeko(fp, offset, whence, ltest)
* 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 @@ _fseeko(fp, offset, whence, ltest)
* 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 @@ _fseeko(fp, offset, whence, ltest)
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);
}

View File

@ -110,7 +110,7 @@ _ftello(fp, offset)
if (fp->_flags & __SOFF)
pos = fp->_offset;
else {
pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
if (pos == -1)
return (1);
}

View File

@ -64,7 +64,7 @@ __sfvwrite(fp, uio)
register struct __siov *iov;
register int w, s;
char *nl;
int nlknown, nldist;
int nlknown, nldist, firsttime;
if ((len = uio->uio_resid) == 0)
return (0);
@ -86,12 +86,21 @@ __sfvwrite(fp, uio)
len = iov->iov_len; \
iov++; \
}
firsttime = 1;
if (fp->_flags & __SNBF) {
/*
* Unbuffered: write up to BUFSIZ bytes at a time.
*/
do {
GETIOV(;);
if (firsttime) {
if ((fp->_flags & __SAPP) &&
_sseek(fp, (fpos_t)0, SEEK_END) == -1)
goto err;
/* In case FAPPEND mode is set. */
fp->_flags &= ~__SOFF;
firsttime = 0;
}
w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
if (w <= 0)
goto err;
@ -147,6 +156,14 @@ __sfvwrite(fp, uio)
goto err;
} else if (len >= (w = fp->_bf._size)) {
/* write directly */
if (firsttime) {
if ((fp->_flags & __SAPP) &&
_sseek(fp, (fpos_t)0, SEEK_END) == -1)
goto err;
/* In case FAPPEND mode is set. */
fp->_flags &= ~__SOFF;
firsttime = 0;
}
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
goto err;
@ -186,6 +203,14 @@ __sfvwrite(fp, uio)
if (__fflush(fp))
goto err;
} else if (s >= (w = fp->_bf._size)) {
if (firsttime) {
if ((fp->_flags & __SAPP) &&
_sseek(fp, (fpos_t)0, SEEK_END) == -1)
goto err;
/* In case FAPPEND mode is set. */
fp->_flags &= ~__SOFF;
firsttime = 0;
}
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
goto err;

View File

@ -46,6 +46,7 @@
* in particular, macros and private variables.
*/
extern fpos_t _sseek __P((FILE *, fpos_t, int));
extern int _ftello __P((FILE *, fpos_t *));
extern int _fseeko __P((FILE *, off_t, int, int));
extern int __fflush __P((FILE *fp));

View File

@ -44,6 +44,7 @@ static const char rcsid[] =
#include "namespace.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "un-namespace.h"
@ -141,10 +142,18 @@ __srefill(FILE *fp)
if (fp->_r == 0)
fp->_flags |= __SEOF;
else {
err:
fp->_r = 0;
fp->_flags |= __SERR;
fp->_flags &= ~__SOFF;
}
return (EOF);
} else if (fp->_flags & __SOFF) {
if (fp->_offset > OFF_MAX - fp->_r) {
errno = EOVERFLOW;
goto err;
} else
fp->_offset += fp->_r;
}
return (0);
}

View File

@ -45,7 +45,6 @@ static const char rcsid[] =
#include "namespace.h"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include "un-namespace.h"
@ -53,7 +52,6 @@ static const char rcsid[] =
/*
* Small standard I/O/seek/close functions.
* These maintain the `known seek offset' for seek optimisation.
*/
int
__sread(cookie, buf, n)
@ -62,24 +60,8 @@ __sread(cookie, buf, n)
int n;
{
register FILE *fp = cookie;
register int ret;
ret = _read(fp->_file, buf, (size_t)n);
/* if the read succeeded, update the current offset */
if (ret >= 0) {
if (fp->_flags & __SOFF) {
if (fp->_offset > OFF_MAX - ret) {
errno = EOVERFLOW;
ret = -1;
} else {
fp->_offset += ret;
return (ret);
}
} else
return (ret);
}
fp->_flags &= ~__SOFF;
return (ret);
return(_read(fp->_file, buf, (size_t)n));
}
int
@ -90,9 +72,6 @@ __swrite(cookie, buf, n)
{
register FILE *fp = cookie;
if (fp->_flags & __SAPP)
(void) lseek(fp->_file, (off_t)0, SEEK_END);
fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */
return (_write(fp->_file, buf, (size_t)n));
}
@ -103,32 +82,8 @@ __sseek(cookie, offset, whence)
int whence;
{
register FILE *fp = cookie;
register off_t ret;
int serrno, errret;
serrno = errno;
errno = 0;
ret = lseek(fp->_file, (off_t)offset, whence);
errret = errno;
if (errno == 0)
errno = serrno;
/*
* Disallow negative seeks per POSIX.
* It is needed here to help upper level caller
* (fseek) 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);
return (lseek(fp->_file, (off_t)offset, whence));
}
int