diff options
author | Thomas Koenig <Thomas.Koenig@online.de> | 2005-01-22 19:49:18 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2005-01-22 19:49:18 +0000 |
commit | d02b2c6474afab3e4d5748eca254bcf9aa12fa18 (patch) | |
tree | fda79f894c069363a2ace1fa2cd36b81203001de /libgfortran/io | |
parent | d7c71ee3e6bd95291f0f33a7fdd7de00980ce3fd (diff) | |
download | gcc-d02b2c6474afab3e4d5748eca254bcf9aa12fa18.zip gcc-d02b2c6474afab3e4d5748eca254bcf9aa12fa18.tar.gz gcc-d02b2c6474afab3e4d5748eca254bcf9aa12fa18.tar.bz2 |
re PR libfortran/18982 (open(status="new") does not generate an error if the file exists)
2005-01-22 Thomas Koenig <Thomas.Koenig@online.de>
PR libfortran/18982
* io/unix.c (regular_file): No need to change flags->action
if an error occurs. Document this.
No need to call stat() for STATUS_OLD, open() will
fail anyway.
For ACTION_UNSPECIFIED, try open for read-write, then for
read-only if open fails with EACCES, then for write-only
if that fails with EACCES again.
* io/unix.c (open_external): Document changed behavior of
regular_file.
testsuite/
* gfortran.dg/open_new.f90: New file.
From-SVN: r94076
Diffstat (limited to 'libgfortran/io')
-rw-r--r-- | libgfortran/io/unix.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index e174e3b..daa0fb1 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -998,16 +998,17 @@ tempfile (void) /* regular_file()-- Open a regular file. - * Change flags->action if it is ACTION_UNSPECIFIED on entry. + * Change flags->action if it is ACTION_UNSPECIFIED on entry, + * unless an error occurs. * Returns the descriptor, which is less than zero on error. */ static int regular_file (unit_flags *flags) { char path[PATH_MAX + 1]; - struct stat statbuf; int mode; int rwflag; + int crflag; int fd; if (unpack_filename (path, ioparm.file, ioparm.file_len)) @@ -1040,21 +1041,20 @@ regular_file (unit_flags *flags) switch (flags->status) { case STATUS_NEW: - rwflag |= O_CREAT | O_EXCL; + crflag = O_CREAT | O_EXCL; break; - case STATUS_OLD: /* file must exist, so check for its existence */ - if (stat (path, &statbuf) < 0) - return -1; + case STATUS_OLD: /* open will fail if the file does not exist*/ + crflag = 0; break; case STATUS_UNKNOWN: case STATUS_SCRATCH: - rwflag |= O_CREAT; + crflag = O_CREAT; break; case STATUS_REPLACE: - rwflag |= O_CREAT | O_TRUNC; + crflag = O_CREAT | O_TRUNC; break; default: @@ -1064,29 +1064,39 @@ regular_file (unit_flags *flags) /* rwflag |= O_LARGEFILE; */ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - fd = open (path, rwflag, mode); - if (flags->action == ACTION_UNSPECIFIED) + fd = open (path, rwflag | crflag, mode); + if (flags->action != ACTION_UNSPECIFIED) + return fd; + + if (fd >= 0) { - if (fd < 0) - { - rwflag = rwflag & !O_RDWR | O_RDONLY; - fd = open (path, rwflag, mode); - if (fd < 0) - { - rwflag = rwflag & !O_RDONLY | O_WRONLY; - fd = open (path, rwflag, mode); - if (fd < 0) - flags->action = ACTION_READWRITE; /* Could not open at all. */ - else - flags->action = ACTION_WRITE; - } - else - flags->action = ACTION_READ; - } - else - flags->action = ACTION_READWRITE; + flags->action = ACTION_READWRITE; + return fd; } - return fd; + if (errno != EACCES) + return fd; + + /* retry for read-only access */ + rwflag = O_RDONLY; + fd = open (path, rwflag | crflag, mode); + if (fd >=0) + { + flags->action = ACTION_READ; + return fd; /* success */ + } + + if (errno != EACCES) + return fd; /* failure */ + + /* retry for write-only access */ + rwflag = O_WRONLY; + fd = open (path, rwflag | crflag, mode); + if (fd >=0) + { + flags->action = ACTION_WRITE; + return fd; /* success */ + } + return fd; /* failure */ } @@ -1109,7 +1119,8 @@ open_external (unit_flags *flags) } else { - /* regular_file resets flags->action if it is ACTION_UNSPECIFIED. */ + /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and + * if it succeeds */ fd = regular_file (flags); } |