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

发布于 2024-12-06 05:54:39 字数 1105 浏览 0 评论 0原文

我有一个 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

我 如果我从另一个 C 程序调用这个函数,它应该可以

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

正常工作。有人可以指出出了什么问题吗?

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

谢谢, 克什蒂吉

I have a fortran program which calls a C function and opens a file using 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");
}

I compile as:

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

When I run the program, it creates the file test.txt, but with incorrect permissions:

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

when it should have been

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

If I call this function from another C program, it works fine. Can someone point out what is going wrong?

Specs:
64 bit linux
GNU Fortran (SUSE Linux) 4.5.0, GCC (SUSE Linux) 4.5.0

Thanks,
Kshitij

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

氛圍 2024-12-13 05:54:39

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

#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 模式=384

600 八进制等于 384 十进制。

Your constants are wrong because permissions are typically specified in octal. Try this program:

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

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

I get:

oflag=66 mode=384

600 octal eqals 384 decimal.

请恋爱 2024-12-13 05:54:39

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

十进制的 600 八进制的 1130。 1130 对应于 ---x-wx--T,并且您的 umask 可能为 022,留下 ---x--x--T

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

编辑:MSB指出,虽然GNU Fortran可能是更宽松,为了符合标准,您必须在 data 语句中声明一个八进制常量,或者(自 Fortran 2003 起)如下int(o'600')

open expects you to give it a value for the mode in octal, not decimal (this is why you basically always see an extra leading zero when dealing with modes in C code, since in C you write an octal literal with a leading zero).

600 in decimal is 1130 in octal. 1130 would correspond to ---x-wx--T, and you likely have a umask of 022, leaving you with ---x--x--T.

I believe you can specify an octal value in Fortran like this: o'600' (that's the letter o and then the octal value inside single quotes). Or, as David Schwartz suggested in his answer, you can just use the decimal equivalent of the mode you want. That's likely to be confusing when you look back at it later, though.

Edit: M. S. B. has pointed out that, while GNU Fortran may be more permissive, to comply with the standard you'd have to declare an octal constant in a data statement or (since Fortran 2003) as int(o'600').

傲影 2024-12-13 05:54:39

下面是一个使用 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");
}

Here is an example using the Fortran ISO C Binding for a standard & portable interface between the Fortran and C portions. On my computer I found O_CREAT|O_RDWR to have a different value, i.e., 514, so setting flag to a specific value is not portable.

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

and

#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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文