diff options
author | Simon J. Gerraty <sjg@FreeBSD.org> | 2014-08-19 06:50:54 +0000 |
---|---|---|
committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2014-08-19 06:50:54 +0000 |
commit | ee7b0571c2c18bdec848ed2044223cc88db29bd8 (patch) | |
tree | b04f4bd7cd887f50e7d98af35f46b9834ff86c80 /lib/libc/stdio | |
parent | ffda191e301f128a62c152fde92b692548367fca (diff) | |
parent | 15fc2873832ea5b9b639e701bbbf2e73af8b6a88 (diff) | |
download | src-ee7b0571c2c18bdec848ed2044223cc88db29bd8.tar.gz src-ee7b0571c2c18bdec848ed2044223cc88db29bd8.zip |
Notes
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r-- | lib/libc/stdio/fflush.c | 25 | ||||
-rw-r--r-- | lib/libc/stdio/fmemopen.c | 17 | ||||
-rw-r--r-- | lib/libc/stdio/fopen.3 | 9 | ||||
-rw-r--r-- | lib/libc/stdio/fputs.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/fputws.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/freopen.c | 10 | ||||
-rw-r--r-- | lib/libc/stdio/ftell.c | 18 | ||||
-rw-r--r-- | lib/libc/stdio/gets.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/printf.3 | 4 | ||||
-rw-r--r-- | lib/libc/stdio/puts.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/putw.c | 2 | ||||
-rw-r--r-- | lib/libc/stdio/rewind.c | 5 | ||||
-rw-r--r-- | lib/libc/stdio/vfprintf.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/vfwprintf.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/wbuf.c | 5 |
15 files changed, 81 insertions, 32 deletions
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index 456b031dd01b..ef9b45b8b6f1 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -60,7 +60,7 @@ fflush(FILE *fp) /* * There is disagreement about the correct behaviour of fflush() - * when passed a file which is not open for reading. According to + * when passed a file which is not open for writing. According to * the ISO C standard, the behaviour is undefined. * Under linux, such an fflush returns success and has no effect; * under Windows, such an fflush is documented as behaving instead @@ -68,11 +68,13 @@ fflush(FILE *fp) * Given that applications may be written with the expectation of * either of these two behaviours, the only safe (non-astonishing) * option is to return EBADF and ask that applications be fixed. + * SUSv3 now requires that fflush() returns success on a read-only + * stream. + * */ - if ((fp->_flags & (__SWR | __SRW)) == 0) { - errno = EBADF; - retval = EOF; - } else + if ((fp->_flags & (__SWR | __SRW)) == 0) + retval = 0; + else retval = __sflush(fp); FUNLOCKFILE(fp); return (retval); @@ -89,10 +91,9 @@ __fflush(FILE *fp) if (fp == NULL) return (_fwalk(sflush_locked)); - if ((fp->_flags & (__SWR | __SRW)) == 0) { - errno = EBADF; - retval = EOF; - } else + if ((fp->_flags & (__SWR | __SRW)) == 0) + retval = 0; + else retval = __sflush(fp); return (retval); } @@ -122,6 +123,12 @@ __sflush(FILE *fp) for (; n > 0; n -= t, p += t) { t = _swrite(fp, (char *)p, n); if (t <= 0) { + /* Reset _p and _w. */ + if (p > fp->_p) /* Some was written. */ + memmove(fp->_p, p, n); + fp->_p += n; + if ((fp->_flags & (__SLBF | __SNBF)) == 0) + fp->_w -= n; fp->_flags |= __SERR; return (EOF); } diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c index 581a91efd73b..ebd3596be775 100644 --- a/lib/libc/stdio/fmemopen.c +++ b/lib/libc/stdio/fmemopen.c @@ -57,6 +57,14 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode) int flags, rc; /* + * POSIX says we shall return EINVAL if size is 0. + */ + if (size == 0) { + errno = EINVAL; + return (NULL); + } + + /* * Retrieve the flags as used by open(2) from the mode argument, and * validate them. */ @@ -119,14 +127,7 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode) */ switch (mode[0]) { case 'a': - if (ck->bin) { - /* - * This isn't useful, since the buffer isn't allowed - * to grow. - */ - ck->off = ck->len = size; - } else - ck->off = ck->len = strnlen(ck->buf, ck->size); + ck->off = ck->len = strnlen(ck->buf, ck->size); break; case 'r': ck->len = size; diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3 index f11f4e07e3de..b39cb5a0d504 100644 --- a/lib/libc/stdio/fopen.3 +++ b/lib/libc/stdio/fopen.3 @@ -302,6 +302,15 @@ for any of the errors specified for the routines .Xr fclose 3 and .Xr fflush 3 . +.Pp +The +.Fn fmemopen +function +may also fail and set +.Va errno +if the +.Fa size +argument is 0. .Sh SEE ALSO .Xr open 2 , .Xr fclose 3 , diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c index 3b8f2c9d1b68..32e57645f56a 100644 --- a/lib/libc/stdio/fputs.c +++ b/lib/libc/stdio/fputs.c @@ -55,7 +55,7 @@ fputs(const char * __restrict s, FILE * __restrict fp) struct __siov iov; iov.iov_base = (void *)s; - iov.iov_len = uio.uio_resid = strlen(s); + uio.uio_resid = iov.iov_len = strlen(s); uio.uio_iov = &iov; uio.uio_iovcnt = 1; FLOCKFILE(fp); diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c index fa8d31784e09..41530673c007 100644 --- a/lib/libc/stdio/fputws.c +++ b/lib/libc/stdio/fputws.c @@ -67,7 +67,7 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) &fp->_mbstate); if (nbytes == (size_t)-1) goto error; - iov.iov_len = uio.uio_resid = nbytes; + uio.uio_resid = iov.iov_len = nbytes; if (__sfvwrite(fp, &uio) != 0) goto error; } while (wsp != NULL); diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index 0ff83bf96175..4dcd50fbb13d 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -97,7 +97,7 @@ freopen(const char * __restrict file, const char * __restrict mode, (dflags & (O_ACCMODE | O_EXEC)) != (oflags & O_ACCMODE)) { fclose(fp); FUNLOCKFILE(fp); - errno = EINVAL; + errno = EBADF; return (NULL); } if (fp->_flags & __SWR) @@ -151,6 +151,14 @@ freopen(const char * __restrict file, const char * __restrict mode, /* Get a new descriptor to refer to the new file. */ f = _open(file, oflags, DEFFILEMODE); + /* If out of fd's close the old one and try again. */ + if (f < 0 && isopen && wantfd > STDERR_FILENO && + (errno == ENFILE || errno == EMFILE)) { + (void) (*fp->_close)(fp->_cookie); + isopen = 0; + wantfd = -1; + f = _open(file, oflags, DEFFILEMODE); + } sverrno = errno; finish: diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index 2c8800ccfe19..745d500513d9 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <sys/types.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdio.h> #include "un-namespace.h" @@ -87,6 +88,7 @@ _ftello(FILE *fp, fpos_t *offset) { fpos_t pos; size_t n; + int dflags; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ @@ -118,6 +120,22 @@ _ftello(FILE *fp, fpos_t *offset) if (HASUB(fp)) pos -= fp->_r; /* Can be negative at this point. */ } else if ((fp->_flags & __SWR) && fp->_p != NULL) { + dflags = 0; + if (fp->_flags & __SAPP) + dflags = O_APPEND; + else if (fp->_file != -1 && + (dflags = _fcntl(fp->_file, F_GETFL)) < 0) + return (1); + if ((dflags & O_APPEND) && + (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) { + if ((fp->_flags & __SOPT) || __sflush(fp) || + (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1) + return (1); + else { + *offset = pos; + return (0); + } + } /* * Writing. Any buffered characters cause the * position to be greater than that in the diff --git a/lib/libc/stdio/gets.c b/lib/libc/stdio/gets.c index c7c1c2fa38c8..c9438515323a 100644 --- a/lib/libc/stdio/gets.c +++ b/lib/libc/stdio/gets.c @@ -52,7 +52,7 @@ gets(char *buf) int c; char *s; static int warned; - static char w[] = + static const char w[] = "warning: this program uses gets(), which is unsafe.\n"; FLOCKFILE(stdin); diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3 index 05c30dcfb523..058f9a9f7d67 100644 --- a/lib/libc/stdio/printf.3 +++ b/lib/libc/stdio/printf.3 @@ -827,14 +827,14 @@ first appeared in the .Tn GNU C library. These were implemented by -.An Peter Wemm Aq peter@FreeBSD.org +.An Peter Wemm Aq Mt peter@FreeBSD.org in .Fx 2.2 , but were later replaced with a different implementation from .Ox 2.3 by -.An Todd C. Miller Aq Todd.Miller@courtesan.com . +.An Todd C. Miller Aq Mt Todd.Miller@courtesan.com . The .Fn dprintf and diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c index 5ee7fc1c63f0..124afc73d600 100644 --- a/lib/libc/stdio/puts.c +++ b/lib/libc/stdio/puts.c @@ -51,12 +51,12 @@ int puts(char const *s) { int retval; - size_t c = strlen(s); + size_t c; struct __suio uio; struct __siov iov[2]; iov[0].iov_base = (void *)s; - iov[0].iov_len = c; + iov[0].iov_len = c = strlen(s); iov[1].iov_base = "\n"; iov[1].iov_len = 1; uio.uio_resid = c + 1; diff --git a/lib/libc/stdio/putw.c b/lib/libc/stdio/putw.c index 0360cafc4052..ecd5d095de5e 100644 --- a/lib/libc/stdio/putw.c +++ b/lib/libc/stdio/putw.c @@ -50,7 +50,7 @@ putw(int w, FILE *fp) struct __siov iov; iov.iov_base = &w; - iov.iov_len = uio.uio_resid = sizeof(w); + uio.uio_resid = iov.iov_len = sizeof(w); uio.uio_iov = &iov; uio.uio_iovcnt = 1; FLOCKFILE(fp); diff --git a/lib/libc/stdio/rewind.c b/lib/libc/stdio/rewind.c index ff4c9072c76b..133e3f43dd0c 100644 --- a/lib/libc/stdio/rewind.c +++ b/lib/libc/stdio/rewind.c @@ -53,9 +53,8 @@ rewind(FILE *fp) __sinit(); FLOCKFILE(fp); - if (_fseeko(fp, (off_t)0, SEEK_SET, 1) == 0) { - clearerr_unlocked(fp); + if (_fseeko(fp, (off_t)0, SEEK_SET, 1) == 0) errno = serrno; - } + clearerr_unlocked(fp); /* POSIX: clear stdio error regardless */ FUNLOCKFILE(fp); } diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index ea47d36ea14a..e54e8acf00ff 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -455,8 +455,10 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) return (__xvprintf(fp, fmt0, ap)); /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ - if (prepwrite(fp) != 0) + if (prepwrite(fp) != 0) { + errno = EBADF; return (EOF); + } convbuf = NULL; fmt = (char *)fmt0; diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index 4350c48acafc..b75c504b1e72 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -531,8 +531,10 @@ __vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */ - if (prepwrite(fp) != 0) + if (prepwrite(fp) != 0) { + errno = EBADF; return (EOF); + } convbuf = NULL; fmt = (wchar_t *)fmt0; diff --git a/lib/libc/stdio/wbuf.c b/lib/libc/stdio/wbuf.c index 3f697e287a1f..5bc3c4dc3e77 100644 --- a/lib/libc/stdio/wbuf.c +++ b/lib/libc/stdio/wbuf.c @@ -36,6 +36,7 @@ static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <errno.h> #include <stdio.h> #include "local.h" @@ -59,8 +60,10 @@ __swbuf(int c, FILE *fp) * calls might wrap _w from negative to positive. */ fp->_w = fp->_lbfsize; - if (prepwrite(fp) != 0) + if (prepwrite(fp) != 0) { + errno = EBADF; return (EOF); + } c = (unsigned char)c; ORIENT(fp, -1); |