Давным-давно, на заре своего рождения Windows использовала файловую систему FAT. Потом ей на смену Microsoft и IBM разработали NTFS. В те давние времена возникло два противоположных подхода к файловой системе. В Linux используется case-sensitive файловая система, а в Microsoft — case-insensitive.
Суть в том, что в case-sensitive файловой системе считается, что имена, написанные в разных регистрах (например, FILE.txt и file.txt) — это разные имена. А для Windows между ними нет разницы.
Несмотря на нечувствительность Windows к регистру букв, разработчики NTFS подошли к делу ответственно, и бережно сохраняют регистр имен каталогов и файлов. Возможно, они не теряли надежды на сближение с противоборствующим лагерем.
Первые жертвы
Шли годы, информационные технологии не стояли на месте, и дистрибутивы Linux научились монтировать NTFS-разделы. Операционные системы стали ближе, а наши противники впервые столкнулись на одном поле — и появились первые проблемы. Присоединив NTFS-раздел, пользователь Linux мог создать в одном каталоге несколько различных файлов с именами, которые отличаются только регистром. А как мы знаем, NTFS сохраняет регистр букв при создании объектов файловой системы. Если потом подключить тот же NTFS-раздел к Windows, то операционная система начнет путать файлы-близнецы между собой. С ее точки зрения, они имеют одинаковые имена! Пользователь кликает по одному файлу, а открывается совсем другой. Короче, хаос и безобразие.
В 2016 году Microsoft сделала шаг навстречу Linux и выпустила Windows 10 Anniversary Update с подсистемой WSL. Windows Subsystem for Linux (WSL) предоставляет интерфейсы, во многом совместимые с интерфейсами ядра Linux. Что позволяет запускать большинство Linux-приложений, в том числе оригинальные образы некоторых Linux-дистрибутивов. Например, Ubuntu 14.04! Это была революция! Linux и Windows работают на одном компьютере одновременно, как партнеры. Но к сожалению, партнеры все еще по-разному смотрели на регистрочувствительность в плане работы с файловой системой. Ввести Windows в замешательство с помощью создания файлов или каталогов с именами, отличающимися только регистром, стало еще проще.
Попытка примирения
В новой версии Windows 10 Spring Creators Update компания Microsoft добавила возможность задания режима case-sensitivity для отдельно взятого каталога. Сделать это можно с помощью утилиты fsutil. Читатель, наверное, уже знаком с этой полезной утилитой.
Теперь у нее появились две новые команды:
fsutil file queryCaseSensitiveInfo
fsutil file setCaseSensitiveInfo
Для того чтобы воспользоваться этими командами, у вас должна быть активирована WSL-подсистема, а команда setCaseSensitiveInfo требует прав администратора.
После включения режима case-sensitivity файлы и каталоги, находящиеся внутри, будут доступны только при указании их точного имени! И Windows теперь четко видит разницу между FILE.txt и file.txt.
С другой стороны, WSL-подсистема тоже должна учитывать, включен или выключен режим case-sensitivity у каталога, в котором она создает файл или дочерний каталог. Каталоги, которые формируют структуру WSL или создаются из WSL, сразу имеют включенный case-sensitivity. Все остальные каталоги по умолчанию режим case-sensitivity не включают.
Если в WSL зайти в каталог с выключенным case-sensitivity режимом и попробовать создать в нем два файла, имена которых будут отличаться только регистром, то получите ошибку.
Таким образом, WSL и Windows поделили логический диск между собой. Часть каталогов поддерживает режим case-sensitivity, а другая часть – нет.
Спускаемся ниже
Под капотом для получения и задания флага case-sensitivity используются функции NtQueryInformationFile и NtSetInformationFile c новым параметром FileCaseSensitiveInformation.
Пример:
HANDLE h = CreateFile(
path,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_SUPPORTS_USN_JOURNAL,
0);
if( INVALID_HANDLE_VALUE == h )
return;
IO_STATUS_BLOCK io;
uint32_t csFlags = 0;
DWORD error = NtQueryInformationFile(
testHandle,
&io,
&csFlags,
sizeof(csFlags),
(FILE_INFORMATION_CLASS)0x47); // FileCaseSensitiveInformation
CloseHandle(h);
В результате работы функции в переменной csFlags будет 1, если режим case-sensitivity включен, и 0 — если выключен.
Еще ниже — Raw NTFS
На уровне NTFS флаг case-sensitivity хранится в атрибуте StandartInfoData, в поле NumVersion.
Если атрибут выставлен, то NumVersion = 1, иначе NumVersion = 0
typedef struct _StandartInfoData_
{
FILETIME CreateTime;
FILETIME LastModTime;
FILETIME LastModMFT;
FILETIME LastAccess;
DWORD FileAttrib;
DWORD MaxVersions;
DWORD NumVersion; // <--
DWORD ClassId;
DWORD OwnerId;
DWORD SecureId;
ULONGLONG Quota;
ULONGLONG SequenceNumber;
} StandartInfoData;
Заключение
Мы видим, что Microsoft прикладывает значительные усилия для того, чтобы объединить в одной системе два разных мира — Windows и Linux. И для успеха своей миссии они пошли на уступки в плане регистрочувствительности своей файловой системы. Поможет ли это? Решит ли противоречия? И какие еще проблемы всплывут? Все это покажет лишь Его Величество Время.
Wanted
Кстати. Или не совсем кстати. У нас тут коллеги ищут руководителя группы разработки автотестов. Правда работа в Новосибирске. Если кому-то это интересно, то вот вакансия.
Автор: OldMaster