从fortran调用C的open()函数时文件权限不正确

时间:2011-09-24 21:53:46

标签: fortran fortran90 gfortran

我有一个fortran程序,它调用C函数并使用open()

打开一个文件

main.f90时:

PROGRAM TEST

    integer                        :: oflag, mode

    !Set oflag to O_CREAT|O_RDWR
    oflag = 66   
    mode = 600 

    call test2("test.txt", oflag, mode)

END PROGRAM

test.c的:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>

#pragma weak test2_     = test2
#pragma weak test2__    = test2
#pragma weak TEST2      = test2

void test2(char* filename, int* flag, int* mode)
{
    int fd; 
    if(-1 == (fd = open(filename, *flag, *mode)))
        puts("Returned -1");
}

我编译为:

gcc -c test.c
gfortran main.f90 test.o

当我运行程序时,它会创建文件test.txt,但权限不正确:

---x--x--T 1 xyz users    0 2011-09-24 16:40 test.txt

应该是什么时候

-rw------- 1 xyz users    0 2011-09-24 16:45 test.txt

如果我从另一个C程序调用此函数,它可以正常工作。有人可以指出出了什么问题吗?

规格: 64位linux GNU Fortran(SUSE Linux)4.5.0,GCC(SUSE Linux)4.5.0

谢谢, Kshitij

3 个答案:

答案 0 :(得分:5)

您的常量是错误的,因为权限通常以八进制指定。试试这个程序:

#include <stdio.h>
#include <fcntl.h>

int main(void)
{
 printf("oflag=%d mode=%d\n", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
}

我明白了:

  

oflag = 66 mode = 384

600八进制equals 384十进制。

答案 1 :(得分:2)

open希望你给它一个八进制模式的值,而不是十进制(这就是为什么你在C代码中处理模式时基本上总是看到一个额外的前导零,因为在C中你写了一个八进制带有前导零的文字。

600十进制是八进制的1130。 1130对应于---x-wx--T,你可能有一个022的umask,只剩下---x--x--T

我相信你可以像这样在Fortran中指定一个八进制值:o'600'(这是字母o,然后是单引号内的八进制值)。或者,正如David Schwartz在他的回答中建议的那样,你可以使用你想要的模式的十进制等值。但是,当你稍后回顾它时,这可能会令人困惑。

编辑:MSB指出,虽然GNU Fortran可能是more permissive,但要符合标准,您必须在data中声明八进制常量声明或(自Fortran 2003起)为int(o'600')

答案 2 :(得分:2)

以下是使用Fortran ISO C绑定标准版的示例。 Fortran和C部分之间的便携式接口。在我的计算机上,我发现O_CREAT | O_RDWR具有不同的值,即514,因此将标志设置为特定值是不可移植的。

PROGRAM TEST

    use iso_c_binding

    implicit none

    interface test2_interface

       subroutine test2 ( filename, flag, mode )  bind (C, name="test2")

       import

       character (kind=c_char, len=1), dimension (100), intent (in) :: filename
       integer (c_int), intent (in), VALUE :: flag, mode

       end subroutine test2

    end interface test2_interface


    integer (c_int) :: oflag, mode
    character (kind=c_char, len=100) :: filename


    !Set oflag to O_CREAT|O_RDWR
    oflag = 66  ! incorrect value ... not used
    mode = int ( o'600', c_int)

    filename = "test.txt" // C_NULL_CHAR

    call test2 (filename, oflag, mode)

END PROGRAM

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>

void test2(char* filename, int flag, int mode)
{
    int fd;
    printf ( "filename = '%s'\n", filename );
    flag = O_CREAT | O_RDWR;
    printf ( "flag = %d\n", flag );
    printf ( "mode = octal %o\n", mode );
    if(-1 == (fd = open(filename, flag, mode)))
        puts("Returned -1");
}