Fortran OPEN 调用在 NFSv3 和 NFSv4 上有所不同
Fortran OPEN-call differs on NFSv3 vs NFSv4
我试图理解为什么你可以在 NFSv3 上以读写模式对你只有读权限的文件进行 OPEN 调用,而如果你做同样的事情在 NFSv4 上,OPEN 调用将失败。
让我解释一下,下面是一个简单的 fortran 程序,它以读写模式打开给定文件(程序的参数),
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
将以上内容保存在 test_open.f90 中并使用
进行编译
gfortran -o fortran test_open.f90
现在,使用 NFSv3 在挂载点上执行以下命令,
strace -eopen ./fortran file-with-only-read-permissions
您应该会看到以下几行(以及许多其他输出),
> open("file-with-only-read-permissions", O_RDWR) = -1 EACCES (Permission denied)
> open("file-with-only-read-permissions", O_RDONLY) = 3
所以,我们可以清楚地看到我们在 'O_RDWR' 中尝试打开时得到一个 "EACCES (Permission denied)" (打开读写), 但 紧随其后我们看到另一个 open O_RDONLY (以只读方式打开)并且成功了。
运行 NFSv4 共享文件上的相同程序,我们得到以下内容,
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)
所以,这里我们在尝试打开 'O_RDWR' 中的文件(打开读写)时得到一个 "EPERM (Operation not permitted)",仅此而已(即应用程序失败)。
用一个小的测试程序在 C 中做同样的测试,在这两种情况下都无法打开文件(也就是说,在获取 "EACCES" 在 NFSv3 上)。
所以对于问题,
我假设上述行为是由于在 fortran 中执行了 OPEN 调用,并且如果 fortran 在尝试打开文件时获得 "EACCES (Permission denied)",它将自动尝试以只读方式打开文件 (O_RDONLY)。这个假设是否正确?
我还假设 Fortran 在尝试打开文件时得到 "EPERM (Operation not permitted)" 时没有这个 "fallback-method"。这个假设是正确的,还是我遗漏了什么?
C 似乎没有在 "EACCES" 和 "EPERM" 中实现 "fallback-method"。这对我来说似乎是正确的,因为这不会留下任何混淆的余地。如果您尝试以您没有权限的方式打开文件,程序应该会失败——我的意见。
我知道 "Permission denied" 和 "Operation not permitted" 之间有明显的区别。我想当在 kerberos 上安装 NFSv4 时,有理由得到 "Permission denied" 而不是 "Operation not permitted",但是关于这个领域的一些澄清会很好。
当然,在打开调用 (ACTION=READ) 中添加适当的标志可以解决问题。我只是好奇我的假设以及它们是否正确。
回答你的问题,顺序是:
你说得对,当遇到 EACCES(或 EROFS)时,gfortran 会尝试以只读模式重新打开文件。
EPERM 没有以这种方式处理也是正确的,libgfortran 源代码树中根本没有提到它。
如你所说,见仁见智。 Gfortran 很早以前就决定这样做了,看起来很适合用户。
我不明白为什么 NFS v4 returns EPERM 会出现这种情况。这似乎至少与我有权访问的 open(2) Linux 联机帮助页中的文档不一致,其中仅在指定 O_NOATIME 时提及(libgfortran 不这样做)。至少,这种行为似乎不可移植。
我试图理解为什么你可以在 NFSv3 上以读写模式对你只有读权限的文件进行 OPEN 调用,而如果你做同样的事情在 NFSv4 上,OPEN 调用将失败。
让我解释一下,下面是一个简单的 fortran 程序,它以读写模式打开给定文件(程序的参数),
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
将以上内容保存在 test_open.f90 中并使用
进行编译gfortran -o fortran test_open.f90
现在,使用 NFSv3 在挂载点上执行以下命令,
strace -eopen ./fortran file-with-only-read-permissions
您应该会看到以下几行(以及许多其他输出),
> open("file-with-only-read-permissions", O_RDWR) = -1 EACCES (Permission denied)
> open("file-with-only-read-permissions", O_RDONLY) = 3
所以,我们可以清楚地看到我们在 'O_RDWR' 中尝试打开时得到一个 "EACCES (Permission denied)" (打开读写), 但 紧随其后我们看到另一个 open O_RDONLY (以只读方式打开)并且成功了。
运行 NFSv4 共享文件上的相同程序,我们得到以下内容,
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)
所以,这里我们在尝试打开 'O_RDWR' 中的文件(打开读写)时得到一个 "EPERM (Operation not permitted)",仅此而已(即应用程序失败)。
用一个小的测试程序在 C 中做同样的测试,在这两种情况下都无法打开文件(也就是说,在获取 "EACCES" 在 NFSv3 上)。
所以对于问题,
我假设上述行为是由于在 fortran 中执行了 OPEN 调用,并且如果 fortran 在尝试打开文件时获得 "EACCES (Permission denied)",它将自动尝试以只读方式打开文件 (O_RDONLY)。这个假设是否正确?
我还假设 Fortran 在尝试打开文件时得到 "EPERM (Operation not permitted)" 时没有这个 "fallback-method"。这个假设是正确的,还是我遗漏了什么?
C 似乎没有在 "EACCES" 和 "EPERM" 中实现 "fallback-method"。这对我来说似乎是正确的,因为这不会留下任何混淆的余地。如果您尝试以您没有权限的方式打开文件,程序应该会失败——我的意见。
我知道 "Permission denied" 和 "Operation not permitted" 之间有明显的区别。我想当在 kerberos 上安装 NFSv4 时,有理由得到 "Permission denied" 而不是 "Operation not permitted",但是关于这个领域的一些澄清会很好。
当然,在打开调用 (ACTION=READ) 中添加适当的标志可以解决问题。我只是好奇我的假设以及它们是否正确。
回答你的问题,顺序是:
你说得对,当遇到 EACCES(或 EROFS)时,gfortran 会尝试以只读模式重新打开文件。
EPERM 没有以这种方式处理也是正确的,libgfortran 源代码树中根本没有提到它。
如你所说,见仁见智。 Gfortran 很早以前就决定这样做了,看起来很适合用户。
我不明白为什么 NFS v4 returns EPERM 会出现这种情况。这似乎至少与我有权访问的 open(2) Linux 联机帮助页中的文档不一致,其中仅在指定 O_NOATIME 时提及(libgfortran 不这样做)。至少,这种行为似乎不可移植。