Unixファイル名のエンコードについて


25

ファイル名のエンコードがどのように機能するかを理解するのに苦労しています。unix.SEには矛盾する説明があります。

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

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

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

ファイル名が文字として保存される場合、最終的にファイル名がディスク上のビットまたはバイトシーケンスとして終了する必要があるため、何らかの種類のエンコーディングが必要になります。ユーザーが選択できる場合は任意のカーネルに供給されたバイト配列に文字をマップするためのエンコーディングを、作成することが可能である任意の有効なファイル名のバイトシーケンスを。

次のことを想定します。ユーザーがランダムエンコーディングXを使用して、ファイルfooをバイトシーケンスαに変換し、ディスクに保存します。別のユーザーはエンコーディングYを使用します。このエンコーディングでは、αはに変換されますが/、これはファイル名として許可されていません。ただし、最初のユーザーの場合、ファイルは有効です。

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

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

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

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

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

説明は、ファイルシステムは任意の 文字を含むファイル名を格納でき、無効な文字を含むファイル名で停止するのはエンコードを考慮するユーザープログラムのみであるということです。これは、ファイルシステムとカーネルが/。を含むファイル名を問題なく処理できることを意味します。

また、これは間違っていると思います。

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


Nullはすべてのエンコーディングで同じ(0)です。
ケビン

2
@Kevinまったくそうではありません。たとえば、UTF-16、UCS-4(= UTF-32)、またはASCIIの拡張ではない他のほとんどのマルチバイトエンコーディングではありません。
ジル「SO-悪であるのをやめる」

1
実際、Riccardo Murriの答えは、文字ではなくバイトについて言及しているはずです。ほとんどのファイルシステムはバイトを保存します。
ジル 'SO-悪であるのをやめる

@Gilles:さらに別の時間written書かれていることを本当に見ます。
Incnis Mrsi

回答:


25

簡単な答え:Unix / Linux / BSDカーネル、namei()機能に課せられた制限。エンコードはxtermfirefoxやなどのユーザーレベルのプログラムで行われます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制御文字を除き、ゼロ値のバイトは含まれません。UTF-8は、Unixの玉座へのプレテンダーであるPlan-9のために考案されました。

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

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


正しい、namei()1986年頃に放棄されました。新しいUNIXシステムlookuppn()はVFSベースです。
気味悪い

17

カーネルは、アプリケーションがファイル名として指定されたデータをアプリケーションがどのように解釈するかについて、1つも気にしません。

UTF-16文字列のみを扱うCアプリケーションがあると想像してください。そして、適切に構成された入力方法を介して、「名前を付けて保存」プロンプト/ダイアログに∯記号(Unicode 0x222F)を入力します。

アプリケーションが何らかの形式の変換を行わず、それを単純な古いC文字列(char*)で、たとえばfopen書き込みモードで送信すると、カーネルはseeを認識せず、それを想像しようとさえしません。char値のある2つのsが順番に表示されます0x22 0x2FCライブラリに 8ビットの文字とファニーがないと仮定)。
つまり、カーネルの観点からは、有効な文字(")の後に/(ASCII 0x2F)が続きます。fopen戻りますEISDIR(つまり、「ディレクトリのように見え、書き込みモードを要求しました!」)。
∮(Unicode 0x222E)と入力した場合、カーネルは2つの細かい文字を認識し、ASCIIを使用したアプリケーションで見られるように、という名前のファイルを作成します".

私が入っていた場合はa、ファイル名などのアプリケーションでは、アプリケーションがカーネルにUTF-16でそれに沿って通過し、カーネルが読んでいました0x00 0x61し、実際にもそれを考慮していない0x61ので、0x00すでに限りそのまま、文字列を終了します心配している。エラーメッセージは、空のファイル名の場合と同じです(ENOENT私は信じています)。

そのため、カーネルは実際にデータをblobとして受け取ります。それはのストリームですchar。お好みのユーザー空間エンコーディングで無効「の文字は、」生成するものです0x000x2F(「ヌル」と/そのブロブ(カーネルに渡されるバイナリ表現)で)。


私があなたを正しく理解すれば、無効な文字などはありません。無効なバイトシーケンスがあります。値0x000x2Fは、カーネルにハードコードされています。これは、ディレクトリがで区切られているの/ではなく0x2F、使用中のエンコーディングでマッピングされている文字に対応していることを意味します。
マルコ

はい、そのように見たいのであれば、それがアイデアです。(しかしそれは間違っているかもしれません。カーネル/は0x2F ではない「ネイティブエンコーディング」を持っているかもしれません- chars実際には8ビットを使用しないかもしれません。)「伝統的な」ディレクトリセパレータは/です。これは8ビットバイトASCII(たとえばEBCDICではない)システムでは0x27です。
マット

UTF-16BEを想定していますが、UTF-16LEではU + 0061は(nullで終了する)a文字列になります。
Incnis Mrsi

4

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

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

http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.htmlに詳細情報があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.