This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
 



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]