Another conformance question... This time fputs().

Jordan K. Hubbard jkh at queasyweasel.com
Tue Mar 2 12:34:37 PST 2004


On Mar 2, 2004, at 8:53 AM, David Schultz wrote:

> Nice catch.  I think the wording of POSIX suggests that the error
> code is supposed to be EBADF, which is returned if ``the file
> descriptor [...] is not a valid file descriptor for writing.''
> Although you could argue that the standard is wrong, Linux and
> Solaris return EBADF, so we probably should, too.

Yeah, that's the approach I just took.  Thanks.

> (By the way, there are a few other cantwrite() calls in libc that
> probably have the same bug.)

I've been looking at those...   The ones used by the vfprintf() 
internals look like a no-brainer since the man page says:

      In addition to the errors documented for the write(2) system call, 
the
      printf() family of functions may fail if: [ ... ]

Since we've cleverly short-circuited the write(2) calls with the 
cantwrite() checks, one assumes we're on the hook to
emulate what would have happened if we actually had called write(2).  I 
was sort of on the fence about the call in
__swbuf(), which is used in the include/stdio.h macros to implement the 
putc()/putc_unlocked() internals, but I guess
there's really no question about it either since 
http://www.opengroup.org/onlinepubs/007904975/functions/fputc.html
is pretty clear that EBADF is expected in the same case.

With the full understanding that tabs are going to get smashed in this 
paste but don't represent what I'd actually
commit, does anyone have any objection to the following diff?

Index: stdio/vfprintf.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/vfprintf.c,v
retrieving revision 1.62
diff -u -r1.62 vfprintf.c
--- stdio/vfprintf.c    18 Jan 2004 10:32:49 -0000      1.62
+++ stdio/vfprintf.c    2 Mar 2004 20:31:15 -0000
@@ -50,6 +50,7 @@
  #include <sys/types.h>

  #include <ctype.h>
+#include <errno.h>
  #include <limits.h>
  #include <locale.h>
  #include <stddef.h>
@@ -641,8 +642,10 @@
         decimal_point = localeconv()->decimal_point;
  #endif
         /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
-       if (cantwrite(fp))
+       if (cantwrite(fp)) {
+               errno = EBADF;
                 return (EOF);
+       }

         /* optimise fprintf(stderr) (and other unbuffered Unix files) */
         if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
Index: stdio/vfwprintf.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/vfwprintf.c,v
retrieving revision 1.16
diff -u -r1.16 vfwprintf.c
--- stdio/vfwprintf.c   23 Jan 2004 22:48:16 -0000      1.16
+++ stdio/vfwprintf.c   2 Mar 2004 20:31:16 -0000
@@ -54,6 +54,7 @@
  #include <sys/types.h>

  #include <ctype.h>
+#include <errno.h>
  #include <limits.h>
  #include <locale.h>
  #include <stdarg.h>
@@ -646,8 +647,10 @@
  #endif
         convbuf = NULL;
         /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
-       if (cantwrite(fp))
+       if (cantwrite(fp)) {
+               errno = EBADF;
                 return (EOF);
+       }

         /* optimise fprintf(stderr) (and other unbuffered Unix files) */
         if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
Index: stdio/wbuf.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/wbuf.c,v
retrieving revision 1.10
diff -u -r1.10 wbuf.c
--- stdio/wbuf.c        13 Aug 2002 09:30:41 -0000      1.10
+++ stdio/wbuf.c        2 Mar 2004 20:31:16 -0000
@@ -40,6 +40,7 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD: src/lib/libc/stdio/wbuf.c,v 1.10 2002/08/13 
09:30:41 tjr Exp $");

+#include <errno.h>
  #include <stdio.h>
  #include "local.h"

@@ -65,8 +66,10 @@
          * calls might wrap _w from negative to positive.
          */
         fp->_w = fp->_lbfsize;
-       if (cantwrite(fp))
+       if (cantwrite(fp)) {
+               errno = EBADF;
                 return (EOF);
+       }
         c = (unsigned char)c;

         ORIENT(fp, -1);

> I'll bet the isatty() call in __smakebuf() is setting errno
> because /dev/null doesn't support the relevant ioctl.  Note that
> rc=0 so libc is ignoring the error and completing the write, even
> though it spuriously sets errno.  In any case, you're right that
> this is an unrelated bug.

No, I don't think that's it (see reply to bde on -arch).  I've looked 
at isatty() and it's fine, it
just calls tcgetattr() which sets errno to ENOTTY correctly (I checked).

> ASCII stupid question, get a stupid ANSI.

UGH!! :-)

--
Jordan K. Hubbard
Engineering Manager, BSD technology group
Apple Computer


More information about the freebsd-standards mailing list