delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2016/10/22/16:34:46

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Recipient: djgpp AT delorie DOT com
Message-ID: <580BCAA5.2000304@gmx.de>
Date: Sat, 22 Oct 2016 22:23:01 +0200
From: "Juan Manuel Guerrero (juan DOT guerrero AT gmx DOT de) [via djgpp AT delorie DOT com]" <djgpp AT delorie DOT com>
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.13) Gecko/20101206 SUSE/3.1.7 Thunderbird/3.1.7
MIME-Version: 1.0
To: djgpp AT delorie DOT com
Subject: A grep 2.26 test fails because fopen sets errno to EACCES when openning
an existing directory.
X-Provags-ID: V03:K0:5z7/5MRka/Mz0ccDj+MzRA0zcrBNd8JsvogWGKl2W9oOskJrdfv
OebR1kCRDNNYxw4ciEC/U4SmY+eQPhqZXO4KNnNudpnO0Ez8HCg80kS14VCjtbtAMWzD9pJ
+gElyFmpctSKJ7Th3JB5Vp3Uu08L+qpwY8CZusNxXs+kqEs77kEyhBpx7TQ/gb8hVXgDBWE
/+pzg3E4s0FiLp9ZqHpKA==
X-UI-Out-Filterresults: notjunk:1;V01:K0:HYpFCUWbceI=:R8bEqGmczNoXNGEA9cW6kt
TSuP+bwPtisb67syLGDWN6HI+eghHwyDoEuozlV8xGR3cDvJQzXD2RZ6LFoEcjBX4Bus8Bck5
wLEn9J9M6Us5RjccJASA9wB5+eq6yZfYoF9xJ6k/vqUBO9EYeSn+S/dP0SCiaEQhIyJ688Y06
CcI+O9QbNyf5urajkIlp3Z2KNiQ7ENvuqOukLvHzrfBkzF/VT3Ha2H7FbDctRfl1RayEJGZc7
y70fI7wtz+LJuwWgcFiD5zXP/JOAkZJhwwwwnEQe+n31mfqZ/lilxv9TOqvKVcOtWbMaJK8PU
olMFmY4OwHOoag3OkkqSC9cs9t3AklN46y855D5gOXzrmx79M9YzPfKeQE2nso9E519gS5x3d
z71Mt9cROr6gT0fxaG3c+11LeCe2pLoUTk5ClVkE/evyL0eC64gdEmanwd0dp+uDWA0Ai4FQo
qQ1HGWCMpqL8J+5xdOMgzvP6JwRKy6CTaxoWIP+Evfijm5V4O9ig+rUbUBLhzzzGU22L0+YsT
HX+WxPmQP/lNVCB06152e8WCCUgFpbGTpGkXq+399xrLP62CK/hO+J5fC5HlsW9HRucYFtzaG
kuaDPbSgqAQwLSMAHFw5YeXG051RnwBiVdpMgC6RrqjdrX3Zzd6a3R0sfIjmoBRhbUnJsRPyf
ZtjDIeEwZS1zj2CNcT2kU58BFiLj2oJBV4tj3vLt8s2yZ/zKKpn2edZmNsD1DQ7pmIVEA+hzr
2MuxQK4UgDb7u/1fFI+oAT/NaOkdyG9flcxnnCqOL6hILtBl55ng5YIuc/+ZzpOxA2UQ4V0tt
JtMTT7b
Reply-To: djgpp AT delorie DOT com

While I was trying to port grep 2.26 I have observed that the implementation of
open retains errno to values that are generated by intermediary operations even
if the open operation performs well.
In this particular case an existing directory shall be open but errno is set to
EACCES by some DOS call and passed to the calling context that later uses this
errno to generate an error message.  This is wrong IMHO.  The calling context
is the grep code and not the djgpp library code.  The documentation of the open
function clearly states that is at least possible to use the open function to
open a directory.  Thus no errno number should be set as consequence of this
call if the directory exists.  And this is the way linux works.  Please note
that no read nor write operation is performed on the directory at this moment.
Thus there is no reason for errno to be set at all by a successfull directory
open call.  This djgpp specific behavior makes the grep-dir test fail in the
testsuite.  It does not fail because it tries to access a directory but it
fails because it fails with EACCES from fopen/open instead of failing with
EISDIR as it shall.  The bottom line of all this is: if the operation performs
well there is no reason why the original errno value should be alterated by
the operation.

I have changed fread and fwrite to return with EISDIR if the file pointer
corresponds to a directory and open will restore the original errno if the
call of _open is successfull.  Of course, after having compiled grep with a
changed library, the check passes because fopen no longer fails with EACCES
but the later fread fails with EISDIR as it shall.

As usual suggestions, objections, comments are welcome.  If no one seriously
opposes in a rasonable periode of time I will committe the patch below.


Regards,
Juan M. Guerrero




2016-10-22  Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>

	* src/libc/posix/fcntl/open.c (open):  Store original errno before calling
	_open and restore it if the _open call was successfull.

	* src/libc/ansi/stdio/fread.c (fread):  If diretory set errno to EISDIR.

	* src/libc/ansi/stdio/fwrite.c (fwrite):  If diretory set errno to EISDIR.







diff -aprNU7 djgpp.orig/src/libc/ansi/stdio/fread.c djgpp/src/libc/ansi/stdio/fread.c
--- djgpp.orig/src/libc/ansi/stdio/fread.c	2015-05-02 07:32:00 -0512
+++ djgpp/src/libc/ansi/stdio/fread.c	2016-10-22 21:02:28 -0512
@@ -1,29 +1,40 @@
+/* Copyright (C) 2016 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2015 DJ Delorie, see COPYING.DJ for details */
  /* 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 */
  #include <libc/stubs.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include <libc/file.h>
+#include <libc/fd_props.h>
  #include <libc/ttyprvt.h>
+#include <errno.h>

  size_t
  fread(void *vptr, size_t size, size_t count, FILE *f)
  {
    char *ptr = (char *)vptr;
    int s;
    int c;

+  /* Reading on directories is not supported,
+     thus let the operation fail with the corresponding errno.  */
+  if (__get_fd_flags(fileno(f)) & FILE_DESC_DIRECTORY)
+  {
+    errno = EISDIR;
+    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)
    {
      if (f->_fillsize < 512)
        f->_fillsize = 512;
diff -aprNU7 djgpp.orig/src/libc/ansi/stdio/fwrite.c djgpp/src/libc/ansi/stdio/fwrite.c
--- djgpp.orig/src/libc/ansi/stdio/fwrite.c	2015-05-02 07:32:00 -0512
+++ djgpp/src/libc/ansi/stdio/fwrite.c	2016-10-22 21:02:26 -0512
@@ -1,26 +1,37 @@
+/* Copyright (C) 2016 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2015 DJ Delorie, see COPYING.DJ for details */
  /* 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 */
  #include <libc/stubs.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <libc/file.h>
+#include <libc/fd_props.h>
+#include <errno.h>

  size_t
  fwrite(const void *vptr, size_t size, size_t count, FILE *f)
  {
    const char *ptr = (const char *)vptr;
    ssize_t s;

+  /* Writing on directories is not supported,
+     thus let the operation fail with the corresponding errno.  */
+  if (__get_fd_flags(fileno(f)) & FILE_DESC_DIRECTORY)
+  {
+    errno = EISDIR;
+    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))
        f->_flag |= _IOTERM;
      else
diff -aprNU7 djgpp.orig/src/libc/posix/fcntl/open.c djgpp/src/libc/posix/fcntl/open.c
--- djgpp.orig/src/libc/posix/fcntl/open.c	2016-10-22 19:36:24 -0512
+++ djgpp/src/libc/posix/fcntl/open.c	2016-10-22 20:17:06 -0512
@@ -1,7 +1,8 @@
+/* Copyright (C) 2016 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 2014 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) 2000 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
@@ -230,14 +231,15 @@ open(const char* filename, int oflag, ..
      oflag |= __djgpp_share_flags;
    }

    if (should_create)
      fd = _creatnew(real_name, dmode, oflag & 0xff);
    else
    {
+    const int original_errno = errno;
      fd = _open(real_name, oflag);

      if (fd == -1)
      {
        /* It doesn't make sense to try anything else if there are no
  	 more file handles available.  */
        if (errno == EMFILE || errno == ENFILE)
@@ -274,14 +276,16 @@ open(const char* filename, int oflag, ..
              remove(real_name);
              errno = previous_errno;
              return fd;
            }
          }
        }
      }
+    else
+      errno = original_errno;
    }

    /* Is the target a directory? If so, generate a file descriptor
     * for the directory. Skip the rest of `open', because it does not
     * apply to directories. */
    if ((fd == -1) && (access(real_name, D_OK) == 0))
      return opendir_as_fd(real_name, original_oflag);

- Raw text -


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