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 -