X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/3d9156a7a519a5e3aa1b92e9d9d4b991f1aed7ff..507116e319a1470bb0a5040d4d23e5c76955ef97:/stdio/FreeBSD/freopen.c?ds=sidebyside diff --git a/stdio/FreeBSD/freopen.c b/stdio/FreeBSD/freopen.c index ddd978e..b401304 100644 --- a/stdio/FreeBSD/freopen.c +++ b/stdio/FreeBSD/freopen.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,13 +34,14 @@ static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.13 2004/05/22 15:19:41 tjr Exp $"); +__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.21 2008/04/17 22:17:54 jhb Exp $"); #include "namespace.h" #include #include #include #include +#include #include #include #include @@ -67,15 +64,16 @@ freopen(file, mode, fp) int dflags, flags, isopen, oflags, sverrno, wantfd; if ((flags = __sflags(mode, &oflags)) == 0) { + sverrno = errno; (void) fclose(fp); + errno = sverrno; return (NULL); } + pthread_once(&__sdidinit, __sinit); + FLOCKFILE(fp); - if (!__sdidinit) - __sinit(); - /* * If the filename is a NULL pointer, the caller is asking us to * re-open the same file with a different mode. We allow this only @@ -99,9 +97,11 @@ freopen(file, mode, fp) (oflags & O_ACCMODE)) { fclose(fp); FUNLOCKFILE(fp); - errno = EINVAL; + errno = EBADF; return (NULL); } + if (fp->_flags & __SWR) + (void) __sflush(fp); if ((oflags ^ dflags) & O_APPEND) { dflags &= ~O_APPEND; dflags |= oflags & O_APPEND; @@ -114,15 +114,9 @@ freopen(file, mode, fp) } } if (oflags & O_TRUNC) - ftruncate(fp->_file, 0); - if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET, - 0) < 0 && errno != ESPIPE) { - sverrno = errno; - fclose(fp); - FUNLOCKFILE(fp); - errno = sverrno; - return (NULL); - } + (void) ftruncate(fp->_file, (off_t)0); + if (!(oflags & O_APPEND)) + (void) _sseek(fp, (fpos_t)0, SEEK_SET); f = fp->_file; isopen = 0; wantfd = -1; @@ -136,6 +130,8 @@ freopen(file, mode, fp) * 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 */ @@ -146,11 +142,18 @@ freopen(file, mode, fp) if (fp->_flags & __SWR) (void) __sflush(fp); /* if close is NULL, closing is a no-op, hence pointless */ +#if __DARWIN_UNIX03 + if (fp->_close) + (void) (*fp->_close)(fp->_cookie); + isopen = 0; + wantfd = -1; +#else /* !__DARWIN_UNIX03 */ isopen = fp->_close != NULL; if ((wantfd = fp->_file) < 0 && isopen) { (void) (*fp->_close)(fp->_cookie); isopen = 0; } +#endif /* __DARWIN_UNIX03 */ } /* Get a new descriptor to refer to the new file. */ @@ -187,13 +190,13 @@ finish: if (HASLB(fp)) FREELB(fp); fp->_lb._size = 0; - fp->_extra->orientation = 0; - memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t)); + fp->_orientation = 0; + memset(&fp->_mbstate, 0, sizeof(mbstate_t)); if (f < 0) { /* did not get it after all */ - fp->_flags = 0; /* set it free */ - errno = sverrno; /* restore in case _close clobbered */ FUNLOCKFILE(fp); + __sfprelease(fp); /* set it free */ + errno = sverrno; /* restore in case _close clobbered */ return (NULL); } @@ -209,6 +212,20 @@ finish: } } + /* + * File descriptors are a full int, but _file is only a short. + * If we get a valid file descriptor that is greater than + * SHRT_MAX, then the fd will get sign-extended into an + * invalid file descriptor. Handle this case by failing the + * open. + */ + if (f > SHRT_MAX) { + FUNLOCKFILE(fp); + __sfprelease(fp); /* set it free */ + errno = EMFILE; + return (NULL); + } + fp->_flags = flags; fp->_file = f; fp->_cookie = fp; @@ -216,6 +233,16 @@ finish: fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; + /* + * When opening in append mode, even though we use O_APPEND, + * we need to seek to the end so that ftell() gets the right + * answer. If the user then alters the seek pointer, or + * the file extends, this will fail, but there is not much + * we can do about this. (We could set __SAPP and check in + * fseek and ftell.) + */ + if (oflags & O_APPEND) + (void) _sseek(fp, (fpos_t)0, SEEK_END); FUNLOCKFILE(fp); return (fp); }