delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2013/07/16/19:00: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: <51E5D0C6.1060404@gmx.de>
Date: Wed, 17 Jul 2013 01:01:26 +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: Set _IOERR if the file stream has been opened in wrong mode.
X-Provags-ID: V03:K0:oy90SpKbqhEE4GKNwWpSj78dUrW/a+pjpAU5QTee6eXv4cQVtAs
Qq1Sg2JVonjnY2/uZstTT9HfGEe34NP6D0lrpkTezkroKmndtQFKutCj/DAkab4n6xx8dJn
3zfkD5CA7lTWuBHvjhVvw9RYu1axJqlIk3MliUwokn4MBtM7PexzUktOw2Hk/+MSH9khM9C
TpfPcr8J8GAfe5ADbBSgg==
Reply-To: djgpp-workers AT delorie DOT com

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.

Regards,
Juan M. Guerrero





cvs ci -"Set _IOERR if the file stream has been opened in wrong mode." djgpp/include/libc/file.h
cvs ci -"Set _IOERR if the file stream has been opened in wrong mode." djgpp/src/docs/kb/wc204.txi
cvs ci -"Set _IOERR if the file stream has been opened in wrong mode." djgpp/src/libc/ansi/stdio/fread.c
cvs ci -"Set _IOERR if the file stream has been opened in wrong mode." djgpp/src/libc/ansi/stdio/fwrite.c



Logging in to :pserver:anonymous AT cvs DOT delorie DOT com:2401/cvs/djgpp
Index: djgpp/include/libc/file.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/libc/file.h,v
retrieving revision 1.14
diff -p -U 5 -r1.14 file.h
--- djgpp/include/libc/file.h    16 Jul 2013 19:01:02 -0000    1.14
+++ djgpp/include/libc/file.h    16 Jul 2013 22:06:21 -0000
@@ -1,5 +1,6 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
@@ -36,10 +37,14 @@ extern "C" {
  /* if _flag & _IORMONCL, ._name_to_remove needs freeing */
  #define _IOUNGETC 010000  /* there is an ungetc'ed character in the buffer */
  #define _IOTERM   020000  /* file's handle hooked by termios */
  #define _IONTERM  040000  /* file's handle not hooked by termios */

+#define IN_READ_ONLY_MODE(f)    ((f)->_flag & _IOREAD && !((f)->_flag & _IOWRT))
+#define IN_WRITE_ONLY_MODE(f)   ((f)->_flag & _IOWRT && !((f)->_flag & _IOREAD))
+
+
  int  _flsbuf(int, FILE*);
  int  _filbuf(FILE *);
  void _fwalk(void (*)(FILE *));

  static __inline__ int __getc_raw(FILE *const p)
@@ -69,10 +74,15 @@ static __inline__ int __is_text_file(FIL
  }

  static __inline__ int __getc(FILE *const p)
  {
    int __c;
+  if (IN_WRITE_ONLY_MODE(p))
+  {
+    p->_flag |= _IOERR;
+    return EOF;
+  }
    if (__libc_read_termios_hook
        && !(p->_flag & (_IOTERM | _IONTERM)))
    {
      extern int __isatty(int);
      /* first time we see this handle--see if termios hooked it */
@@ -87,10 +97,15 @@ static __inline__ int __getc(FILE *const
    return __c;
  }

  static __inline__ int __putc(const int x, FILE *const p)
  {
+  if (IN_READ_ONLY_MODE(p))
+  {
+    p->_flag |= _IOERR;
+    return EOF;
+  }
    if (__libc_write_termios_hook
        && !(p->_flag & (_IOTERM | _IONTERM)))
    {
      extern int __isatty(int);
      /* first time we see this handle--see if termios hooked it */
Index: djgpp/src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.207
diff -p -U 5 -r1.207 wc204.txi
--- djgpp/src/docs/kb/wc204.txi    23 Mar 2013 11:54:58 -0000  1.207
+++ djgpp/src/docs/kb/wc204.txi    16 Jul 2013 22:06:21 -0000
@@ -1287,5 +1287,13 @@ members of @code{struct rlimit}.
  @findex islessgreater AT r{ added}
  @findex isunordered AT r{ added}
  The @acronym{C99} macros @code{isfinite}, @code{isinf}, @code{isnan}, @code{isnormal}, @code{isgreater},
  @code{isgreaterequal}, @code{isless}, @code{islessequal}, @code{islessgreater} and @code{isunordered}
  were added to comply with the @acronym{C99} standard.
+
+@findex fread AT r{, and setting @code{_flag} to @code{_IOERR} if stream has been opened with wrong mode}
+@findex fwrite AT r{, and setting @code{_flag} to @code{_IOERR} if stream has been opened with wrong mode}
+@findex __getc AT r{, and setting @code{_flag} to @code{_IOERR} if stream has been opened with wrong mode}
+@findex __putc AT r{, and setting @code{_flag} to @code{_IOERR} if stream has been opened with wrong mode}
+@code{fread}, @code{fwrite}, @code{__getc} and @code{__putc} now check that the
+file stream has been opened in correct mode.  If it is the wrong mode the file
+stream @code{_flag} flag will be set to @code{_IOERR} before aborting the operation.
Index: djgpp/src/libc/ansi/stdio/fread.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/fread.c,v
retrieving revision 1.8
diff -p -U 5 -r1.8 fread.c
--- djgpp/src/libc/ansi/stdio/fread.c    16 Jul 2013 21:54:37 -0000    1.8
+++ djgpp/src/libc/ansi/stdio/fread.c    16 Jul 2013 22:06:21 -0000
@@ -1,5 +1,6 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
@@ -16,10 +17,16 @@ fread(void *vptr, size_t size, size_t co
  {
    char *ptr = (char *)vptr;
    int s;
    int c;

+  if (IN_WRITE_ONLY_MODE(f))
+  {
+    f->_flag |= _IOERR;
+    return 0;
+  }
+
    /* grow if we know we're asking for a lot, even if it's in the
       buffer, since we'll probably read chunks this size for a while */
    while (size * count > f->_fillsize
           && f->_fillsize < f->_bufsiz)
    {
Index: djgpp/src/libc/ansi/stdio/fwrite.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/fwrite.c,v
retrieving revision 1.9
diff -p -U 5 -r1.9 fwrite.c
--- djgpp/src/libc/ansi/stdio/fwrite.c    16 Jul 2013 21:54:39 -0000    1.9
+++ djgpp/src/libc/ansi/stdio/fwrite.c    16 Jul 2013 22:06:21 -0000
@@ -1,5 +1,6 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
@@ -13,10 +14,16 @@ size_t
  fwrite(const void *vptr, size_t size, size_t count, FILE *f)
  {
    const char *ptr = (const char *)vptr;
    ssize_t s;

+  if (IN_READ_ONLY_MODE(f))
+  {
+    f->_flag |= _IOERR;
+    return 0;
+  }
+
    if (__libc_write_termios_hook
        && !(f->_flag & (_IOTERM | _IONTERM)))
    {
      /* first time we see this handle--see if termios hooked it */
      if (isatty(f->_file))

- Raw text -


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