opendir 和 readdir 在我背後編碼字元串?
(如果你能回答這個問題,你可以跳過最後幾行的細節:))
我在 Ubuntu 12.04 上。我正在嘗試解決我過去發布的一個舊問題(如果您好奇:https ://superuser.com/questions/339877/trouble-viewing-files-with-non-english-names -on-hard-disk/339895#339895)。Linux、Mac、HFS+ 和韓文命名文件之間存在一個已知的兼容性問題,我今天花了一整天的時間試圖最終找到某種解決方法。
基本上,我已經將我的 HFS+ 驅動器安裝到了 linux 上。正常的 ls 和 cd 無法訪問文件,因為它們是韓文的。所以我編寫了一個 C 程序來嘗試在最低級別訪問這些文件,這樣我就可以更加確定在我背後不會發生任何事情:
DIR* dp; struct dirent *ep; char* parent = "/media/external/Movies"; dp = opendir( parent ); if( dp != NULL ) { while( ep = readdir(dp) ) { printf( "%d %s %X\t", ep->d_ino, ep->d_name, ep->d_type ); // now print out the filenames in hex for( int i = 0; i != strlen( ep->d_name ) ; i++) { printf( "0x%X " , ep->d_name[i] & 0xff ); } printf("\n"); } closedir(dp); } else { perror("Couldn't open the directory! "); }
這是我為此獲得的輸出範例:
433949 密陽 4 0xEB 0xB0 0x80 0xEC 0x96 0x91
413680 蝙蝠 4 0xEB 0xB0 0x95 0xEC 0xA5 0x90
434033 박하사탕 4 0xEB 0xB0 0x95 0xED 0x95 0x98 0xEC 0x82 0xAC 0xED 0x83 0x95
所以從表面上看,openddir 查看目錄條目似乎沒有問題。索引節點號在那裡,它們被正確標記為目錄(4 表示目錄),並且文件名似乎儲存為 UTF-8 編碼,因為這些十六進制是韓國文件名的正確 UTF-8 程式碼。但是現在,如果我要對其中一個目錄執行 readdir(並且我將使用十六進制的文件名,以格外小心,以免在我背後發生任何事情):
unsigned char new_dirname[] = {'/',0xEB,0xB0,0x80,0xEC,0x96,0x91,'\0'}; unsigned char final[ strlen(parent) + strlen(new_dirname) + 1 ]; memcpy(final, parent, strlen( parent )); strcpy(final + strlen(parent), dirname ); dp = opendir( final ); // dp == NULL here!!!
它無法打開目錄。這讓我感到困惑,因為如果 opendir 只是在目錄條目中報告文件名的原始位,而 readdir 只是獲取我給定的文件名並將其與正確的目錄條目匹配,那麼我會認為應該沒有問題找到inode並打開目錄。這似乎表明 opendir 對文件名並不完全誠實。
opendir 報告的目錄條目中的文件名是否不是磁碟上的實際文件名(即它們是否被編碼)?如果是這樣,有什麼方法可以控制 opendir 和 readdir 如何編碼名稱,或者使用其他一些可以處理原始字節的系統呼叫,而不是在我背後編碼東西?總的來說,我發現正在發生什麼級別的編碼非常令人困惑,我將不勝感激任何解釋,或者更好的是理解這一點的參考!謝謝!
opendir
並且readdir
他們自己在字節上工作。他們不執行和重新編碼。一些文件系統驅動程序可能會對字節序列施加約束。例如,HFS+ 使用專有的 Unicode 規範化方案規範化文件名。但是,我希望返回的表單
readdir
在傳遞給 時可以正常工作opendir
,因此就像jw013提到的Ubuntu 論壇執行緒中的 OP 一樣,我懷疑 HFS+ 驅動程序中存在錯誤。它不是HFS+ 上被 Hangul 絆倒的唯一程序。甚至 OSX似乎在Unicode規範化方面也遇到了麻煩。