2010-03-07 160 views
19

我正嘗試在Linux(Ubuntu)的C上創建一個只寫文件。 這是我的代碼:在Linux中使用C創建文件

int fd2 = open ("/tmp/test.svg", O_RDWR|O_CREAT); 

if (fd2 != -1) { 
    //.... 
} 

可是爲什麼我創建的文件有「XR」模式?我怎樣才能創建它,以便我可以在命令提示符下自己打開它?

------xr-- 1 michael michael 55788 2010-03-06 21:57 test.txt* 
------xr-- 1 michael michael 9703 2010-03-06 22:41 test.svg* 
+2

不安全代碼的絕妙例子。 – 2010-03-07 07:27:16

+2

@邁克爾Foukarakis:暫時,有更大的問題需要處理,但你是對的。應該添加O_EXCL(以避免遵循惡意破壞的符號鏈接,並避免在同一臺計算機上運行同一程序時剽竊其他人的文件);固定名稱在生產代碼中會有問題,所以它應該使用''mkstemp()''或者一個相關來創建文件名。毫無疑問,這份名單仍在繼續。 – 2010-03-07 07:30:58

回答

31

當您指定O_CREAT時,需要open()的三參數形式。當你省略第三個參數時,open()使用任何恰好在第三個參數預期的堆棧上的值;這很少是一組連貫的權限(在你的例子中,似乎十進制12 =八進制014在堆棧中)。

第三個參數是文件的權限 - 將由umask()值修改。

int fd2 = open("/tmp/test.svg", O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 

注意,您可以創建一個沒有寫權限的文件(給其他人,或任何其他進程),同時還能夠從目前的進程寫入。很少需要在從程序創建的文件上使用執行位 - 除非您正在編寫一個編譯器(並且「.svg」文件通常不是可執行文件!)。

的S_xxxx標記來自<sys/stat.h><fcntl.h> - 您可以使用頭獲取的信息(但open()本身是在<fcntl.h>聲明)。

請注意,固定的文件名和缺少保護選項(如O_EXCL)會使修改後的open()調用有些不安全。

+1

如果你有兩個glibc頭文件和gcc的最新版本,gcc可以警告你關於'open'的第三個參數。 – caf 2010-03-07 07:27:13

+0

@Jonathan:我發佈的內容有錯嗎?您提到過在生產代碼中使用固定名稱的惡意破壞符號鏈接和問題。這些問題是什麼/爲什麼? – 2010-03-07 08:07:01

+1

@nvl:假設兩個用戶bill和joe都同時運行你的程序。兩者都創建一個文件/tmp/test.svg...使用哪些數據?假設Malicious先生在您的機器上工作,並設法執行:'ln -s/etc/passwd/tmp/test.svg'。當你的程序運行時,現在有兩件事情會發生:(1)由於你不能寫入/ etc/passwd(你不是root用戶),或者(2)你得到/ etc/passwd中的SVG圖像,因爲你是root用戶。通常都不被認爲是可取的。 Malicious先生也可以這樣做:'ln -s /usr/lib/security/libmalpam.so /tmp/test.svg' ... – 2010-03-07 08:10:47

1

提供訪問權限作爲第三個參數:

int fd2 = open("/tmp/test.svg", O_RDWR|O_CREAT, 0777); // Originally 777 (see comments) 

if (fd2 != -1) { 
    // use file descriptor 
    close(fd2); 
} 

通過這樣做,所有的讀,寫和執行權限將給予用戶,組和其他。根據您的使用修改第三個參數。

+1

777與S_IRWXU | S_IRWXG | S_IRWXO。 0x777碰巧是一樣的,但是編碼實踐很差。 – prewett 2013-12-17 11:00:12

+3

請注意,777(十進制)和0x777(十六進制)都不是正常的0777(八進制)或「S_IRWXU | S_IRWXG | S_IRWXO'爲用戶,組和其他人提供對文件的讀取,寫入和執行訪問。所以,之前的評論「0x777碰巧是相同的」是錯誤的。它對應於:r-xrwSrwt(設置了SGID位,設置了SVTX位,加上0567權限,我沒有耐心象徵性地寫出它 - 它需要7個術語或一起)。 – 2014-01-13 15:42:24