Так сложилось, что в рамках подготовки курса SI-365 Solaris Internals, я разбирался со строением драйвера pcfs (эмулятора файловых систем FAT), c целью показать на простом примере, как организована внутренняя файловая кухня в Solaris. И дернуло меня заглянуть в файл /usr/include/sys/fs/pc_dir.h! Насторожили буквально первые строчки: Long filename support (introduced by Windows 95) is an interesting exercise in compatibility. Интересно, думаю, что это за упражнение? Остаток дня я провел в гомерическом хохоте, закатывая глаза и бессильно дрыгая ногами.
Простите, если байан, я раньше даже не мог задуматься о таком «элегантном» решении! В общем судите сами.
Как мы с вами знаем, запись в каталоге о файле DOS-like файловых систем, состоит из следующих полей:
struct pcdir {
char pcd_filename[PCFNAMESIZE]; /* file name */
char pcd_ext[PCFEXTSIZE]; /* file extension */
uchar_t pcd_attr; /* file attributes */
uchar_t pcd_ntattr; /* reserved for NT attributes */
uchar_t pcd_crtime_msec; /* milliseconds after the minute */
struct pctime pcd_crtime; /* creation time/date */
ushort_t pcd_ladate; /* last-access date */
union {
uint16_t pcd_eattr; /* OS/2 extended attribute */
pc_cluster16_t pcd_scluster_hi;
} un;
struct pctime pcd_mtime; /* last modified time/date */
pc_cluster16_t pcd_scluster_lo; /* starting cluster (little endian) */
uint_t pcd_size; /* file size (little endian) */
};
Эти поля предназначены для хранения записи о имени файла состоящего из 8 символов имени и 3 символов расширения, представленными в национальной восьми-битной кодировке (используется альтернативная таблица ГОСТ). Дык вот, длинное имя файла — это последовательность подобных структур, которые завершаются коротким именем файла. Подобные — значит что в стандартную структуру директории, во всевозможные ее места, пытаются вставить кусочки имени файла:
#define PCLF_FIRSTNAMESIZE 10
#define PCLF_SECONDNAMESIZE 12
#define PCLF_THIRDNAMESIZE 4
/*
* A long filename entry. It must match the 'pcdir' structure in size,
* and pcdl_attr must overlap pcd_attr.
*/
struct pcdir_lfn {
uchar_t pcdl_ordinal; /* lfn order. First is 01, next 02, */
/* last has bit 7 (0x40) set */
uchar_t pcdl_firstfilename[PCLF_FIRSTNAMESIZE];
uchar_t pcdl_attr;
uchar_t pcdl_type; /* type - always contains 0 for an LFN entry */
uchar_t pcdl_checksum; /* checksum to validate the LFN entry - */
/* based on the short name */
uchar_t pcdl_secondfilename[PCLF_SECONDNAMESIZE];
pc_cluster16_t pcd_scluster; /* (not used, always 0) */
uchar_t pcdl_thirdfilename[PCLF_THIRDNAMESIZE];
};
Как видно, каждый компонент длинного имени состоит из 13 символов Unicode, разбитого на три! части. При этом первый компонент используется как счетчик компонентов имени и указание на последний компонент (установлен бит 0x40). Кроме того, каждая часть длинного имени файла содержит отдельные атрибуты (скрытый, системный, только для чтения, ...). Обычное имя «This is a very long filename indeed» выглядит так:
Offset Sequence Component Attributes Cluster Size
0 0x43 "me indeed" RSHV 0 0
32 0x02 "y long filena" RSHV 0 0
64 0x01 "This is a ver" RSHV 0 0
96 ---- "THISIS~1.TXT" <whatever> 2122 110
В общем, представьте себе ежика. Покажите на него пальцем и скажите — это слон. Не верят?! Тогда возьмите череп коровы, порвите зад ежика на три части, натяните череп, а из всего остального сделайте хобот. Немного косметики, и можете спокойно говорить, что это хоть и маленький, но слон. А когда подрастет!!! Люблю майкрософт.
Хотя и понимаю иногда. Как расширить имя, сохранив совместимость? Писать правильно изначально.
А я то думаю, как полечу файловую систему дос, все левые файлы вылезают! Теперь понятно откуда.