Index: lib/libc/stdio/fgetln.3 =================================================================== --- lib/libc/stdio/fgetln.3 +++ lib/libc/stdio/fgetln.3 @@ -97,6 +97,9 @@ The argument .Fa stream is not a stream open for reading. +.It Bq Er ENOMEM +The internal line buffer could not be expanded due to lack of available memory, +or because it would need to expand beyond INT_MAX in size. .El .Pp The Index: lib/libc/stdio/fgetln.c =================================================================== --- lib/libc/stdio/fgetln.c +++ lib/libc/stdio/fgetln.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" +#include +#include #include #include #include @@ -61,6 +63,10 @@ #endif if (fp->_lb._size >= newsize) return (0); + if (newsize > INT_MAX) { + errno = ENOMEM; + return (-1); + } if ((p = realloc(fp->_lb._base, newsize)) == NULL) return (-1); fp->_lb._base = p; @@ -159,6 +165,7 @@ error: *lenp = 0; /* ??? */ + fp->_flags |= __SERR; FUNLOCKFILE(fp); return (NULL); /* ??? */ } Index: lib/libc/stdio/fputs.c =================================================================== --- lib/libc/stdio/fputs.c +++ lib/libc/stdio/fputs.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" +#include #include #include #include "un-namespace.h" @@ -62,5 +63,7 @@ ORIENT(fp, -1); retval = __sfvwrite(fp, &uio); FUNLOCKFILE(fp); + if (retval == 0) + return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len); return (retval); } Index: lib/libc/stdio/freopen.c =================================================================== --- lib/libc/stdio/freopen.c +++ lib/libc/stdio/freopen.c @@ -132,6 +132,7 @@ * descriptor (if any) was associated with it. If it was attached to * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin) * should work. This is unnecessary if it was not a Unix file. + * For UNIX03, we always close if it was open. */ if (fp->_flags == 0) { fp->_flags = __SEOF; /* hold on to it */ @@ -142,15 +143,22 @@ if (fp->_flags & __SWR) (void) __sflush(fp); /* if close is NULL, closing is a no-op, hence pointless */ - isopen = fp->_close != NULL; - if ((wantfd = fp->_file) < 0 && isopen) { + if (fp->_close) (void) (*fp->_close)(fp->_cookie); - isopen = 0; - } + isopen = 0; + wantfd = -1; } /* Get a new descriptor to refer to the new file. */ f = _open(file, oflags, DEFFILEMODE); + if (f < 0 && isopen) { + /* If out of fd's close the old one and try again. */ + if (errno == ENFILE || errno == EMFILE) { + (void) (*fp->_close)(fp->_cookie); + isopen = 0; + f = _open(file, oflags, DEFFILEMODE); + } + } sverrno = errno; finish: @@ -158,11 +166,9 @@ * Finish closing fp. Even if the open succeeded above, we cannot * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. - * - * Leave the existing file descriptor open until dup2() is called - * below to avoid races where a concurrent open() in another thread - * could claim the existing descriptor. */ + if (isopen) + (void) (*fp->_close)(fp->_cookie); if (fp->_flags & __SMBF) free((char *)fp->_bf._base); fp->_w = 0; @@ -181,8 +187,6 @@ memset(&fp->_mbstate, 0, sizeof(mbstate_t)); if (f < 0) { /* did not get it after all */ - if (isopen) - (void) (*fp->_close)(fp->_cookie); fp->_flags = 0; /* set it free */ FUNLOCKFILE(fp); errno = sverrno; /* restore in case _close clobbered */ @@ -194,13 +198,12 @@ * to maintain the descriptor. Various C library routines (perror) * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ - if (wantfd >= 0) { + if (wantfd >= 0 && f != wantfd) { if ((oflags & O_CLOEXEC ? _fcntl(f, F_DUP2FD_CLOEXEC, wantfd) : _dup2(f, wantfd)) >= 0) { (void)_close(f); f = wantfd; - } else - (void)_close(fp->_file); + } } /*