2013-01-25 24 views
9

假設操作系統是linux。假設我打開一個文件進行寫入並獲取文件描述符fdw。是否有可能獲得另一個文件描述符fdr,只需訪問該文件而不再調用open?我不想調用open的原因是底層文件可能已被其他進程在文件系統中移動甚至解除鏈接,因此重新使用相同的文件名對於此類操作是不可靠的。所以我的問題是:無論如何打開一個文件描述符具有不同的訪問權限,如果只給一個文件描述符?我想,dupdup2不會更改訪問權限。用另一個訪問重新打開一個文件描述符?

回答

9

是的!訣竅是通過/proc/self/fd/n訪問已刪除的文件。就我所知,這只是一個linux專用的技巧。

運行這個程序:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main() { 
    FILE* out_file; 
    FILE* in_file; 
    char* dev_fd_path; 
    char buffer[128]; 

    /* Write 「hi!」 to test.txt */ 
    out_file = fopen("test.txt", "w"); 
    fputs("hi!\n", out_file); 
    fflush(out_file); 

    /* Delete the file */ 
    unlink("test.txt"); 

    /* Verify that the file is gone */ 
    system("ls test.txt"); 

    /* Reopen the filehandle in read-mode from /proc */ 
    asprintf(&dev_fd_path, "/proc/self/fd/%d", fileno(out_file)); 
    in_file = fopen(dev_fd_path, "r"); 
    if (!in_file) { 
     perror("in_file is NULL"); 
     exit(1); 
    } 
    printf("%s", fgets(buffer, sizeof(buffer), in_file)); 

    return 0; 
} 

它寫一些文本文件,將其刪除,但保留的文件描述符和,然後通過不同的路線重新打開它。直到最後一個保存最後一個文件描述符的進程關閉文件,文件纔會被刪除,在此之前,您可以通過/proc獲取文件內容。


感謝我的老上司阿納託利教我這一招,當我刪除是幸運還是被其它進程附加到一些重要的文件!

+0

這是作弊,因爲他明確表示「沒有再打開」 - 儘管我想如果你真的想這樣做,那是一個你會放鬆的限制。無論如何,他的意思可能是「沒有以相同的方式開放」。 – tvanfosson

+0

謝謝。好答案。 –

+0

什麼是'/ dev/proc/fd/n',是一個錯字?根據你的代碼,它似乎是'/ proc/self/fd /%d'。 – Mehrdad

5

不,fcntl調用不會讓您在打開的文件描述符上設置讀/寫位,並且從現有文件描述符獲取新文件描述符的唯一方法是使用重複功能。撥打dup/dup2/dup3(和fcntl)不允許您更改文件訪問模式。

注意:這對於Linux是正確的,但對於其他一般的Unix來說並非如此。例如,在HP-UX中[請參閱(1)(2)],您可以使用打開的文件描述符上的F_SETFL來更改fcntl的讀/寫位。由於由dup創建的文件描述符共享相同的狀態標誌,但是,更改一個訪問模式將必然會改變另一個。

+0

還注意到'freopen'對'FILE *'流具有類似的功能,因爲訪問模式是否可以改變取決於OS的實現。 – CMCDragonkai