Понимание кодирования имени файла Unix

Просто используйте точную команду от своего вопроса. yum может взять несколько имен пакета, как введено:

yum install mysql php vsftp
25
13.04.2017, 15:37
3 ответа

Короткий ответ: ограничения вводятся в ядре Unix/Linux/BSD, namei() функция. Кодирование происходит в программах уровня пользователя как xterm, firefox или ls.

Я думаю, что Вы запускаете с неправильного помещения. Имя файла в Unix является строкой байтов с произвольными значениями. Несколько значений, 0x0 (ASCII Nul) и 0x2f (ASCII '/') просто не позволяются, не как часть многобайтовой кодировки символов, не как ничто. "Байт" может содержать число, представляющее символ (в ASCII и некоторой другой кодировке), но "символ" может потребовать больше чем 1 байта (например, кодовые точки выше 0x7f в представлении UTF-8 Unicode).

Эти ограничения являются результатом конвенций печати имени файла и набора символов ASCII. Исходный Unixes использовал ASCII '/' (численно 0x2f) оцененные байты для разделения частей частично - или полностью определенный путь (как '/usr/bin/cat' имеет части "usr", "мусорное ведро" и "кошку"). Исходный Unixes использовал ASCII Nul для завершения строк. Кроме тех двух значений, байты в именах файлов могут принять любое другое значение. Вы видите эхо этого в кодировке UTF-8 для Unicode. Печатаемые символы ASCII, включая '/', берут только один байт в UTF-8. UTF-8 для кодовых точек выше не включает байтов с нулевым знаком, за исключением управляющего символа Nul. UTF-8 был изобретен для Плана 9, Претендента на Трон Unix.

Более старый Unixes (и это похоже на Linux), имел a namei() функция, которая просто смотрит на пути байт за один раз и ломает пути на кусочки в 0x2F, оценила байты, останавливающиеся на уровне байта с нулевым знаком. namei() часть ядра Unix/Linux/BSD, таким образом, это - то, где исключительные значения байта осуществляются.

Заметьте, что до сих пор, я говорил о значениях байта, не символах. namei() не осуществляет символьной семантики на байтах. Это до программ уровня пользователя, как ls, который мог бы отсортировать имена файлов на основе значений байта или символьных значений. xterm решает что пиксели осветить для имен файлов на основе кодировки символов. Если Вы не говорите xterm у Вас есть закодированные имена файлов UTF-8, Вы будете видеть много мусора при вызове его. Если vim не компилируется для обнаружения UTF-8 (или что бы то ни было, UTF-16, UTF-32) кодировка, Вы будете видеть много мусора, когда Вы откроетесь, "текстовый файл", содержащий UTF-8, закодировал символы.

25
27.01.2020, 19:40
  • 1
    Корректный, namei() отказался приблизительно в 1986. Более новое системное использование UNIX lookuppn() это - базирующийся VFS. –  schily 17.09.2015, 16:29

Вещь, ядро не заботится об одном бите, как приложения интерпретируют данные, которые это дано как имя файла.

Давайте предположим, что у меня есть приложение C, которое имеет дело с исключительно строками UTF-16. И я вхожу, через правильно настроенный метод ввода, ∯ символ (Unicode 0x222F) в подсказку/диалоговое окно "Сохранить Как".

Если приложение не делает никакой формы перевода и отправляет это в простой струне до (char*) к, скажем, fopen в режиме записи ядро не будет видеть ∯ или даже пытаться вообразить это. Это будет видеть два chars, один за другим, со значениями 0x22 0x2F (принятие символов на 8 битов и никакого funnies в библиотеке C).
Таким образом, с точки зрения ядра, допустимый символ (") сопровождаемый / (ASCII 0x2F). fopen возвратится EISDIR (т.е., "который похож на каталог и Вы запросили режим записи!").
Если я ввел ∮ (Unicode 0x222E), ядро видело бы два прекрасных символа и создало бы файл, который, как замечено через говорящее ASCII приложение, назовут "..

Если я вошел a в приложении, поскольку имя файла и приложение провели его в UTF-16 к ядру, ядро будет читать 0x00 0x61, и на самом деле даже не рассмотрите это 0x61, потому что 0x00 уже завершает строку, что касается его. Сообщение об ошибке совпало бы с для пустого имени файла (ENOENT Я верю).

Таким образом, ядро действительно берет данные в качестве блоба. Это - поток chars. Недопустимые "символы" в Вашем пространстве пользователя, кодирующем по Вашему выбору, являются теми, которые генерируют 0x00 или 0x2F ("пустой указатель" и /) в их блобе (двоичное представление, которое передается ядру).

17
27.01.2020, 19:40
  • 1
    Если я разбираюсь в Вас, то нет такой вещи как недопустимые символы. Существуют только недопустимые последовательности байта. И значения 0x00 и 0x2F трудно кодируются в ядре. Это в свою очередь означает, что каталоги не разделяются a /, но к любым картам символов к 0x2F в используемом кодировании. –  Marco 22.05.2012, 23:28
  • 2
    Да, это - идея, если Вы хотите видеть его тот путь. (Но это могло бы быть неправильно. Ядро могло бы иметь "собственный компонент, кодирующий" где / не 0x2F - не мог бы использовать 8-разрядный chars, на самом деле.) "Традиционный" разделитель dir /. Это - 0x27 на байте на 8 битов ASCII (не EBCDIC, например) системы. –  Mat 22.05.2012, 23:41
  • 3
    Вы принимаете UTF-16BE, тогда как в UTF-16LE U+0061 приведет к (завершенный пустым указателем) a строка. –  Incnis Mrsi 12.09.2015, 19:29

Разделение байтов по сравнению с символами произошло очень после того, как Unix был разработан. Когда это было разработано, использование слов только передало что-то о том, как 8 (или 6, или 9) биты интерпретировались, но кодировка слова не была упомянута.

Имена файлов являются последовательностями байтов. Любой байт кроме 0x2f "/" позволяется. Байт, содержащий 0x00, не может даже добраться до ядра из-за его использования в качестве строкового разделителя. Приложение может интерпретировать последовательность байтов согласно кодированию, это выбирает. Если это звучит грязным, я предполагаю, что это.

Существует больше информации по http://www.gtk.org/api/2.6/glib/glib-Character-Set-Conversion.html, который можно найти полезным.

4
27.01.2020, 19:40

Теги

Похожие вопросы