web-dev-qa-db-ja.com

Unixファイル名のエンコーディングについて

ファイル名エンコーディングがどのように機能するかを理解するのに苦労しています。 unix.SEで私は矛盾する説明を見つけます。

ファイル名は文字として保存されます

別の回答を引用するには: Linuxでのファイルシステムの文字エンコードに関するいくつかの質問

[…]質問で述べたように、UNIXファイル名は文字のシーケンスにすぎません。カーネルはエンコーディングについて何も知りません。これは完全にユーザー空間(つまり、アプリケーションレベル)の概念です。

ファイル名が文字として格納される場合、最終的にファイル名がディスク上でビットまたはバイトシーケンスになるため、何らかのエンコードが必要になります。ユーザーがanyエンコーディングを選択して、カーネルに供給されるバイトシーケンスに文字をマッピングできる場合、有効なファイル名にanyバイトシーケンスを作成できます。

次のように仮定します。ユーザーはランダムなエンコード[〜#〜] x [〜#〜]を使用して、ファイルを変換しますfooバイトシーケンスαに入れて、ディスクに保存します。別のユーザーがエンコードを使用しています[〜#〜] y [〜#〜]。このエンコーディングでは、α/に変換され、ファイル名としては許可されません。ただし、最初のユーザーのファイルは有効です。

このシナリオは起こり得ないと思います。

ファイル名はバイナリBLOBとして保存されます

別の答えを引用するには: Linuxでファイル名とパスに使用されている文字セットエンコーディングは何ですか?

他の人が指摘したように、これに対する答えは実際にはありません。ファイル名とパスにはエンコードがありません。 OSはバイトシーケンスのみを扱います。個々のアプリケーションはそれらを何らかの方法でエンコードされていると解釈することを選択できますが、これは異なります。

システムが文字を処理しない場合、特定の文字(/またはNULLなど)をファイル名でどのように禁止できますか?エンコーディングなしの/の概念はありません。

ファイルシステムはany文字を含むファイル名を保存でき、無効な文字を含むファイル名を窒息させるのは、エンコーディングを考慮に入れるのはユーザープログラムだけであることを説明します。つまり、ファイルシステムとカーネルは、/を含むファイル名を問題なく処理できます。

これも間違っていると思います。

エンコードはどこで行われ、特定の文字を許可しないという制限はどこにありますか?

25
Marco

短い答え:Unix/Linux/BSDカーネル、namei()関数に課せられた制限。エンコードは、xtermfirefoxlsなどのユーザーレベルのプログラムで行われます。

あなたは間違った前提から始めていると思います。 Unixのファイル名は、任意の値を持つバイトの文字列です。いくつかの値、0x0(ASCII Nul)と0x2f(ASCII '/')は、マルチバイト文字エンコーディングの一部としてではなく、何でも許可されていません。 「バイト」には、文字を表す数値を含めることができます(ASCIIおよびその他のエンコーディング))が、「文字」には1バイト以上が必要になる場合があります(たとえば、UTF-で0x7fを超えるコードポイントUnicodeの8つの表現)。

これらの制限は、ファイル名の印刷規則とASCII文字セットです。元のUnixで使用されていたASCII '/'(数字で0x2f)の値のバイトで区切られています。部分的または完全に修飾されたパス( '/ usr/bin/cat'には "usr"、 "bin"、​​ "cat"の断片があります)使用された元のUnixはASCII Nul to terminate文字列。これらの2つの値以外のファイル名のバイトは、他の値をとることがあります。これのエコーは、UnicodeのUTF-8エンコーディングで確認できます。PrintableASCII文字を含む '/ '、UTF-8で1バイトのみを使用します。上記のコードポイントのUTF-8には、Nul制御文字を除いて、ゼロ値のバイトは含まれません。UTF-8は、Plan-9、The Prenender to the Throneのために発明されましたUnix。

古いUnix(およびLinuxのように見える)には、一度に1バイトずつパスを調べ、0x2F値のバイトでパスを分割し、ゼロ値のバイトで停止するnamei()関数がありました。 namei()はUnix/Linux/BSDカーネルの一部であるため、例外的なバイト値が適用されます。

ここまでは、文字ではなくバイト値について説明してきました。 namei()は、バイトに文字セマンティクスを適用しません。これは、lsのようなユーザーレベルのプログラム次第です。これは、バイト値または文字値に基づいてファイル名をソートする場合があります。 xtermは、文字エンコードに基づいて、ファイル名に使用するピクセルを決定します。 xtermを指定しないと、UTF-8でエンコードされたファイル名を持っているので、それを呼び出すと、意味不明なことが多く見られます。 vimがUTF-8(または、UTF-16、UTF-32)エンコーディングを検出するようにコンパイルされていない場合、UTF-8を含む「テキストファイル」を開くと、意味不明なことが多く表示されます。エンコードされた文字。

25
Bruce Ediger

バイトと文字の分離は、Unixが設計されてからかなりの時間を要しました。それが設計されたとき、単語の使用は8(または6、または9)ビットがどのように解釈されたかについて何かを伝えましたが、単語エンコーディングはそうではありませんでした言及した。

ファイル名はバイトのシーケンスです。 0x2f "/"以外のバイトは許可されます。文字列ターミネータとして使用されているため、0x00を含むバイトはカーネルに到達することさえできません。アプリケーションは、選択したエンコーディングに従ってバイトシーケンスを解釈できます。それが厄介に聞こえるなら、私はそれがそうだと思います。

詳細は http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html をご覧ください。

4
John S Gruber