ファイル名のエンコーディングがどのように機能するかを理解するのが困難です。 unix.SEで矛盾する説明が見つかりました。
文字で保存されたファイル名
他の答えを引用するには: Linuxのファイルシステム文字エンコーディングに関するいくつかの質問
[...]あなたの質問で述べたように、UNIXファイル名は単なる文字列であり、カーネルはエンコードについて全く知らず、完全にユーザースペース(アプリケーションレベル)の概念です。
ファイル名が文字として保存されている場合、最終ファイル名はディスクにビットまたはバイトのシーケンスとして表示される必要があるため、一部のエンコーディングを含める必要があります。ユーザーが選択できる場合どのエンコーディングは、文字をカーネルに供給されるバイトシーケンスにマッピングして生成できます。どの有効なファイル名の一連のバイトです。
以下を想定します。ユーザーはランダムエンコーディングを使用します。X、ファイルをfoo
一連のバイトに変換します。αそしてディスクに保存します。他のユーザーがエンコードを使用します。はい。このエンコーディングではαに変換します/
。ファイル名として使用できません。ただし、最初のユーザーの場合、ファイルは有効です。
私はこれが起こるとは思わない。
バイナリブロブとして保存されたファイル名
他の答えを引用するには: Linuxでは、ファイル名とパスにどの文字セットエンコーディングが使用されますか?
他の人が指摘したように、これに対する実際の答えはありません。ファイル名とパスはエンコードされません。オペレーティングシステムはバイトシーケンスのみを処理します。個々のアプリケーションは特定の方法でエンコードされたと解釈することを選択できますが、これはさまざまです。
システムが文字を処理しない場合、ファイル名の特定の文字(/
または)を抑制するにはどうすればよいですか?コーディングがなければ、NULL
aの概念もありません。/
1つの説明は、ファイルシステムが以下を含むファイル名を保存できることです。どの
文字がある場合は、エンコードを検討しているユーザープログラムのみが、無効な文字を含むファイル名をブロックします。これは、最終的にファイルシステムとカーネルが問題なく包含を処理できることを意味します/
。
私もこれが間違っていると思います。
エンコーディングはどこで行われ、特定の文字を許可しない制限はどこにありますか?
答え1
短い答え:namei()
Unix / Linux / BSDカーネル機能に課される制限です。エンコードは、または同じユーザーレベルのプログラムで発生しますxterm
。firefox
ls
私はあなたが間違った前提から始めていると思います。 Unixのファイル名は、任意の値を持つバイト文字列です。一部の値、0x0(ASCII Nul)、および0x2f(ASCII '/')は、マルチバイト文字エンコーディングの一部として許可されていません。 「バイト」には文字を表す数値(ASCIIやその他のエンコード)を含めることができますが、「文字」には1バイト以上が必要になる場合があります(UnicodeのUTF-8表現では0x7f以上のコードポイントなど)。
これらの制限は、ファイル名の印刷規則とASCII文字セットが原因で発生します。元のUnixでは、ASCII '/'(数値0x2f)の値バイトを使用して部分パスまたはフルパスの断片を分離しました(例: '/usr/bin/cat'では 'usr'、 'bin'、および 'cat'フラグメントあり)。もともとUnixでは、文字列を終了するためにASCII Nulを使用しました。これら2つの値に加えて、ファイル名のバイトは異なる値を持つことができます。 UnicodeのUTF-8エンコーディングでこれを確認できます。印刷可能なASCII文字( "/"を含む)はUTF-8で1バイトしか占めません。上記のコードポイントのUTF-8には、Nul制御文字を除いて値が0のバイトは含まれていません。 UTF-8はUnixの王座を狙うPlan-9のために発明されました。
以前のUnix(Linuxのように見えます)には、namei()
パスを一度に1バイトずつ調べて、0x2F値バイトからパスをフラグメントに分割し、値が0のバイトで停止する機能がありました。 namei()
Unix/Linux/BSD カーネルの一部なので、例外バイト値が適用される場所です。
これまで、文字ではなくバイト値について説明しました。 namei()
バイトには文字セマンティクスは適用されません。これはls
、たとえば、バイト値または文字値に基づいてファイル名をソートできるユーザーレベルのプログラムによって異なります。xterm
ファイル名で点灯するピクセルは、文字エンコーディングによって決まります。 UTF-8でエンコードされたファイル名があることを教えてくれない場合は、xterm
呼び出し時に横たわる言葉がたくさん表示されます。 UTF-8(またはすべてのUTF-16、UTF-32)エンコードを検出するようにコンパイルされていない場合、vim
UTF-8でエンコードされた文字を含む「テキストファイル」を開くと、多くの横説説が表示されます。
答え2
問題は、カーネルがアプリケーションがファイル名で提供されたデータをどのように解釈するかをまったく気にしないことです。
UTF-16文字列を特別に扱うCアプリケーションがあるとしましょう。適切に設定された入力方法で、「名前を付けて保存」のプロンプト/ダイアログボックスに∯記号(Unicode 0x222F)を入力しました。
アプリケーションが何らかの変換を行わずにそれを通常のC文字列(書き込みモードなど)にchar*
送信すると、fopen
カーネルは∯を見ることができず、それを想像しようとすることもできません。char
値を含む2つのsが順番に表示されます0x22 0x2F
(8ビット文字とCライブラリには面白いコンテンツはありません)。
つまり、カーネルの観点から見ると、有効な文字("
)の後に/
(ASCII 0x2F)が続きます。fopen
返されますEISDIR
(たとえば、「ディレクトリのように見えますが、書き込みモードを要求しました!」)。
∮(Unicode)を入力すると、0x222E
カーネルは2つのクールな文字をチェックし、ASCII言語アプリケーションで見られるように名前が".
。
私のアプリケーションにファイル名を入力し、a
アプリケーションがそれをUTF-16としてカーネルに渡すと、カーネルはそれを読み取り、実際には文字列がすでに終了しているので考慮し0x00 0x61
ません。エラーメッセージは空のファイル名と同じです(私の考えでは)。0x61
0x00
ENOENT
したがって、カーネルはデータを汚れとして扱います。これはストリームですchar
。選択したユーザー空間エンコーディングで無効な「文字」は、blob(カーネルに渡されたバイナリ表現)または0x00
(「null」と)を生成する文字です。0x2F
/
答え3
バイトと文字の分離は、Unixが設計されてから長い間行われました。設計時に、これらの単語の使用は8(または6または9)ビットの解釈方法に関する情報のみを渡しましたが、コーディング言及されていません。
ファイル名はバイトのシーケンスです。 0x2f "/"を除くすべてのバイトが許可されます。 0x00を含むバイトは文字列ターミネータとして使用されるため、カーネルに到達することもできません。アプリケーションは、選択したエンコーディングに従ってバイトシーケンスを解釈できます。これが混乱していると思われると思います。
詳細は以下で確認できます。http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html役に立つと思うかもしれません。