@@ -1139,6 +1139,7 @@ might in some way or another become visible to the programmer.
* Internal representation of LOGICAL variables::
* Thread-safety of the runtime library::
* Data consistency and durability::
+* Files opened without an explicit ACTION= specifier::
@end menu
@@ -1328,6 +1329,22 @@ releasing @code{fcntl} file locks, if the server supports them, will
also force cache validation and flushing dirty data and metadata.
+@node Files opened without an explicit ACTION= specifier
+@section Files opened without an explicit ACTION= specifier
+@cindex open, action
+
+The Fortran standard says that if an @code{OPEN} statement is executed
+without an explicit @code{ACTION=} specifier, the default value is
+processor dependent. GNU Fortran behaves as follows:
+
+@enumerate
+@item Attempt to open the file with @code{ACTION='READWRITE'}
+@item If that fails, try to open with @code{ACTION='READ'}
+@item If that fails, try to open with @code{ACTION='WRITE'}
+@item If that fails, generate an error
+@end enumerate
+
+
@c ---------------------------------------------------------------------
@c Extensions
@c ---------------------------------------------------------------------
@@ -1,5 +1,5 @@
! { dg-do run }
-! { dg-shouldfail "File already exists" }
+! { dg-shouldfail "Cannot open file" }
! PR 64770 SIGSEGV when trying to open an existing file with status="new"
program pr64770
implicit none
@@ -10,5 +10,5 @@ program pr64770
status="new")
end program pr64770
! { dg-output "At line 10 of file.*" }
-! { dg-output "Fortran runtime error: File .pr64770test.dat. already exists" }
+! { dg-output "Fortran runtime error: Cannot open file .pr64770test.dat.:" }
! { dg-final { remote_file build delete "pr64770test.dat" } }
@@ -502,34 +502,12 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
s = open_external (opp, flags);
if (s == NULL)
{
+ char errbuf[256];
char *path = fc_strdup (opp->file, opp->file_len);
- size_t msglen = opp->file_len + 51;
+ size_t msglen = opp->file_len + 22 + sizeof (errbuf);
char *msg = xmalloc (msglen);
-
- switch (errno)
- {
- case ENOENT:
- snprintf (msg, msglen, "File '%s' does not exist", path);
- break;
-
- case EEXIST:
- snprintf (msg, msglen, "File '%s' already exists", path);
- break;
-
- case EACCES:
- snprintf (msg, msglen,
- "Permission denied trying to open file '%s'", path);
- break;
-
- case EISDIR:
- snprintf (msg, msglen, "'%s' is a directory", path);
- break;
-
- default:
- free (msg);
- msg = NULL;
- }
-
+ snprintf (msg, msglen, "Cannot open file '%s': %s", path,
+ gf_strerror (errno, errbuf, sizeof (errbuf)));
generate_error (&opp->common, LIBERROR_OS, msg);
free (msg);
free (path);
@@ -1353,7 +1353,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
flags->action = ACTION_READWRITE;
return fd;
}
- if (errno != EACCES && errno != EROFS)
+ if (errno != EACCES && errno != EPERM && errno != EROFS)
return fd;
/* retry for read-only access */
@@ -1369,7 +1369,7 @@ regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
return fd; /* success */
}
- if (errno != EACCES && errno != ENOENT)
+ if (errno != EACCES && errno != EPERM && errno != ENOENT)
return fd; /* failure */
/* retry for write-only access */