2011-09-24 48 views
0

C'S open()函數時,我有一個Fortran程序使用它調用C函數,並打開一個文件打開()不正確的文件權限調用從FORTRAN

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 

測試。 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

回答

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

600八進制eqals 384(十進制)。

+0

我很困惑,爲什麼它工作時,我稱之爲從C函數,而不是Fortran語言的功能? – jitihsk

+3

你的C調用是什麼樣的?如果使用「0600」,則前導「0」指定八進制(參見[C標準的第6.4.4.1節](http://c0x.coding-guidelines.com/6.4.4.1.html))。 –

+0

你是對的。我在我的C函數中有一個領先的「0」 – jitihsk

2

open希望你給它一個八進制模式的值,而不是十進制的(這就是爲什麼你在處理C代碼模式時基本上總是看到額外的前導零,因爲在C中你寫了一個八進制文字,領先零)。

十進制600爲八進制1130。 1130將對應於---x-wx--T,並且您可能有一個022的umask,使您與---x--x--T

我相信你可以在Fortran中指定一個八進制值,如下所示:o'600'(這是字母o然後是單引號內的八進制值)。或者,正如David Schwartz在他的回答中所建議的那樣,您可以使用您想要的模式的十進制等值。但是,當你稍後回顧它時,這很可能會讓人困惑。

編輯:M. S. B.指出,雖然GNU Fortran語言可能是more permissive,符合標準的,你不得不宣佈在data語句中的八進制常量或(自Fortran 2003的)爲int(o'600')

+0

對於完全符合標準的Fortran,應在Data語句中使用八進制常量,或者從Fortran 2003開始,將其作爲INT內部函數的參數:mode = int (o'600')。 –

+0

@ M.S.B .:正式指出。 –

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"); 
}