Search code examples
linuxfortransystem-callsgfortrannfs

Fortran OPEN-call differs on NFSv3 vs NFSv4


I'm trying to understand the difference between why you can do an OPEN-call in fortran on NFSv3 in read-write mode on a file that you only have read-permissions on, while if you do the same thing on NFSv4 the OPEN-call will fail.

Let me explain, below is a simple fortran-program that opens given file (argument to the program) in read-write mode,

PROGRAM test_open

 IMPLICIT NONE

 ! Parameters

 INTEGER,            PARAMETER :: lunin = 10
 CHARACTER(LEN=100) :: fname

 ! Local

 INTEGER :: i,ierr,siteid,nstation
 REAL :: lat, lon, asl
 CHARACTER(len=15) :: name

 !----------------------------------------------------------------
 !
 ! Open input file
 !

 CALL getarg(1,fname)

 OPEN(lunin,file=fname,STATUS='OLD',IOSTAT=ierr)

 IF ( ierr /= 0 ) THEN
    WRITE(6,*)'Could not open ',TRIM(fname),ierr
    STOP
 ENDIF

 WRITE(6,*)'Opened OK'

 CLOSE(lunin)


END PROGRAM test_open

Save the above in test_open.f90 and compile with,

gfortran -o fortran test_open.f90 

Now, execute the following on a mountpoint with NFSv3,

strace -eopen ./fortran file-with-only-read-permissions 

And you should see the following lines (along with a lot of other output),

> open("file-with-only-read-permissions", O_RDWR)  = -1 EACCES (Permission denied)
> open("file-with-only-read-permissions", O_RDONLY) = 3

So, we can clearly see that we get an "EACCES (Permission denied)" while trying to open in 'O_RDWR' (open read-write), but right after we see another open O_RDONLY (open read-only) and that succeeds.

Run the same program on a file on a NFSv4 share, and we get the following,

strace -eopen ./fortran file-with-only-read-permissions-on-nfsv4-share 
> open("file-with-only-read-permissions-on-nfsv4-share", O_RDWR)  = -1 EPERM (Operation not permitted) 

So, here we get an "EPERM (Operation not permitted)" while trying to open the file in 'O_RDWR' (open read-write) and nothing more (ie application fails).

Doing the same tests in C with a small test-program it will fail to open the file in both scenarios (that is, it will not try to open the file in 'read-only-mode' after getting the "EACCES" on NFSv3).

So to the questions,

  • I assume the above behaviour is due to the implementation of the OPEN-call in fortran, and that if fortran gets an "EACCES (Permission denied)" while trying to open a file, it will automatically try to open the file in read-only (O_RDONLY). Is this assumption correct ?

  • I also assume that fortran doesn't have this "fallback-method" when getting an "EPERM (Operation not permitted)" while trying to open a file. Is this assumption correct, or am I missing something ?

  • C doesn't seem to implement a "fallback-method" in either a "EACCES" nor "EPERM". This seems correct to me, since this doesn't leave any room for confusion. If you try to open a file in a way that you do not have the permissions to do, the program should fail - my opinion.

  • I am aware of that there is a distinct difference between "Permission denied" and "Operation not permitted". And I guess that when mounting NFSv4 over kerberos there is a reason for getting "Permission denied" instead of "Operation not permitted", however some clarification regarding this area would be great.

Of course, adding the appropriate flags to the open-call (ACTION=READ) solves the problem. I'm just curios about my assumptions and if they are correct.


Solution

  • To answer your question, in order:

    • You are correct that gfortran will try to reopen a file in read-only mode when EACCES (or EROFS) is encountered.

    • You are also correct that EPERM is not handled this way, it is not mentioned in the libgfortran source tree at all.

    • As you say, this is a matter of opinion. Gfortran made the decision to do this a long time ago, and it seems to suit the users just fine.

    • I do not understand why NFS v4 returns EPERM in such a case. This seems at odds at least with the documentation in the open(2) Linux manpage that I have access to, where it is only mentioned when O_NOATIME has been specified (which libgfortran does not do). At least, this behavior does not seem to be portable.