Date: Wed, 3 Mar 2004 15:04:58 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: David Schultz <das@freebsd.org> Cc: "Jordan K. Hubbard" <jkh@queasyweasel.com> Subject: Re: Another conformance question... This time fputs(). Message-ID: <20040303144451.T5253@gamplex.bde.org> In-Reply-To: <20040302165323.GA17665@VARK.homeunix.com> References: <F648D56F-6C28-11D8-9000-000393BB9222@queasyweasel.com> <20040302165323.GA17665@VARK.homeunix.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 2 Mar 2004, 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. I don't think there is any option for fwrite(). Its underlying function is normally write(2) and that would return EBADF (this is what is arguably wrong). fwrite() must do what the underlying function would. > (By the way, there are a few other cantwrite() calls in libc that > probably have the same bug.) One is vfprintf(), which may output to non-files. Oops, so can __svfwrite(). The underlying function isn't always write(2). EBADF is a very bogus errno if the output is not to a file. It can be to a string or anything set up by funopen()/fropen()/fwopen(). Strings are writable, so they don't cause a problem here, but anything set up by fropen() or funopen() without a write function is unwritable and returning EBADF is wrong for it. NetBSD just returns EBADF for all the cantwrite() cases. This incomplete fix was made less than 7 years ago: % RCS file: /home/NetBSD/NetBSD-cvs/src/lib/libc/stdio/fvwrite.c,v % Working file: fvwrite.c % head: 1.15 % ... % ---------------------------- % revision 1.6 % date: 1997/05/03 09:01:48; author: kleink; state: Exp; lines: +6 -3 % Upon an attempt to write to a stream that can't be written to, set errno % to EBADF. % ---------------------------- > > errno = 19, rc = 0 > > fwrite errno = 0, rc = 18 > > > > Which gives us ENODEV for the fputs(3) and no error for the fwrite(3). > ... > 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. Very unrelated. As explained in my earlier reply, rc = 0 indicates an error. errno is not set since we don't support the POSIX extension of setting it. The bug is that ioctls on /dev/zero return a wrong errno (ENODEV instead of ENOTTY). I fixed tens if not hundreds of instances of this bug but never got around to it in the /dev/null family. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040303144451.T5253>