opendir 和 readdir 背後編碼字串?

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 只是獲取我給定的文件名並將其與正確的目錄條目相匹配,那麼我會認為應該沒有問題找到索引節點並開啟目錄。這似乎表明 opendir 對檔案名稱並不完全誠實。

opendir 報告的目錄條目中的檔案名稱不是磁碟上實際的檔案名稱(即它們是否被編碼)?如果是這樣,有什麼方法可以控制 opendir 和 readdir 如何編碼名稱,或者使用一些其他處理原始位元組的系統調用,而不是在我背後編碼內容?一般來說,我發現在什麼級別的編碼發生時非常令人困惑,我希望得到任何解釋或更好的理解這一點的參考!謝謝!

答案1

opendir它們readdir本身就以位元組為單位工作。他們不執行和重新編碼。

某些檔案系統驅動程式可能會對位元組序列施加限制。例如,HFS+ 使用專有的 Unicode 標準化方案標準化檔案名稱。我希望返回的表格readdir在傳遞給opendir,就像 OP 中的那樣Ubuntu 論壇主題jw013 提及,我懷疑 HFS+ 驅動程式中存在錯誤。這是不是唯一的程序HFS+ 上的 Hangul 會觸發該錯誤。甚至 OSX似乎有麻煩統一碼正常化。

相關內容