FreeSource : Локализация/КодировкаНазванийФайлов

О кодировках названий файлов


Оглавление документа

Вступление


Каждый вступающий на тропу освоения Линукса, рано или поздно сталкивается с проблемой кодировок. Оказывается, что мир вокруг заполнен файлами, содержащими информацию в самых различных кодировках, и вопросы взаимодействия решены не очень...

Подробнее см. раздел «Причины появления» библиотеки NATSPEC.
В общем случае в системе отсутствует:

Стандартизация очень важна, особенно при разработке операционных систем. Все ключевые понятия должны быть определены.
Как написано в руководстве по нашим дистрибутивам, «Файловая система Linux... является единым деревом». Тут нет понятия ext3, reiserfs, FAT32 или NTFS. И фактически все файлы в этом дереве имеют названия в определённой кодировке.


Рекомендации


Общей рекомендацией является (для десктопной машины) ставить систему в такую же кодировку, как в Windows.

Кодировка windows-1251 имеет множество преимуществ перед koi8-r, созданной для решения одной единственной задачи — возможности прочитать сообщение, даже при утрате старшего бита в каждом байте. В настоящее время эта проблема неактуальна. Преимущества же кодировки windows-1251:

Предлагается

Достичь цели, когда только в одном конфигурационном файле системы будет указана кодировка. Вторым этапом предлагается установить эту кодировку в UTF-8.

Конкретные шаги:
  1. Ввести в систему библиотеку NATSPEC
  2. Устанавливать переменную G_FILENAME_ENCODING, которая будет задавать текущую кодировку файловой системы для тех программ, которые к этой переменной обращаются. В настоящий момент такой программой является GLIB и все программы, построенные на этой библиотеке, то есть GTK-программы и GNOME-программы. Если переменная не установлена, программа просто использует умолчание, которое в неё заложено. Рекомендуется значение кодировки получать напрямую из библиотеки libnatspec.
  3. Определиться с полиси, должно ли понятия кодировки быть общесистемным, или возможно разрешить пользователем влиять на это (например, изменением локали), и каков порядок – сейчас имеется конкретная релизация механизма в libnatspec.
  4. Внести соответствующие добавление во все проблемные (или завязанные на кодировки) программы (перечислены в разделе «Программы, где это нужно»)
  5. Добавить в программы, работающие с архивами, определение кодировки названий файлов в архивах (сформулировать критерии для разных систем) и перекодирование названий файлов. Потребуется включенный по умолчанию режим совместимости, когда названия файлов запоминаются в кодировке, принятой в альтернативной системе (Windows).

Что мы получим


В общем: систему, более пригодную к переходу на UTF-8, взаимодействующую с ресурсами UTF-8-систем, и после перехода на UTF-8 – взаимодействующую с другими системами, и данными, не поддерживающими UTF-8.
В частности:


Проблемы


Сюда записываются возражения, даже и не очень обоснованные. Желательно найти им ответ.

DenisSmirnov /25.02.2005 15:26/ Как и в любой другой не-unicode системе он будет вынужден пользоваться латиницей

DenisSmirnov /25.02.2005 15:26/ Отлавливанием виновного, и поручением ему перекодировки. Внутри организации должны действовать стандарты, и один из них — используемая кодировка хранения данных. Это существенно исключительно для nfs и ftp, в CIFS подобных проблем нет (перекодировка есть штатно);

DenisSmirnov /25.02.2005 15:26/ Описания всех возможных кодировок у нас и так есть — libiconv, на которую уже переползла та же Samba. У неё, правда, есть один серьёзнейший недостаток, из-за которого links на неё не перейдёт никогда — отсутствие возможности преобразовать символы в близкие по смыслу (например русские буквы при перекодировке в iso8859–1 отображать транслитом);
/VitalyLipatov // В libnatspec хранится описание *соответствия* всех возможных кодировок, а не просто перечень. К тому же в libnatspec добавлена возможность транслитерировать несоответствующие символы.

Программы, где это нужно

GLIB/GTK/GNOME

Статус: Есть готовый файл для profile

В gtk есть обработка переменной окружения G_FILENAME_ENCODING, которая у нас _не_ устанавливается, поэтому gtk предполагает, что она соответствует локали. При этом всё ломается, если я хочу запустить программу из другой локали (LANG=ru_RU.UTF-8 или LANG=ru_RU.CP1251) при основной koi8-r.
Так же GLIB обрабатывает переменную G_BROKEN_FILENAMES. Если она установлена, GLib предполагает, что названия файлов хранятся в кодировки локали, а не в UTF-8. Но G_FILENAME_ENCODING имеет больший приоритет.

SAMBA

TODO:

1. Ни к чему каждый раз после установки раскомментировать в конф. файле строчки про кодировку (unix/display charset), когда они должны устанавливаться в кодировку файловой системы / локаль автоматически.
DenisSmirnov /25.02.2005 15:26/Для сервера ручная настройка ещё может иметь какой-то разумный смысл, для клиента же — автоугадав обязателен
2. При монтировании удалённой файловой системы через smbmount (и mount -t cifs скорее всего тоже) опять же требуется указать кодировку своей системы (iocharset)
DenisSmirnov /25.02.2005 15:26/ iocharset давно надо брать из текущей локали по-умолчанию

Монтирование файловых систем FAT-32, NTFS, ISO9660/Jouliet

Статус: есть патч для mount
TODO: Одновременно можно внести в mount поддержку /etc/fstab.d
Тут я хотел бы пояснить, что в стандартной системе должна быть команда mount и она должна работать правильно. HAL – это хорошо, но это другое решение и надстройка более высокого уровня. Она не отменяет простого использования mount.

Бесконечное количество раз люди бьются с fstab, записывая туда разные iocharset, nls_ и пр. Но ведь можно же брать эти параметры (по умолчанию) из кодировки файловой системы.

TODO:
Rock Ridge предполагать в UTF-8, перекодировать, если валидна.

Создание образов дисков

Статус: есть патч для mkisofs и isoinfo

DOSEMU

Статус: у меня претензий нет
Там происходит перекодирование названий файлов в досовскую кодировку. Скорее всего, используется кодировка локали.
TODO: автоматизация заполнения config.sys для установки внутренней локали

FTP 

Поскольку для FTP никаким образом не определено задание кодировок, обращаться из одной системы в другую за файлами, имеющими название из не ASCII-диапазона, невозможно.
В proftp 1.3.1 добавился модуль mod_lang (поддержка команды “LANG” в соответствии с интернационализацией по RFC2640)
Варианты решения:

(Как частный вариант есть http://linux.kiev.ua/details.html?&L=1&cHash=f4c7be3c1a&tx_ttnews[backPid]=87&tx_ttnews[pointer]=2&tx_ttnews[tt_news]=550

WINE

Статус: у меня претензий нет
В основном проблема с кодировками названий файлов не возникает (решена за счёт предположения соответствия кодировки локали и файловой системы) – идеально, если бы это решалось вне проекта.
TODO: консольные сообщения не перекодируются в кодировку локали (что с wcmd?)

Архиваторы


Как правило, в Windows для кодирования названий файлов в архивах используется OEM-кодировка (DOS), в то время как в Linux названия записываются в кодировке файловой системы. И ничего не сдвинуто в этом направлении...

См. Ситуация С Архиваторами

Модули файловых систем в ядре Linux kernel 2.6.10

Подлежит уточнению:
Предлагается ввести перекодирование названий при работе с подмонтированными файловыми системами, подразумевая в них UTF-8.

Модули поддержки «чужих» файловых систем как правило имеют параметр iocharset, задающий внутреннюю кодировку названий файлов для перекодирования из «чужого» Юникода. Это относится к isofs, udf, vfat, ntfs, jfs
Для vfat имеется умолчание в ядре: FAT_DEFAULT_CHARSET, FAT_DEFAULT_CODEPAGE, по умолчанию присваиваемые iocharset и codepage соответственно, но это константы, что нам не подходит.

DenisSmirnov /25.02.2005 15:31/ Мысль : насколько просто внедрить дополнительный параметр в суперблок ext3, reiserfs4, xfs (основных используемых FS)?
В JFS предусмотрен iocharset, позволяющий перекодирование смонтированной системы (как я понимаю, в JFS подразумевается UTF8). Можно посмотреть, как это сделано там и рекомендовать разработчикам.
Вообще нужно сделать выбор: указывать кодировку в файловой системе или подразумевать, что она – в UTF-8.


Средство перекодирования файловой системы налету (через fuse?)

DenisSmirnov /24.02.2005 19:14/ Использование для этой цели fuse это очень хорошее временное решение

Кодировку на коротких названиях в FAT можно предполагать на основании кодировки файловой системы (для koi8-r/cp1251 будет cp866), для длинных названий на FAT/NTFS известно какая кодировка. А для остальных файловых систем ext?/reiserfs/xfs нужно вводить хранение кодировки или иметь предубеждение, что она там в UTF-8. Также потребуется перекодирование подмонтированной системы.
Получается, ядро должно иметь информацию о кодировке. Кстати, если хранить названия файлов в произвольной кодировке, можно избежать перекодирования, которое будет производится только при различии кодировкой локальной и на монтируемой файловой системе.

Замечания


Вячеслав Диконов:
Имею программу, у которой своя собственная внутренняя система локалей (VDR). Там гвоздями и стандартами DVB-вещания забито, что русский всегда идет в iso8859–5. Нет никаких внутренних средств перекодировки или поддержки системной локали, при этом нужно писать и читать много файлов, а файлам автоматически даются русские имена.
Может быть добавить в библиотеку функцию, позволяющую прозрачно заменять обычные обращения к объектам файловой системы в C и автоматически приводить имена к заданной кодировке, в каком бы виде они не хранились на реальных носителях? А также при записи преобразовывать имя из заданной кодировки в любую, какая используется на диске.
К VDR есть даже свои коммандер и консоль... Задача в том, чтобы видеть через преобразователь кодировок все съемные носители, все разделы с мультимедийными файлами и т.п. Кстати, набирать длинные команды и монтировать через обычный пульт ДУ слишком тяжело, а лавиатуры/мыши у VDR-машин часто вообще нет.
Еще проблема – включение в специаизированные дистрибутивы, которые ставятся на компы-ресиверы. Там все обрезано под ноль. Это я к тому, что решение должно быть маленьким и включаться минимальными движениями пользователя.

Алексей Морозов:
Единственным решением, которое худо-бедно может претендовать на некоторую универсальность (ну, помимо банального использования содержимого /etc/sysconfig/i18n) является организация (через dbus, вестимо, куда ж нынче без него) _обратной связи_ между HAL и пользовательским сеансом. То есть, сценарий использования примерно таков:
HAL, почуяв устройство с подходящей файловой системой, кидает броадкаст сообщение, о том, что-де, обнаружен FAT или там NTFS или еще какой ISO9660 позорный, требуется указать, как его монтировать. Соответствующий _пользовательский_ процесс, запущенный при старте сеанса, сверяется с какой-либо своей настройкой (например, получает значение LC_CTYPE, как вариант или еще что) и отвечает HAL'у, что-де так и так, предпочитаемая локаль пользователя такая-то и такая-то, использовать такой-то и такой-то чарсет для конвертации данных.
(from LAV: пока принцип не очень жизнеспособен, потому что HAL нападёт на первого попавшегося пользователя)
DenisSmirnov /25.02.2005 15:31/Думаю речь должна идти о пользователе, коий последний обращался к консоли

Алексей Морозов:
. /etc/sysconfig/i18n
: ${SYSFONTACM:=koi8-r}
: ${SYSMOUNTCHARSET:=$SYSFONTACM}
echo $SYSMOUNTCHARSET

http://lists.altlinux.ru/pipermail/devel/2005-February/017892.html

Только нужно учитывать, что рецепт, приведенные там не вполне корректен. Во-первых, нужно проверять на наличие файла /etc/hal/fdi/95userpolicy/system_charset.fdi перед его перезаписью. Во-вторых, формируемый .fdi, боюсь, не вполне корректен, требуется еще некоторый пролог и эпилог. Ну, и в третьих, Антон до сих пор не перенес соответствующие настройки
из /usr/share/hal в /etc/hal. Нужно только помнить, что «системные» настройки, которых там большинство лучше по-прежнему оставлять в /usr, т.к. по размеру они большие, а править их все равно не следует. А вот подкаталог 95userpolicy – явный кандидат в /etc.

Ссылки


Страницы, ссылающиеся на данную: Локализация/НациональнаяСпецификаСистемы