2012-12-05 23 views
1

我想要什麼:如何從標準FILE結構中獲取文件名?

void printFname(FILE * f) 
    {  
     char buf[255]; 
     MagicFunction(f,buf); 
     printf("File name: %s",buf); 
    } 

所以,我需要的是 「MagicFunction」,但unfortunatelly I haven't found such ...

有什麼辦法來實現,在使用OS庫? (windows.h,cocoa.h,posix.h等)

+0

可能的重複[如何從FILE \ *結構在C中獲取文件的名稱](http://stackoverflow.com/questions/7988784/how-to-get-a-files-name-from-file- struct-in-c) – dasblinkenlight

+0

從我的角度來看,@dasblinkenlight在該線程中沒有答案。 – 0x6B6F77616C74

+0

有人回答,並且回答正確。 –

回答

8

沒有這樣的功能。可能沒有文件名或與FILE *對應的多個文件名。在Unix上,程序在重命名或刪除後可以繼續引用文件,這可能意味着您的文件名不存在FILE *。或者可以對文件進行更多的硬鏈接,這意味着文件可以有多個名稱;你會選哪一個?爲了進一步混淆事物,可以通過在包含該文件的目錄上安裝文件系統來臨時隱藏文件。該文件仍然位於磁盤上,位於其原始路徑名中,但該文件在該路徑上將無法訪問,因爲該安裝程序會遮蓋該文件。

也有可能FILE *根本不對應文件系統上的文件;雖然他們通常會這樣做,但您可以使用fdopen()從任何文件描述符創建一個文件描述符,並且該文件描述符可能是管道,套接字或其他類似文件的對象,它們在磁盤上從來沒有路徑。在C庫的某些版本中,您可以打開一個字符串流(例如,glibc中的fmemopen()),因此FILE *實際上只對應於內存緩衝區。

如果您關心該名稱,最好只跟蹤打開文件時命名的內容。

有一些hacky的方法來近似獲取文件名;如果您只是將其用於調試或信息目的,那麼它們可能就足夠了。其中大多數將需要在文件描述符而不是FILE *上運行,因爲文件描述符是引用文件的較低級別方式。要獲取文件描述符,請在FILE *上運行fileno(),並記住在沒有與該文件關聯的文件描述符FILE *時檢查錯誤。

在Linux上,您可以在"/proc/self/fd/fileno"上執行readlink(),其中fileno是文件描述符。這會告訴你文件打開時文件的文件名是什麼,或者是一個字符串,表示它是什麼類型的文件描述符,比如套接字或inotify句柄。 FreeBSD和NetBSD都有Linux仿真層,其中包括模擬Linux風格的procfs;如果你安裝了一個Linux兼容的procfs,你也許可以在這些上做到這一點,儘管我沒有它們可用於測試。

在Mac OS X上,您沒有/proc/self/fd。如果你不關心如何找到原始文件名,但是引用文件的其他文件名可以起作用(這樣你就可以將它傳遞給另一個程序),你可以構造一個:/.vol/deviceid/inode。例如,/.vol/234881030/281363。要獲取這些值,請在文件描述符上運行fstat(),並在生成的struct stat上使用st_devst_ino

在Windows上,文件和文件系統的工作方式與Unix完全不同。顯然,可以在Windows上將文件映射回其名稱。從Windows Vista開始,您只需撥打GetFinalPathNameByHandle()即可。這需要一個HANDLE;從文件描述符中獲取HANDLE,請致電_get_osfhandle()。在Windows Vista之前,您需要做更多的工作,如this article中所述。請注意,在Windows上fileno()被命名爲_fileno(),雖然前者可能會發出警告。

進一步進入hacky領域,還有一些技巧可以使用。你可以掏出lsof,或者你可以提取它用來解析路徑名的代碼。 lsof實際上直接在內核內存中查看,從內核的名稱緩存中提取信息。這有幾個限制,在the lsof FAQ中列出。當然,您需要root或相當的權限才能直接或通過suid/sgid二進制文件來執行此操作。最後,對於尋找與打開的文件相匹配的一個或多個文件名的便攜式但速度慢的解決方案,您可以在文件描述符上使用fstat()找到設備和inode編號,然後遞歸遍歷文件系統stat(),直到找到具有匹配設備和inode編號的文件。請記住我上面提到的警告;您可能會發現沒有匹配的文件,多個匹配的文件,即使沒有找到任何匹配的文件,該文件可能仍然存在,但被掛載點隱藏。當然,可能存在競爭條件;有些東西可能會重新命名文件,以至於在遍歷層次結構時永遠不會看到它。

+0

+1用於指示非常規解決方案。 – Jack

+1

我想'fstat()'得到inode,然後解決它。這樣更好。 – xiaoyi

+0

@xiaoyi的確,您可以'fstat()'獲取設備和inode,然後遍歷目錄樹以查找具有匹配設備和inode的文件。我已經提到,如果您真的需要盡最大努力找到該文件,並且無法使用Mac或Linux特定的答案,那麼作爲緩慢,便攜式的解決方案。 –

2

沒有這樣的標準功能。

0

你自己是fopen()嗎?如果接下來,請保留FILE *以自己爲文件名散列表。

否則,一般情況下是不可能的。

0

我不認爲即使在windows.h,coca.h或unistd.h也有這樣的功能。 很可能你自己寫。只是做一個

struct myFile { 
FILE *fh; 
char *filename; 
} 

並保持這種結構成的struct myFile陣列和MagicFunction(f,b)散步陣列尋找地址等於f上。

相關問題