From d02b2c6474afab3e4d5748eca254bcf9aa12fa18 Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Sat, 22 Jan 2005 19:49:18 +0000 Subject: re PR libfortran/18982 (open(status="new") does not generate an error if the file exists) 2005-01-22 Thomas Koenig 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 --- libgfortran/io/unix.c | 71 +++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 30 deletions(-) (limited to 'libgfortran/io/unix.c') 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); } -- cgit v1.1