Вход:  Пароль:  
FreeSource: Локализация/КодировкаНазванийФайлов ...
Free Source | Каталог | Изменения | НовыеКомментарии | Пользователи | Регистрация |

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


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

Вступление


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


Подробнее см. раздел «Причины появления» библиотеки 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.

Ссылки


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


 
Файлов нет. [Показать файлы/форму]
Комментарии [Скрыть комментарии/форму]

Да, по поводу mount — есть ещё и libfstype, написаная rider@
Она умеет понимать LABEL на reiserfs разделах (в отличии от mount) и много других вкусных вещей.
У меня есть мнение что пора mount переписывать целиком.
Слишком много недостатков накопилось.
Заодно iocharset надо брать из текущей локали (одно это уже здорово облегчит жизнь).

-- DenisSmirnov (2005-02-24 19:10:30)

Для получения iocharset используется библиотека libnatspec, в её каталоге examples имеется соотв. патч для mount.
А rider IMHO неправ в том, что написав библиотеку, не подключил её к mount.

-- VitalyLipatov (2005-02-24 20:00:48)

Там не подключать надо, там переделывать логику mount надо. Полностью удаляя весь код автоопределения типа раздела и его параметров, и заменяя на вызовы libfstype. rider свой код писал отнюдь не для mount, и ему просто не до него.


А в ALT уже столько новой функциональности, которую следует учитывать mount, что его действительно пора переписывать.


А этот соответствующий патч приложен в ALT?

-- DenisSmirnov (2005-02-24 20:14:11)

Совершенно верно, но чтобы переделать логику и обновить mount, надо
1. Сформулировать, как надо
2. Переписать (и лучше сообщаясь с международной общественностью)
3. apt-cache search по слову fstype не находит libfstype


Соответствующий патч пока не приложен, потому что я так и не понял реакцию на него. Да и библиотека libnatspec последней версии
ещё не появилась в Сизифе. Думаю через bugzilla действовать?
Вы наверное читали обсуждение в devel по поводу нужности какой-либо логики в mount :)

-- VitalyLipatov (2005-02-24 20:56:18)

Опаньки, кажись rider@ всё в libhw положил
Обсуждение уже не помню.
Так как libhw потихоньку входит в базовую систему (и это правильно), то mount можно к нему приучать.
По поводу /etc/fstab.d я уже все уши rider'у прожужжал. Он скоро озвереет, и на слово 'fstype.d' будет грязно материться и кидаться тяжёлыми предметами :) А так как теперь правку fstab свалили на HAL, то теперь и rider'у всё пофиг.
Некому mount переписывать.
А с международной общественностью пока libhw существует только в Сизифе об этом разговаривать рано.

-- DenisSmirnov (2005-02-25 12:25:18)

Хорошо, я проведу ревизию libhw
Посмотрю в mount на предмет:

  1. подключения libnatspec
  2. добавления fstab.d
  3. использования libhw

Проверю работу с /etc/mtab – ссылкой на /proc/mounts
А libhw так и будет только в Сизифе существовать, нет?

-- VitalyLipatov (2005-02-25 22:53:36)

Будет только в Сизифе до тех пор, пока кто-нибудь не захочет её к себе утащить.
Вот только кто? Разве что Debian'овцы в начале. Остальные в kudzu вроде играются. Хотя привлечь внимание можно.


С ссылкой /etc/mtab на /proc/mounts всё прекрасно работает, за исключением mount --bind.

-- DenisSmirnov (2005-02-27 17:55:25)

По поводу iocharset — есть смысл посмотреть на код, использующийся в juliet, vfat, ntfs и jfs. В каждой из них есть соответствующий код для поддержки iocharset. Возможно есть смысл найти общие участки, и вынести их в некий общий модуль, на использование которого пропатчить остальные FS.

-- DenisSmirnov (2005-02-27 17:56:47)

1. Со ссылкой на /proc/mounts всё работает, в том числе и --bind, но не освобождаются loop-устройства.
2. Я детально рассматривал вариант с iocharset и сравнивал код, но решил, что лучше исправить mount -> это позволит не патчить ядро, это важно, поскольку усложняет задачу. А остальным FS это не поможет, потому что в них нет указания кодировки.

-- VitalyLipatov (2005-02-27 22:19:01)

В FAT (не vfat) тоже нет указания кодировки. Однако всё работает. Потому что опциями монтирования можно указать и кодировку внешниюю и внутреннюю.


А то что можно сделать в mount, естественно надо делать в mount. Я имел в виду встраивание самой перекодировки в ext3, например. Чтобы если мне принесли хард с koi8-r, а у меня cp1251, я мог нормально видеть русские буквы.

-- DenisSmirnov (2005-02-27 22:24:34)

Я считаю что это должно быть решено отдельным средством, через unionfs или модуль для fuse, позволяющий монтировать с перекодированием. По поводу того, как это может выглядеть, хорошо бы написать статью. Кстати, для fuse можно за полдня такое средство написать.

-- VitalyLipatov (2005-02-28 15:50:56)

Просто этот код уже есть для juliet, vfat, jfs. Только разный.
Поэтому есть смысл вынести его за пределы этих FS, и использовать в других. Как вынесли из ext3 код для журналирования.
Модуль для fuse это хороший вариант в том смысле, что более надёжный. Я бы однозначно пропагандировал лишь его, если бы не факт уже наличия в ядре нужного кода, который осталось лишь использовать.
Ну и вопрос с производительностью туда же. Будем ли мы /usr через fuse монтировать? А можно ли иметь русские имена файлов на /usr? А я хочу русские имена команд иногда делать ;)

-- DenisSmirnov (2005-02-28 17:18:12)

Код для juliet, vfat достаточно специфичен. Вот jfs – это да, должно быть так же и для остальных.
Там Unicode оказывается внутри, и CONFIG_NLS_DEFAULT по умолчанию для перекодировки.
libnatspec указывает нужный параметр iocharset автоматом.
Может перейти на jfs для переносных дисков ? :)
Модуль для subfs – это как инструмент частного решения проблем. Производительность – да, страдает.
/usr монтировать не будем. Русские названия файлов в rpm-пакетах – только после перехода на utf8.

-- VitalyLipatov (2005-02-28 19:59:11)

juliet специфичен только тем, что внутри всегда уникод.
А FAT чем специфичен? Там точно так же кодировка внутри и снаружи может быть разная.
JFS — давить. Это единственное поделие IBM, к которому я не питаю никаких позитивных эмоций. Нафиг он не нужен никому. Из него только код полезный брать есть смысл :)


Насчёт fuse — в любом случае соглашусь, что подобный модуль будет полезен.

-- DenisSmirnov (2005-02-28 20:03:28)

Уважаемый с адреса 85.115.231.129, ваши восторги Su Se? понимаю, но не соблаговолите ли показать
unzip -l на zip-архив с русскими именами файлов внутри, сделанный в Windows? А также может посмотрите на
него в ark?

-- VitalyLipatov (2005-12-05 17:58:11)

ничем не лучше сп1251. Хотя бы то, что кои8 выживает при потере 8го бита – это весьма важная фича

-- 80.90.116.7 (2006-04-29 22:13:00)