Неправильные права доступа к файлу при вызове функции open () в C из fortran - PullRequest
0 голосов
/ 25 сентября 2011

У меня есть программа на фортране, которая вызывает функцию 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 ]

5 голосов
/ 25 сентября 2011

Ваши константы неверны, потому что разрешения обычно указываются в восьмеричном виде. Попробуйте эту программу:

#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 восьмеричных эквивалентов 384 десятичных.

2 голосов
/ 25 сентября 2011

Вот пример использования Fortran ISO C Binding для стандартного и портативного интерфейса между портами 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");
}
2 голосов
/ 25 сентября 2011

open ожидает, что вы зададите ему значение для режима в восьмеричном, а не десятичном (поэтому вы в основном всегда видите дополнительный начальный ноль при работе с режимами в коде C, поскольку в C вы пишете восьмеричный литерал с ведущий ноль).

600 в десятичном виде - 1130 в восьмеричном. 1130 будет соответствовать ---x-wx--T, и вы, вероятно, получите umask 022, в результате чего вы получите ---x--x--T.

Я полагаю, что вы можете указать восьмеричное значение в Фортране следующим образом: o'600' (это буква o, а затем восьмеричное значение в одинарных кавычках). Или, как предложил Дэвид Шварц в своем ответе, вы можете просто использовать десятичный эквивалент режима, который вы хотите. Впрочем, это может сбить с толку, если вы оглянетесь на это позже.

Редактировать : MSB указал, что, хотя GNU Fortran может быть более разрешительным , для соответствия стандарту вы должны объявить восьмеричную константу в data заявление или (начиная с Фортрана 2003) как int(o'600').

...