This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
fix stderr, fdopen
- From: Eric Blake <ebb9 at byu dot net>
- To: newlib at sources dot redhat dot com
- Date: Tue, 29 May 2007 21:16:58 +0000 (UTC)
- Subject: fix stderr, fdopen
POSIX requires "The stderr stream is expected to be open for reading and
writing". This implements that (and if fd 2 is a write-only pipe instead of a
read-write terminal, fgetc(stderr) will correctly fail later on); ok to apply?
Also, for fdopen, POSIX states "Although not explicitly required by this volume
of IEEE Std 1003.1-2001, a good implementation of append (a) mode would cause
the O_APPEND flag to be set." OK to apply?
Actually, I'm not whether POSIX requires this example to remain in append mode,
or if it can go to seekable writes; if the latter, then my patch is overkill,
and a more efficient solution is to never set __SAPP if we can rely on O_APPEND.
FILE *f = fopen("foo", "a");
fcntl(fileno(f), F_SETFL, fcntl(fileno(f), F_GETFL) & ~O_APPEND);
fputc(' ', f);
Does anyone know for sure how other stdio implementations behave here?
The fix for fdopen is also important for my pending patch that provides
fopencookie, since __SAPP is essential for fopencookie(cookie, "a+", ...) to
correctly implement append semantics. Any review on that patch yet?
http://sourceware.org/ml/newlib/2007/msg00547.html
2007-05-29 Eric Blake <ebb9@byu.net>
* libc/stdio/findfp.c (__sinit): Open stderr read-write.
* libc/stdio/flags.c (__sflags): Don't lose __SAPP on "a+".
* libc/stdio/fdopen.c (_fdopen_r): Set O_APPEND on fd when
requested.
* libc/stdio64/fdopen64.c (_fdopen64_r): Likewise.
Index: libc/stdio/findfp.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/findfp.c,v
retrieving revision 1.18
diff -u -p -r1.18 findfp.c
--- libc/stdio/findfp.c 1 May 2007 23:03:36 -0000 1.18
+++ libc/stdio/findfp.c 29 May 2007 20:57:33 -0000
@@ -204,16 +204,21 @@ _DEFUN(__sinit, (s),
std (s->_stdin, __SRD, 0, s);
- /* on platforms that have true file system I/O, we can verify whether stdout
- is an interactive terminal or not. For all other platforms, we will
- default to line buffered mode here. */
+ /* on platforms that have true file system I/O, we can verify
+ whether stdout is an interactive terminal or not, as part of
+ __smakebuf on first use of the stream. For all other platforms,
+ we will default to line buffered mode here. Technically, POSIX
+ requires both stdin and stdout to be line-buffered, but tradition
+ leaves stdin alone on systems without fcntl. */
#ifdef HAVE_FCNTL
std (s->_stdout, __SWR, 1, s);
#else
std (s->_stdout, __SWR | __SLBF, 1, s);
#endif
- std (s->_stderr, __SWR | __SNBF, 2, s);
+ /* POSIX requires stderr to be opened for reading and writing, even though
+ fd 2 might be write-only. */
+ std (s->_stderr, __SRW | __SNBF, 2, s);
__sinit_lock_release ();
}
Index: libc/stdio/flags.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/flags.c,v
retrieving revision 1.3
diff -u -p -r1.3 flags.c
--- libc/stdio/flags.c 23 Apr 2004 20:01:55 -0000 1.3
+++ libc/stdio/flags.c 29 May 2007 20:57:33 -0000
@@ -62,7 +62,7 @@ _DEFUN(__sflags, (ptr, mode, optr),
}
if (mode[1] && (mode[1] == '+' || mode[2] == '+'))
{
- ret = __SRW;
+ ret = (ret & ~(__SRD | __SWR)) | __SRW;
m = O_RDWR;
}
if (mode[1] && (mode[1] == 'b' || mode[2] == 'b'))
Index: libc/stdio/fdopen.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fdopen.c,v
retrieving revision 1.8
diff -u -p -r1.8 fdopen.c
--- libc/stdio/fdopen.c 23 Apr 2004 20:01:54 -0000 1.8
+++ libc/stdio/fdopen.c 29 May 2007 20:57:33 -0000
@@ -29,7 +29,7 @@ ANSI_SYNOPSIS
FILE *fdopen(int <[fd]>, const char *<[mode]>);
FILE *_fdopen_r(struct _reent *<[reent]>,
int <[fd]>, const char *<[mode]>);
-
+
TRAD_SYNOPSIS
#include <stdio.h>
FILE *fdopen(<[fd]>, <[mode]>)
@@ -97,16 +97,14 @@ _DEFUN(_fdopen_r, (ptr, fd, mode),
fp->_flags = flags;
/*
- * If opened for appending, but underlying descriptor
- * does not have O_APPEND bit set, assert __SAPP so that
- * __swrite() will lseek to end before each write.
+ * Set the O_APPEND bit on fd if possible. Someone else may later
+ * clear O_APPEND on fileno(fp), but fp must remain in append
+ * mode, so rely on __sflags setting __SAPP properly.
*/
- if ((oflags & O_APPEND)
#ifdef HAVE_FCNTL
- && !(fdflags & O_APPEND)
+ if (oflags & O_APPEND && !(fdflags & O_APPEND))
+ _fcntl_r (ptr, fd, F_SETFL, fdflags | O_APPEND);
#endif
- )
- fp->_flags |= __SAPP;
fp->_file = fd;
fp->_cookie = (_PTR) fp;
Index: libc/stdio64/fdopen64.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio64/fdopen64.c,v
retrieving revision 1.4
diff -u -p -r1.4 fdopen64.c
--- libc/stdio64/fdopen64.c 1 May 2007 23:03:36 -0000 1.4
+++ libc/stdio64/fdopen64.c 29 May 2007 20:57:33 -0000
@@ -68,16 +68,14 @@ _DEFUN (_fdopen64_r, (ptr, fd, mode),
fp->_flags = flags;
/*
- * If opened for appending, but underlying descriptor
- * does not have O_APPEND bit set, assert __SAPP so that
- * __swrite() will lseek to end before each write.
+ * Set the O_APPEND bit on fd if possible. Someone else may later
+ * clear O_APPEND on fileno(fp), but fp must remain in append
+ * mode, so rely on __sflags setting __SAPP properly.
*/
- if ((oflags & O_APPEND)
#ifdef HAVE_FCNTL
- && !(fdflags & O_APPEND)
+ if (oflags & O_APPEND && !(fdflags & O_APPEND))
+ _fcntl_r (ptr, fd, F_SETFL, fdflags | O_APPEND);
#endif
- )
- fp->_flags |= __SAPP;
fp->_file = fd;
fp->_cookie = (_PTR) fp;