From: jjohnstn Date: Mon, 9 Jan 2006 17:51:01 +0000 (+0000) Subject: 2006-01-09 Eric Blake X-Git-Tag: pre-ptymaster-archetype~1642 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a21e28b8b7098005fce45e2dfbe99ed21d35bb8d;p=pf3gnuchains%2Fpf3gnuchains4x.git 2006-01-09 Eric Blake * libc/stdio/freopen.c (_freopen_r): Accept NULL filename. * libc/stdio64/freopen64.c (_freopen64_r): Likewise. --- diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 29a8dc09e3..cbc778e6f3 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,8 @@ +2006-01-09 Eric Blake + + * libc/stdio/freopen.c (_freopen_r): Accept NULL filename. + * libc/stdio64/freopen64.c (_freopen64_r): Likewise. + 2006-01-06 Jeff Johnston * libc/sys/linux/include/getopt.h: Add macros needed by diff --git a/newlib/libc/stdio/freopen.c b/newlib/libc/stdio/freopen.c index 995100b270..b57ba513da 100644 --- a/newlib/libc/stdio/freopen.c +++ b/newlib/libc/stdio/freopen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1990, 2006 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted @@ -55,6 +55,12 @@ it). <[file]> and <[mode]> are used just as in <>. +If <[file]> is <>, the underlying stream is modified rather than +closed. The file cannot change access mode (for example, if it was +previously read-only, <[mode]> must be "r", "rb", or "rt"), but can +change status such as append or binary mode. If modification is not +possible, failure occurs. + RETURNS If successful, the result is the same as the argument <[fp]>. If the file cannot be opened as specified, the result is <>. @@ -70,6 +76,7 @@ Supporting OS subroutines required: <>, <>, <>, #include #include #include +#include #include #include #include @@ -87,7 +94,8 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), register FILE *fp) { register int f; - int flags, oflags, e; + int flags, oflags; + int e = 0; __sfp_lock_acquire (); @@ -117,17 +125,57 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), { if (fp->_flags & __SWR) _CAST_VOID fflush (fp); - /* if close is NULL, closing is a no-op, hence pointless */ - if (fp->_close != NULL) + /* + * If close is NULL, closing is a no-op, hence pointless. + * If file is NULL, the file should not be closed. + */ + if (fp->_close != NULL && file != NULL) _CAST_VOID (*fp->_close) (fp->_cookie); } /* - * Now get a new descriptor to refer to the new file. + * Now get a new descriptor to refer to the new file, or reuse the + * existing file descriptor if file is NULL. */ - f = _open_r (ptr, (char *) file, oflags, 0666); - e = ptr->_errno; + if (file != NULL) + { + f = _open_r (ptr, (char *) file, oflags, 0666); + e = ptr->_errno; + } + else + { +#ifdef HAVE_FCNTL + /* + * Reuse the file descriptor, but only if the access mode is + * unchanged. F_SETFL correctly ignores creation flags. + */ + f = fp->_file; + if ((oflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1 + || ((oflags ^ flags) & O_ACCMODE) != 0 + || _fcntl_r (ptr, f, F_SETFL, flags) == -1) + f = -1; +#else + /* We cannot modify without fcntl support. */ + f = -1; +#endif + +#ifdef __SCLE + /* + * F_SETFL doesn't change textmode. Don't mess with modes of ttys. + */ + if (0 <= f && ! _isatty (f) + && setmode (f, flags & (O_BINARY | O_TEXT)) == -1) + f = -1; +#endif + + if (f < 0) + { + e = EBADF; + if (fp->_close != NULL) + _CAST_VOID (*fp->_close) (fp->_cookie); + } + } /* * Finish closing fp. Even if the open succeeded above, diff --git a/newlib/libc/stdio64/freopen64.c b/newlib/libc/stdio64/freopen64.c index b8b7974e54..fa727d3764 100644 --- a/newlib/libc/stdio64/freopen64.c +++ b/newlib/libc/stdio64/freopen64.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1990, 2006 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted @@ -55,6 +55,12 @@ it). <[file]> and <[mode]> are used just as in <>. +If <[file]> is <>, the underlying stream is modified rather than +closed. The file cannot change access mode (for example, if it was +previously read-only, <[mode]> must be "r", "rb", or "rt"), but can +change status such as append or binary mode. If modification is not +possible, failure occurs. + RETURNS If successful, the result is the same as the argument <[fp]>. If the file cannot be opened as specified, the result is <>. @@ -68,6 +74,7 @@ Supporting OS subroutines required: <>, <>, <>, #include #include +#include #include #include #include @@ -87,7 +94,8 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), register FILE *fp) { register int f; - int flags, oflags, e; + int flags, oflags; + int e = 0; __sfp_lock_acquire (); @@ -117,17 +125,57 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), { if (fp->_flags & __SWR) (void) fflush (fp); - /* if close is NULL, closing is a no-op, hence pointless */ - if (fp->_close != NULL) + /* + * If close is NULL, closing is a no-op, hence pointless. + * If file is NULL, the file should not be closed. + */ + if (fp->_close != NULL && file != NULL) (void) (*fp->_close) (fp->_cookie); } /* - * Now get a new descriptor to refer to the new file. + * Now get a new descriptor to refer to the new file, or reuse the + * existing file descriptor if file is NULL. */ - f = _open64_r (ptr, (char *) file, oflags, 0666); - e = ptr->_errno; + if (file != NULL) + { + f = _open64_r (ptr, (char *) file, oflags, 0666); + e = ptr->_errno; + } + else + { +#ifdef HAVE_FCNTL + /* + * Reuse the file descriptor, but only if the access mode is + * unchanged. F_SETFL correctly ignores creation flags. + */ + f = fp->_file; + if ((oflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1 + || ((oflags ^ flags) & O_ACCMODE) != 0 + || _fcntl_r (ptr, f, F_SETFL, flags) == -1) + f = -1; +#else + /* We cannot modify without fcntl support. */ + f = -1; +#endif + +#ifdef __SCLE + /* + * F_SETFL doesn't change textmode. Don't mess with modes of ttys. + */ + if (0 <= f && ! _isatty (f) + && setmode (f, flags & (O_BINARY | O_TEXT)) == -1) + f = -1; +#endif + + if (f < 0) + { + e = EBADF; + if (fp->_close != NULL) + (void) (*fp->_close) (fp->_cookie); + } + } /* * Finish closing fp. Even if the open succeeded above,