summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/fdopen.c4
-rw-r--r--lib/libc/stdio/fflush.c6
-rw-r--r--lib/libc/stdio/fopen.c2
-rw-r--r--lib/libc/stdio/fseek.c44
-rw-r--r--lib/libc/stdio/ftell.c2
-rw-r--r--lib/libc/stdio/fvwrite.c27
-rw-r--r--lib/libc/stdio/local.h1
-rw-r--r--lib/libc/stdio/refill.c9
-rw-r--r--lib/libc/stdio/stdio.c49
9 files changed, 89 insertions, 55 deletions
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c
index 2e72e71..30bf5b9 100644
--- a/lib/libc/stdio/fdopen.c
+++ b/lib/libc/stdio/fdopen.c
@@ -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;
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index 5c1eaa1..55a6a2a 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -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);
}
diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c
index f09fe8a..709316d 100644
--- a/lib/libc/stdio/fopen.c
+++ b/lib/libc/stdio/fopen.c
@@ -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);
}
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);
+}
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c
index e355a20..174eaa8 100644
--- a/lib/libc/stdio/ftell.c
+++ b/lib/libc/stdio/ftell.c
@@ -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);
}
diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c
index 82a49cb..efcfffb 100644
--- a/lib/libc/stdio/fvwrite.c
+++ b/lib/libc/stdio/fvwrite.c
@@ -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;
diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h
index d37a540..e074273 100644
--- a/lib/libc/stdio/local.h
+++ b/lib/libc/stdio/local.h
@@ -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));
diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c
index fa46d78..2d30e81 100644
--- a/lib/libc/stdio/refill.c
+++ b/lib/libc/stdio/refill.c
@@ -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);
}
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
index ea8a4c1..b4bf299 100644
--- a/lib/libc/stdio/stdio.c
+++ b/lib/libc/stdio/stdio.c
@@ -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
OpenPOWER on IntegriCloud