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]" 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. Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit 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 * 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 #include #include #include #include #include +#include #include +#include 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 #include #include #include #include +#include +#include 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);