X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/3d9156a7a519a5e3aa1b92e9d9d4b991f1aed7ff..aa54d2fad3d9038b43475aa93c76795c5141a993:/stdio/FreeBSD/fflush.c?ds=sidebyside diff --git a/stdio/FreeBSD/fflush.c b/stdio/FreeBSD/fflush.c index 59da908..db6761d 100644 --- a/stdio/FreeBSD/fflush.c +++ b/stdio/FreeBSD/fflush.c @@ -13,10 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -38,11 +34,12 @@ static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.13 2004/07/04 20:17:00 cperciva Exp $"); +__FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.14 2007/01/09 00:28:06 imp Exp $"); #include "namespace.h" #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -56,28 +53,14 @@ static int sflush_locked(FILE *); int fflush(FILE *fp) { - int retval; + int retval = 0; - if (fp == NULL) + if (fp == NULL) { return (_fwalk(sflush_locked)); - FLOCKFILE(fp); + } - /* - * There is disagreement about the correct behaviour of fflush() - * when passed a file which is not open for reading. 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 - * as fpurge(). - * 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. - */ - if ((fp->_flags & (__SWR | __SRW)) == 0) { - errno = EBADF; - retval = EOF; - } else - retval = __sflush(fp); + FLOCKFILE(fp); + retval = __sflush(fp); FUNLOCKFILE(fp); return (retval); } @@ -94,8 +77,7 @@ __fflush(FILE *fp) if (fp == NULL) return (_fwalk(sflush_locked)); if ((fp->_flags & (__SWR | __SRW)) == 0) { - errno = EBADF; - retval = EOF; + retval = 0; } else retval = __sflush(fp); return (retval); @@ -108,26 +90,77 @@ __sflush(FILE *fp) int n, t; t = fp->_flags; - if ((t & __SWR) == 0) - return (0); if ((p = fp->_bf._base) == NULL) return (0); - n = fp->_p - p; /* write this much */ - /* - * Set these immediately to avoid problems with longjmp and to allow - * exchange buffering (via setvbuf) in user write function. + * SUSv3 requires that fflush() on a seekable input stream updates the file + * position indicator with the underlying seek function. Use a dumb fseek + * for this (don't attempt to preserve the buffers). */ - fp->_p = p; - fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; - - for (; n > 0; n -= t, p += t) { - t = _swrite(fp, (char *)p, n); - if (t <= 0) { - fp->_flags |= __SERR; - return (EOF); + if ((t & __SRD) != 0) { + if (fp->_seek == NULL) { + /* + * No way to seek this file -- just return "success." + */ + return (0); + } + + n = fp->_r; + + if (n > 0) { + /* + * See _fseeko's dumb path. + */ + if (_sseek(fp, (fpos_t)-n, SEEK_CUR) == -1) { + if (errno == ESPIPE) { + /* + * Ignore ESPIPE errors, since there's no way to put the bytes + * back into the pipe. + */ + return (0); + } + return (EOF); + } + + if (HASUB(fp)) { + FREEUB(fp); + } + fp->_p = fp->_bf._base; + fp->_r = 0; + fp->_flags &= ~__SEOF; + memset(&fp->_mbstate, 0, sizeof(mbstate_t)); + } + return (0); + } + + if ((t & __SWR) != 0) { + n = fp->_p - p; /* write this much */ + + /* + * Set these immediately to avoid problems with longjmp and to allow + * exchange buffering (via setvbuf) in user write function. + */ + fp->_p = p; + fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size; + + for (; n > 0; n -= t, p += t) { + t = _swrite(fp, (char *)p, n); + if (t <= 0) { + /* 5340694: reset _p and _w on EAGAIN */ + if (t < 0 && errno == EAGAIN) { + if (p > fp->_p) { + /* some was written */ + memmove(fp->_p, p, n); + fp->_p += n; + if (!(fp->_flags & (__SLBF|__SNBF))) + fp->_w -= n; + } + } + fp->_flags |= __SERR; + return (EOF); + } } } return (0);