私の知らないところで 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 はディレクトリ エントリの表示に問題がないように見えます。inode 番号は存在し、ディレクトリとして正しくマークされています (4 はディレクトリを意味します)。また、ファイル名は UTF-8 エンコードで保存されているようです。これは、これらの 16 進数が韓国語のファイル名の正しい UTF-8 コードであるためです。しかし、これらのディレクトリの 1 つに対して readdir を実行するとします (背後で何も起こらないように細心の注意を払うため、ファイル名は 16 進数で使用します)。

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 が名前をエンコードする方法を制御する方法、または背後でエンコードする代わりに生のバイトで動作する他のシステム コールを使用する方法はありますか? 一般的に、どのレベルでエンコードが行われているのか非常にわかりにくいので、説明や、さらに良いのは、これを理解するためのリファレンスがあればありがたいです。ありがとうございます!

答え1

opendirそれreaddir自体はバイトに対して動作します。再エンコードは実行しません。

一部のファイルシステムドライバは、バイトシーケンスに制約を課す場合があります。たとえば、HFS+は、独自のUnicode正規化スキームを使用してファイル名を正規化します。ただし、readdirに渡されたときに、 によって返される形式が機能することを期待しています。opendirUbuntu フォーラムスレッドそれジェーエム 言及された、HFS+ドライバのバグだと思われます。唯一のプログラムではないこれは、HFS+ 上のハングルによってトリップされます。OSXでも問題があるようだユニコード正規化。

関連情報