Reading a write-only file doesn't set error condition (was Re: Cygwin fread on Write-Only File Descriptor returns undefined state)
Jeff Johnston
jjohnstn@redhat.com
Thu Jun 15 16:08:00 GMT 2006
Jeff Johnston wrote:
> Corinna Vinschen wrote:
>
>> Thanks for the testcase. This looks like a small flaw in newlib.
>> I redirected to the newlib list.
>>
>>
>>
>> I debugged your testcase and the problem appears to be in __srefill(),
>> defined in newlib/libc/stdio/refill.c:
>>
>> /* if not already reading, have to be reading and writing */
>> if ((fp->_flags & __SRD) == 0)
>> {
>> if ((fp->_flags & __SRW) == 0)
>> return EOF;
>>
>> So, what happens is that EOF is returned if the file is not readable.
>> Errno isn't set and the error condition on the file pointer isn't set
>> either.
>>
>> Testing the same situation on Linux, errno is set to EBADF and the
>> error indicator is set on the file pointer, while the EOF condition
>> stays clear.
>>
>> So, I'd like to propose the below patch. I assume a similar patch
>> should be ok for __sfvwrite, too, isn't it? There's a call to
>> cantwrite() which only returns EOF but which probably should also
>> set the error condition and errno.
>>
>
> This opens a can of worms. You can't just use _REENT to set errno. One
> has to provide _r versions of the read/write functions. I have just
> made a patch and am verifying it builds for x86-linux. I will post the
> patch when I am ready to check it in.
>
> -- Jeff J.
>
I have checked in the patch. The testcase runs successfully and I am
able to build/run x86-linux successfully. Let me know if it causes any
problems for Cygwin.
-- Jeff J.
2006-06-14 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/stdio.h: Add new reentrant I/O prototypes for
read/write functions. Change getc/putc macros to have
reentrant underlying
macros/functions. This includes __sgetc_raw_r, __sgetc_r, and
__sputc_r.
* libc/stdio/fgetc.c: Fix and/or add reentrant version to call
new reentrant I/O functions/macros for reading/writing.
* libc/stdio/fgets.c: Ditto.
* libc/stdio/fputc.c: Ditto.
* libc/stdio/fputs.c: Ditto.
* libc/stdio/fread.c: Ditto.
* libc/stdio/fseek.c: Ditto.
* libc/stdio64/fseeko64.c: Ditto.
* libc/stdio/fwrite.c: Ditto.
* libc/stdio/getc.c: Ditto.
* libc/stdio/getc_u.c: Ditto.
* libc/stdio/getchar.c: Ditto.
* libc/stdio/getchar_u.c: Ditto.
* libc/stdio/putc.c: Ditto.
* libc/stdio/putc_u.c: Ditto.
* libc/stdio/putchar.c: Ditto.
* libc/stdio/puts.c: Ditto.
* libc/stdio/vfprintf.c: Ditto.
* libc/stdio/vfscanf.c: Ditto.
* libc/stdio/fvwrite.c: Change __sfvwrite into reentrant
__sfvwrite_r.
Change all previous callers of __sfvwrite. Set errno to EBADF and
set error flag on if attempt is made to write to file that does not
allow writing.
* libc/stdio/fvwrite.h: Fix new reentrant prototypes.
* libc/stdio/local.h: Ditto.
* libc/stdio/refill.c: Turn __srefill into reentrant __srefill_r.
Set errno to EBADF and the error flag on if attempt is made to
read unreadable file. Change all previous callers of __srefill.
* libc/stdio/rget.c
* libc/stdio/wbuf.c: Turn __swbuf into reentrant __swbuf_r. Change
all previous callers of __swbuf.
* libc/sys/linux/machine/i386/huge_val.h: Ifdef out file
contents since
huge value macros are already defined correctly for i386 by
<math.h>.
More information about the Newlib
mailing list