Linux/VLFN
VLFN(Very Long FileName) - проблема, заключающаяся в том, что в GNU/Linux применено ограничение в 255 байт на длину имени файла, что при использовании UTF-8 даёт для русских букв не более 127 символов.
Длинные имена файлов в Linux
Увеличение длин имен файлов в Linux.
Имена файлов в Windows и Linux
В Windows для именования файлов принята кодировка UTF-16, то есть каждый символ в названии файла кодируется двумя байтами (16 бит). Максимальная длина имени файла — 255 символов (510 байт). В Linux же для именования файлов принята кодировка UTF-8, при этом максимальная длина файла составляет 255 байт (а не символов).
Постановка задачи
Так как в UTF-8 для кодирования русских букв используется два байта, то максимальная длина имени файла, состоящего из русских букв, фактически составляет 127 символов. В связи с этим появляется проблема - длинные имена файлов (от 128 до 255 русских символов) не влезают в установленные для них ограничения в Linux.
Упоминания данной проблемы:
- http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-06/2426.html
- http://stackoverflow.com/questions/833291/is-there-an-equivalent-to-winapis-max-path-under-linux-unix?rq=1
Решение
Предложенное решение - необходимо увеличить возможную длину файлов в Linux.
Выбранная длина нового максимального предела имени файла - 1023 байта.
Причины выбора:
- нет привязки к Windows, поэтому нет необходимости задавать размер ровно 511 байт;
- имя файла задается с запасом, что позволит адаптировать ОС и ФС к иероглифической, к примеру письменности, где знаки могут занимать в районе 4 байт.
Уже сделано
Был проведен тест файловой системы NTFS. Оказалось, что на данной можно создавать файлы с длинным русским именем, из чего следовало, что ограничение задается самой ФС, а не ядром или библиотекой glibc:
https://bugs.etersoft.ru/show_bug.cgi?id=9266
Было решено выбрать файловую систему, которую легче всего было бы адаптировать для решения данной проблемы. Затем было проведено сравнение самых распространенных и перспективных файловых систем:
http://wiki.etersoft.ru/Comparison_of_file_systems
Стоит рассмотреть такие системы как btrfs, xfs, ext4.
В итоге была выбрана BTRFS.
BTRFS
B TRee File System - файловая система, основанная на структуре Б-деревьев и работающая по принципу «копирование при записи».
Изменения
Изначально изменен предел BTRFS_NAME_LEN, заданный в файле /fs/btrfs/ctree.h.
Аналогичный предел был изменен в пакете BTRFS-progs.
Изменения:
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d6dd49b..3ae04d0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -154,7 +154,7 @@ struct btrfs_ordered_sum;
* we can actually store much bigger names, but lets not confuse the rest
* of linux
*/
-#define BTRFS_NAME_LEN 255
+#define BTRFS_NAME_LEN 1023
/*
* Theoretical limit is larger, but we keep this down to a sane
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 7f0c1dd..9bbf0d9 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -202,7 +202,7 @@ struct compat_dirent {
u32 d_ino;
compat_off_t d_off;
u16 d_reclen;
- char d_name[256];
+ char d_name[1024];
};
struct compat_ustat {
diff --git a/include/uapi/linux/limits.h b/include/uapi/linux/limits.h
index 2d0f941..ca17cbe 100644
--- a/include/uapi/linux/limits.h
+++ b/include/uapi/linux/limits.h
@@ -8,7 +8,7 @@
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
-#define NAME_MAX 255 /* # chars in a file name */
+#define NAME_MAX 1023 /* # chars in a file name */
#define PATH_MAX 4096 /* # chars in a path name including nul */
#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
Тестирование
Проведено тестирование основной функциональности новой файловой системы.
Для граничных значение - 1024 и 1023 байта:
Testing glibc functions with 1023-byte filename
FAILED: 0, PASSED: 20
Testing glibc functions with 1024-byte filename
FAILED: 0, PASSED: 20
Программа для тестирования доступна тут: git.eter:/people/reprofy/public/glibc_tests.git -> glibc_tests
Применение
Для того, чтобы использовать файловую систему BTRFS с увеличенным пределом имени файла, необходимо:
- Установить исправленную версию ядра ( git.eter:/people/reprofy/packages/kernel_sis.git -> btrfs_new_bound );
- Отформатировать дисковый раздел, используя исправленную версию btrfs-progs ( git.eter:/people/reprofy/public/btrfs_progs.git -> filename_bound );
- Для обеспечения полной функциональности необходимо изменить предел в файле limits.h:
- Установить исправленный пакет kernel-source-3.9 ( git.eter:/people/reprofy/public/kernel_source_3.9.git -> namelength_increased );
- Установить пакет glibc-kernheaders(из репозитория git.alt );
Glibc
Тестирование mc
При использовании mc было обнаружено, что несмотря на исправленные пределы в файловой системе midnight comander не отображает длинные имена файлов. Как оказалось далее, mc берет значения констант из файла /usr/include/linux/limits.h. Последний, в свою очередь, принадлежит пакету glibc-kernheaders, который требует среди зависимостей пакет kernel-source. Исправив в kernel-source файл limits.h, собрав и установив пакет на виртуальную машину, а затем собрав и установив glibc-kernheaders, удалось добиться изменения файла /usr/include/linux/limits.h. После чего, вновь собранный mc стал корректно отображать длинные имена.