Mar*_*rco 26 character-encoding special-characters filenames locale
我很难理解文件名编码是如何工作的。在 unix.SE 上,我发现了相互矛盾的解释。
引用另一个答案: 关于 linux 上文件系统字符编码的几个问题
[...] 正如您在问题中提到的,UNIX 文件名只是一个字符序列;内核对编码一无所知,这完全是一个用户空间(即应用程序级)概念。
如果文件名存储为字符,则必须涉及某种编码,因为最终文件名必须以位或字节序列的形式出现在磁盘上。如果用户可以选择任何编码将字符映射到提供给内核的字节序列,则可以为有效文件名创建任何字节序列。
假设如下: 用户使用随机编码X,将文件foo转换为字节序列? 并将其保存到磁盘。另一个用户使用编码Y。在这种编码中?转换为/,不允许作为文件名。但是,对于第一个用户,该文件是有效的。
我认为这种情况不会发生。
引用另一个答案: Linux 上的文件名和路径使用什么字符集编码?
正如其他人所指出的,对此并没有真正的答案:文件名和路径没有编码;操作系统只处理字节序列。个别应用程序可能会选择将它们解释为以某种方式编码,但这会有所不同。
如果系统不处理字符,如何在文件名中禁止特定字符(例如/或NULL)?没有/
没有编码的概念。
一种解释是文件系统可以存储包含任何
字符的文件名,并且只有考虑编码的用户程序才会阻塞包含无效字符的文件名。反过来,这意味着文件系统和内核可以毫无困难地处理包含/.
我也认为这是错误的。
编码在哪里进行,不允许特定字符的限制在哪里?
Bru*_*ger 26
简短回答:在 Unix/Linux/BSD 内核、namei()功能中施加的限制。编码发生在用户级程序中,例如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 来终止字符串。除了这两个值之外,文件名中的字节可以采用任何其他值。您可以在 Unicode 的 UTF-8 编码中看到这一点。可打印的 ASCII 字符,包括“/”,在 UTF-8 中只占用一个字节。上述代码点的 UTF-8 不包括任何零值字节,除了 Nul 控制字符。UTF-8 是为 Plan-9,即 Unix 王座的伪装者而发明的。
较旧的 Unix(看起来像 Linux)有一个namei()函数,它一次只查看一个字节的路径,并在 0x2F 值字节处将路径分成几段,在零值字节处停止。 namei()是 Unix/Linux/BSD 内核的一部分,因此这是强制执行特殊字节值的地方。
请注意,到目前为止,我讨论的是字节值,而不是字符。 namei()不对字节强制执行任何字符语义。这取决于用户级程序,例如ls,它可能会根据字节值或字符值对文件名进行排序。xterm根据字符编码决定为文件名点亮哪些像素。如果你不告诉xterm你有 UTF-8 编码的文件名,你会在调用它时看到很多乱码。如果vim未编译以检测 UTF-8(或其他类型,UTF-16、UTF-32)编码,则在打开包含 UTF-8 编码字符的“文本文件”时会看到很多乱码。
Mat*_*Mat 18
问题是,内核一点也不关心应用程序如何解释它作为文件名给出的数据。
假设我有一个专门处理 UTF-16 字符串的 C 应用程序。然后我通过正确配置的输入法输入 ? 符号(Unicode 0x222F)进入“另存为”提示/对话框。
如果应用程序不进行任何形式的翻译,而是将其以普通的旧 C 字符串 ( char*) 发送到,比如说,fopen在写入模式下,内核将看不到 ?,甚至尝试想象它。它将看到两个chars,一个接一个,带有值0x22 0x2F(假设 8 位字符并且C 库中没有有趣的字符)。
也就是说,从内核的角度来看,有效的字符 ( ") 后跟/(ASCII 0x2F)。fopen将返回EISDIR(即“看起来像一个目录并且您请求了写入模式!”)。
如果我进入了?(Unicode 0x222E),内核会看到两个精细的字符,并创建一个文件,如通过 ASCII 应用程序看到的,将命名为"..
如果我a在应用程序中输入了一个文件名,并且应用程序将它以 UTF-16 格式传递给内核,内核会读取0x00 0x61,实际上甚至不会考虑它0x61,因为 就它而言0x00已经终止了字符串担心的。错误消息与空文件名相同(ENOENT我相信)。
因此,内核确实将数据视为 blob。这是一个chars流。您选择的用户空间编码中的无效“字符”是那些在其 blob(传递给内核的二进制表示)中生成0x00或0x2F(“null”和/)的字符。
| 归档时间: |
|
| 查看次数: |
13091 次 |
| 最近记录: |