diff options
author | Bruno Haible <bruno@clisp.org> | 2020-05-24 13:57:59 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2020-05-24 13:57:59 +0200 |
commit | a7e878621dc2fb8430fccb461b7b669b6bf86190 (patch) | |
tree | 23f0b86dfd8eaf63c99fca37f91f691d96b7f774 /lib/fopen.c | |
parent | f58691b91ed22372b4a962432aa3ea860fe1cbbb (diff) | |
download | gnulib-a7e878621dc2fb8430fccb461b7b669b6bf86190.tar.gz |
fopen: Fix the trailing slash workaround.
* lib/fopen.c (rpl_fopen): Parse the mode string. Recognize "r+" as a
write access. Pass the right flags to open().
* tests/test-fopen.h (test_fopen): Add a few more tests on directories.
Diffstat (limited to 'lib/fopen.c')
-rw-r--r-- | lib/fopen.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/lib/fopen.c b/lib/fopen.c index a3128fa8b7..ad6511d2c7 100644 --- a/lib/fopen.c +++ b/lib/fopen.c @@ -47,11 +47,47 @@ orig_fopen (const char *filename, const char *mode) FILE * rpl_fopen (const char *filename, const char *mode) { + int open_direction; + int open_flags_standard; + #if defined _WIN32 && ! defined __CYGWIN__ if (strcmp (filename, "/dev/null") == 0) filename = "NUL"; #endif + /* Parse the mode. */ + open_direction = 0; + open_flags_standard = 0; + { + const char *m; + + for (m = mode; *m != '\0'; m++) + { + switch (*m) + { + case 'r': + open_direction = O_RDONLY; + continue; + case 'w': + open_direction = O_WRONLY; + open_flags_standard |= O_CREAT | O_TRUNC; + continue; + case 'a': + open_direction = O_WRONLY; + open_flags_standard |= O_CREAT | O_APPEND; + continue; + case 'b': + continue; + case '+': + open_direction = O_RDWR; + continue; + default: + break; + } + break; + } + } + #if FOPEN_TRAILING_SLASH_BUG /* Fail if the mode requires write access and the filename ends in a slash, as POSIX says such a filename must name a directory @@ -74,13 +110,13 @@ rpl_fopen (const char *filename, const char *mode) struct stat statbuf; FILE *fp; - if (mode[0] == 'w' || mode[0] == 'a') + if (open_direction != O_RDONLY) { errno = EISDIR; return NULL; } - fd = open (filename, O_RDONLY); + fd = open (filename, open_direction | open_flags_standard); if (fd < 0) return NULL; @@ -101,7 +137,7 @@ rpl_fopen (const char *filename, const char *mode) return fp; } } -# endif +#endif return orig_fopen (filename, mode); } |