aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/stdio
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
commitee7b0571c2c18bdec848ed2044223cc88db29bd8 (patch)
treeb04f4bd7cd887f50e7d98af35f46b9834ff86c80 /lib/libc/stdio
parentffda191e301f128a62c152fde92b692548367fca (diff)
parent15fc2873832ea5b9b639e701bbbf2e73af8b6a88 (diff)
downloadsrc-ee7b0571c2c18bdec848ed2044223cc88db29bd8.tar.gz
src-ee7b0571c2c18bdec848ed2044223cc88db29bd8.zip
Notes
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/fflush.c25
-rw-r--r--lib/libc/stdio/fmemopen.c17
-rw-r--r--lib/libc/stdio/fopen.39
-rw-r--r--lib/libc/stdio/fputs.c2
-rw-r--r--lib/libc/stdio/fputws.c2
-rw-r--r--lib/libc/stdio/freopen.c10
-rw-r--r--lib/libc/stdio/ftell.c18
-rw-r--r--lib/libc/stdio/gets.c2
-rw-r--r--lib/libc/stdio/printf.34
-rw-r--r--lib/libc/stdio/puts.c4
-rw-r--r--lib/libc/stdio/putw.c2
-rw-r--r--lib/libc/stdio/rewind.c5
-rw-r--r--lib/libc/stdio/vfprintf.c4
-rw-r--r--lib/libc/stdio/vfwprintf.c4
-rw-r--r--lib/libc/stdio/wbuf.c5
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);