delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2013/07/17/16:46:30

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
Message-ID: <51E702E0.3010809@gmx.de>
Date: Wed, 17 Jul 2013 22:47:28 +0200
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: Set _IOERR if the file stream has been opened in wrong mode.
References: <51E5D0C6 DOT 1060404 AT gmx DOT de> <83y5951a79 DOT fsf AT gnu DOT org>
In-Reply-To: <83y5951a79.fsf@gnu.org>
X-Provags-ID: V03:K0:ftkZZ2NJScdqmQYssShPyik0w00Gpg+lABccO809f3Ptx+sFy6I
7yQoEiR0Lg8DUS3jVmSOgx9U9f0h6h3CBCxry0Fhy3a0GJnQIcMGQ4c14s8lzdFv4zErgCl
URzQwkP4ntxMSbIZHBSvd8EY6zNRiZPCMakXAuJ5ZOMi35lmf6HRAW5fRfwOZ9dd9GFh5az
JInHCh0jhTgEZK7/B0iBQ==
Reply-To: djgpp-workers AT delorie DOT com

Am 17.07.2013 17:24, schrieb Eli Zaretskii:
>> Date: Wed, 17 Jul 2013 01:01:26 +0200
>> From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
>>
>> Please inspect the code snippet below:
>>
>> #include <stdio.h>
>>
>> int main(void)
>> {
>>     char buffer[1024];
>>     FILE *f = fopen("foobar.txt", "w");
>>
>>     clearerr(f);
>>
>>     if (fgets(buffer, sizeof(buffer), f) == NULL)
>>       printf("EOF encountered before data\n");
>>
>>     printf("ferror = %s\n", ferror(f) ? "TRUE" : "FALSE");
>>     printf("feof = %s\n", feof(f) ? "TRUE" : "FALSE");
>>
>>     return 0;
>> }
>>
>>
>> The code snippet is not arbitrary (especially the "w" mode instead of the "w+"
>> mode in the fopen function) but represents a compilable and working version of
>> the code produced by the lua interpreter for the first two lines of the
>> following lua code snippet:
>>
>>     local f = io.open("foobar.txt", "w")
>>     local r, m, c = f:read()
>>     assert(r == nil and ismsg(m) and type(c) == "number")
>>
>>
>> The above code is part of a test suite and it shall fail because it tries to
>> read from a file opened to be written.  The second line fails and initializes
>> the variables in such a way that the assert is not triggert (the data is a
>> error message and the file descriptor, but that is of no importance here).
>> This is the way the test shall work and this is the way the code works if lua
>> has been compiled on linux.  If lua is compiled using any version of djgpp,
>> the second line:
>>     local r, m, c = f:read()
>> behaves in a different way (it does not fail, among other things) and the
>> variables are initialized with nonsense data making the following assertion
>> to be triggert and thus aborting the complete test suite.
>>
>> The reason for the different behavior of lua's :read() function is the
>> different way the ferror function has been implemented on linux and djgpp.
>>
>> The issue concerns the fread, fwrite, __putc and __getc functions only.
>> These functions manipulate the file stream FILE *.  Functions like read,
>> _read and dos_read are not involved because they work with the file descriptor.
>> If these functions fail due to accessing the file with wrong file mode,
>> they set the appropriate dos error number.
>> Of course, ferror can only fail for those functions that use the file stream.
>>
>> The patch below will fix the issue for read and write functions.
>> As usual, suggestions, objections, comments are welcome.
> What standard mandates that reading from a file stream open in "w"
> mode shall set the error flag for the stream?
>
> DJGPP currently sets the EOF flag, not the error flag.  Why is that
> wrong?

According to http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html
RETURN VALUE

     Upon successful completion, fgets() shall return s. If the stream is at end-of-file,
     the end-of-file indicator for the stream shall be set and fgets() shall return a null
     pointer. If a read error occurs, the error indicator for the stream shall be set,
     fgets() shall return a null pointer.


According to http://pubs.opengroup.org/onlinepubs/009695399/functions/fputs.html
RETURN VALUE

     Upon successful completion, fputs() shall return a non-negative number. Otherwise,
     it shall return EOF, set an error indicator for the stream.


According to http://pubs.opengroup.org/onlinepubs/009695399/functions/fread.html
RETURN VALUE

     Upon successful completion, fread() shall return the number of elements successfully
     read which is less than nitems only if a read error or end-of-file is encountered.
     If size or nitems is 0, fread() shall return 0 and the contents of the array and the
     state of the stream remain unchanged. Otherwise, if a read error occurs, the error
     indicator for the stream shall be set


According to http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html
RETURN VALUE

     The fwrite() function shall return the number of elements successfully written,
     which may be less than nitems if a write error is encountered. If size or nitems
     is 0, fwrite() shall return 0 and the state of the stream remains unchanged.
     Otherwise, if a write error occurs, the error indicator for the stream shall be set,


For IEEE Std 1003.1-2001-conforming systems all the functions also shall set errno.



It is a matter of fact that the sample code posted in the previous mail
behaves as described by me for linux and cygwin.  And this behavior is
exploited by other programs like lua.  I have inspected __getc, __putc,
fwrite and fread and neither of them set EOF.  In the best case some of
them may return EOF to the calling context to signal a failure but the
_flag member (error indicator for the stream) is never set neither to
_IOEOF nor to _IOERR AFAIK.  I have not tried it mingw but I presume it
will behave the same way than linux and cygwin.
It may be objectionable if __getc and __putc were the right places to fix
the issue.  I will move the fix into fgets and fputs, the same way I have
done for fwrite and fread.  By fixing it in the auxiliary functions
__getc and __putc, my intention was to have it fixed every where and for
all times.
BTW as can be seen for fgets if the stream is at end-of-file, the end-of-file
indicator for the stream shall be set apart from returning a NULL pointer.
So there is much work to be done.

IMHO it is better to try to fix the library than to clobber the
source code of some program to get it compiled with djgpp or the
day may come when djgpp become completely useless and obsolete.


Regards,
Juan M. Guerrero


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019