Давным-давно, на заре своего рождения 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.
Пример:
В результате работы функции в переменной csFlags будет 1, если режим case-sensitivity включен, и 0 — если выключен.
На уровне NTFS флаг case-sensitivity хранится в атрибуте StandartInfoData, в поле NumVersion.
Если атрибут выставлен, то NumVersion = 1, иначе NumVersion = 0
Мы видим, что Microsoft прикладывает значительные усилия для того, чтобы объединить в одной системе два разных мира — Windows и Linux. И для успеха своей миссии они пошли на уступки в плане регистрочувствительности своей файловой системы. Поможет ли это? Решит ли противоречия? И какие еще проблемы всплывут? Все это покажет лишь Его Величество Время.
Кстати. Или не совсем кстати. У нас тут коллеги ищут руководителя группы разработки автотестов. Правда работа в Новосибирске. Если кому-то это интересно, то вот вакансия.
Суть в том, что в 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
Кстати. Или не совсем кстати. У нас тут коллеги ищут руководителя группы разработки автотестов. Правда работа в Новосибирске. Если кому-то это интересно, то вот вакансия.
nerudo
По хорошему, драйвер (ifs) файловой системы не должен был позволять создавать файлы с одинаковыми именами. Равно как chkdsk должен эту ситуацию обнаруживать и разрешать. Раз уж изначально для NTFS приняли case-insensitive подход.
Riateche
Дело в том, что сама NTFS case sensitive и хранить в ней файлы по именам, различающимся только регистром, совершенно корректно. Case-insensitive подход приняли не в NTFS, а в Windows.
hdfan2
Скорее, в MS-DOS, а уже оттуда для совместимости было притащено в Windows. А в DOS это, скорее всего, попало от CP/M.
areht
В MS-DOS LFN проецируется в 8.3, так что в Windows можно было разрешить case sensitive, и это не помешало бы MS-DOS.
И это правильно, как минимум когда в системе приняты полноценные названия, вроде Documents and Settings, то вспоминать где там большие буквы — занятие очень такое себе.
Case sensitive можно применять там, где /usr/
ZyXI
В linux речь идёт, вообще?то, совершенно не о чувствительности к регистру. Имя файла здесь — это произвольный набор байт, в котором не может быть только косой черты (прямой, обратная может быть), разделяющей каталоги, и нулевого байта, исторически означающего конец строки. Это позволяет обрабатывать доступ к файлам весьма эффективно: вам не нужно нормализовывать имена перед сравнением и делать кэши нормализованных имён просто чтобы файловый доступ работал быстро (где?то на хабре, кстати, проскакивала статья про эти кэши).
Соответственно в linux если вы не хотите помнить «где большие буквы», то вы просто настраиваете автодополнение. В GUI оно обычно так и работает (и не настраивается), в командной строке — не всегда. Может быть не очень удобно, но это делает разработку linux проще, а доступ к файлам быстрее. (Ещё, конечно, это создаёт целый класс ошибок (иногда потенциально приводящих к уязвимостям) в скриптах на *sh, но тут я бы спрашивал с разработчиков языка и с тех, кто до сих пор его не заменил.)
Конечно есть и ещё один минус: если имя файла — произвольная последовательность байт, то сразу начинается проблема с определением, в какой кодировке оно записано и, соответственно, как интерпретировать имя файла для отображения в GUI. К счастью, современные системы все просто используют UTF-8, а во всех стандартных каталогах ASCII.
areht
Де факто, это и есть нечувствительный к регистру режим.
PS. Имхо, «но тут я бы спрашивал с разработчиков языка и с тех, кто до сих пор его не заменил.)» — это сродни «с нашей стороны пули вылетели». На мой взгляд, ОС характеризуется не только рекордами в скорости файлового доступа, но организацией защиты от дурака.
ZyXI
Запрещение звёздочек в имени файла — это защита от дурака в неправильном месте. В *sh вам даже пробелы в имени проблем доставят — теперь запретить пробелы в ядре? Просто кому?то надо было собраться и исправить язык командной оболочки пока не было слишком поздно (т.е. слишком много скриптов).
areht
Так проблема sh не ограничивается. В любом языке где-то там лежат грабли и «There is no way to quote meta-characters.
Sorry.». А запретили бы десяток символов — жить было бы легче.
ZyXI
Я не слышал про проблемы с экранированием, к примеру, в C, которые бы реально решались запретом символов. Пока имя файла — это имя файла или, хотя бы, просто одна строка никаких проблем нет. Проблемы начинаются, либо когда вы используете eval в той или иной форме (в т.ч. формируете
snprintf
’ом строку дляsystem()
вместо использованияexecv()
(или аналога из libuv, если в системеexecv()
не поддерживается)) и должны сформировать для него строку, либо когда строка неявно преобразовывается во что?то (в вашем примереglob
должен реально получить что?то вроде списка["C:\\abc\\afolderwith[test]\\", glob.STAR]
, потому что семантически вход — отнюдь не простая строка; — но это, очевидно, неудобно). На POSIX shell написать сложный скрипт без eval невозможно, вдобавок все *sh (в т.ч. те, где eval не так нужен) любят внезапно преобразовывать строку в список glob’ов, которые они же сразу раскроют.И здесь «десяток символов» вам не поможет. Насколько я знаю, безопасный набор — это ASCII, причём только буквы, цифры и подчёркивание. Всё остальное либо имеет где?то какое?либо специальное значение, либо может быть неверно воспринято из?за проблем с кодировками. Особенно приколен Windows с его обратными косыми чертами, которые так же являются символом экранирования в большинстве языков программирования.
Так что зачем запрещать символы, если всё, на что способен запрет — это улучшить несколько частных случаев, при этом как ухудшив производительность файловой системы, так и взаимодействие с пользователем? К примеру, в названиях книг встречаются двоеточия, поэтому нельзя взять и сохранить книгу в файле с именем, совпадающим с названием книги — нужно его как?то преобразовывать. Результат, как правило, выглядит хуже, чем оригинальное название.
areht
> Пока имя файла — это имя файла или, хотя бы, просто одна строка никаких проблем нет.
У меня ощущение, что я прослушал лекцию яблоковода о «мне это не нужно».
Кстати, винда и прямые косые понимает. А пути лучше сразу из исходников в конфиг выносить, а как побочный эффект ничего случайно не экранируется.
ZyXI
Это не «не нужно», это «зачем люди придумали строгую типизацию». А прямые косые черты принимаются не везде. Вынос путей из исходников никак не решает проблему, скорее наоборот: пока в вашем скрипте пути внутри вы можете написать
glob.glob("C:\\Foo\\*")
. Когда вместоC:\Foo
у вас путь из настроек вам внезапно нужно экранирование этого пути. Я не говорю, что это не нужно делать: даже не предоставляя настроек в скрипте я часто выношу пути в отдельные константы, определяемые наверху файла. Но проблему «если вы собираете код/регулярное выражение/команду shell/… из кусочков, то вам нужно думать об экранировании» ни вынос части этих кусочков в конфиг, ни запрет символов не решит. Сборка же не в строку, а в более сложную структуру — решит.areht
> Это не «не нужно», это «зачем люди придумали строгую типизацию»
Вы предлагаете в ответ прочитать лекцию почему придумали нестрогую?
> Когда вместо C:\Foo у вас путь из настроек вам внезапно нужно экранирование этого пути.
Действительно внезапно. Но нет, я обхожусь без экранирования — мне сложно разделить вашу боль.
ZyXI
Если эта лекция поддержит вашу позицию по поводу необходимости запрета определённых символов — пожалуйста, почему нет.
Это значит что вы либо получаете уязвимости или плохую привычку (первое если вы распространяете своё ПО, второе — если нет, но можете в будущем), либо используете языки и библиотеки, в которых оно не требуется. В примере с glob вполне можно обойтись без экранирования, если переписать код с использованием
os.listdir
, но он будет длиннее.areht
> либо используете языки и библиотеки
и ОС, что уж )
Ну, которая с десятком запрещенных символов
> Если эта лекция поддержит вашу позицию по поводу необходимости запрета определённых символов — пожалуйста, почему нет.
это не необходимость, а другой способ.
> В примере с glob вполне можно обойтись без экранирования, если переписать код с использованием os.listdir, но он будет длиннее.
А я и не участвую в конкурсе на самый короткий.
Если у вас в конфиге в одном месте экранируется потому, что в коде glob, а в другом нет, потому, что os.listdir — у вас проблемы с конфигом. Или с языком. Или с библиотекой. Или с ОС. Но что-то пора менять, искать другой способ.
ZyXI
Что?! Экранирование происходит в коде, а не конфиге. В случае с
glob.glob("C:\\foo\\*")
ничего не экранируется, потому что нечего и это сразу видно. В случае сglob.glob(os.path.join(globescape(config.foodir), '*'))
вам нужно иметь функциюglobescape
. И не забывать её применять. В случае сglob.glob([config.foodir, glob.STAR])
вы не можете забыть её применить, поскольку она не нужна (предполагается, чтоglob.STAR
— это экземпляр специального класса, а не строка'*'
).Единственное, что в данном случае сделает запрет специальных символов, с которым «жить было бы легче» — это позволит засунуть проверку на них туда, где вы читаете из файла настроек, создав контракт «в настройке типа „путь к каталогу“ не может быть символов из набора …» и таким образом убрав необходимость писать
globescape
. И то только до тех пор, пока вы не захотите вместоglob.glob
подсунуть строку, к примеру, вre.compile
(если, конечно, вы действительно не предлагаете убрать все символы, кроме a-zA-Z0-9_). К тому же, это хорошо только при условии, что вы точно знаете, что ваше ПО не будет запускаться на других платформах.Т.е. жить сильно легче не станет, зато добавится головная боль разработчикам ядра и оно, к тому же, станет работать медленнее.
areht
> В случае с glob.glob(«C:\\foo\\*») ничего не экранируется
Давайте тогда с терминами определимся. У вас слеши 2 раза — это не экранирование?
> вам нужно иметь функцию globescape
Escape all special characters ('?', '*' and '['). This is useful if you want to match an arbitrary literal string that may have special characters in it. Special characters in drive/UNC sharepoints are not escaped, e.g. on Windows escape('//?/c:/Quo vadis?.txt') returns '//?/c:/Quo vadis[?].txt'.
ZyXI
Это тоже экранирование, но на другом уровне: оно для того, чтобы в glob вообще попала обратная косая черта. Экранирование вроде
[]]
— это уже для glob. Так что я несколько не прав и моё утверждение о том, что в примере ничего не экранируется вообще?то следовало написать как «ничего не экранируется специально для glob».А теперь вы хотите вместо glob поискать имя файла где?то регулярным выражением. Или вместо очень ограниченных шаблонов с
?
,*
и[
хотите написать шаблон для zsh, где в список спецсимволов попадают ещё%
,(
и<
(я не про перенаправление), также#
,|
,^
и~
с включённым EXTENDED_GLOB или@
,+
и!
с включённым KSH_GLOB.Т.е. вы своим запретом решаете весьма частный случай, при этом также лишая дополнительных средств выразительности (кстати, напомню про пример с именами книг: вопросительный знак там также встречается). Если не запретить всё подряд, то экранировать где?то что?то придётся, поэтому гораздо полезнее приучать программиста либо экранировать всё и всегда, либо не использовать функции, где экранирование нужно.
areht
Когда частный случай — 99% реального использования, то это не частный случай. '*.pdf' отбирает каждая первая программа чтения pdf, regexp для выбора файлов вряд ли использует хоть одна. Да и мне в моей жизни пока не приходилось отбирать файлы регулярками.
Так что вряд ли вы меня убедите, что wildcard и регулярки — одно и то же. Это вы пытаетесь непонятно что оправдать частными случаями.
> поэтому гораздо полезнее приучать программиста
Только в реальности это сизифов труд, а не «полезнее» (не говоря о том, что и надо не «всегда»).
ZyXI
Я не говорю, что это одно и то же. Я говорю, что это схожие случаи: «нужно запихнуть имя файла куда?то, где часть символов обрабатываются особенным образом». Это решается экранированием, а не запретом символов. И wildcard, кстати, под капотом часто преобразуются в регулярные выражения: и
glob
из Python, и реализация из Vim поступают именно так.Кстати, то что программа чтения pdf показывает
*.pdf
в выпадающем списке совершенно не означает, что внутри она вообще использует что?то похожее наglob.glob()
. Если диалог открытия файлов не самописный, то об этом будет заботиться тулкит, создающий диалог, который нужно написать один раз и которому на вход пойдёт wildcard для файлов в каталоге отдельно от собственно каталога — здесь не нужно никакого экранирования вообще. Ни в читалке — она просто передаёт каталог отдельно от фильтров (иногда неявно: к примеру, стандартный диалог открытия файлов для Windows использует текущий каталог процесса), ни в собственно тулките: вариант сos.listdir
в таком случае более чем уместен, особенно учитывая, что тулкиты обычно написаны на C++.DistortNeo
В той же Windows в самом API функции FindFirstFile директория и фильтр передаются отдельными параметрами, поэтому проблема с экранированием в данном случае возникнуть не может.
areht
> И wildcard, кстати, под капотом часто преобразуются в регулярные выражения: и glob из Python
Давайте всё же договоримся, что «под капотом glob из Python» — это один раз, т.е. «редко», а весь остальной софт на Python так не делает — это «часто». С любым тулкитом — аналогично.
Потом можно подумать есть ли там экранирование при преобразовании в регулярку, но т.к. это «редко», то я не стану.
> которому на вход пойдёт wildcard для файлов в каталоге отдельно от собственно каталога — здесь не нужно никакого экранирования вообще
Так как же вы в
wildcardмаске без экранирования отличите "*.pdf" от "[*].pdf", если "*.pdf" может быть и именем файла, которое приложение хочет открыть? Открытие через диалог файла с предзаданным именем вполне практикуется.ZyXI
В маске обычно просто статические строки, которые разработчик выбирает сам ещё на этапе компиляции. Там может быть что?то вроде статического
.htaccess
, если нужный тип файла вдобавок имеет фиксированное имя, но предзаданное генерируемое имя файла в маске я никогда не видел, видел имя файла по?умолчанию в полеFile name
. Это отдельное поле, и, да, здесь?таки нужно экранирование, если диалог поддерживает маски от пользователя в этом поле — а, насколько я понимаю, это нередкая ситуация.DistortNeo
То есть вы предлагаете зарезервировать некоторое подмножество символов для их использования в исключительно прикладных программах в служебных целях?
areht
0) Мы же в контексте имен файлов говорим?
1) Это как-бы свершившийся факт, а не я предлагаю. Подозреваю, что даже в линуксе назвать файл "*" не будет удачной идеей.
2) «символ» — это что? Глиф? Код? Место на клавиатуре?
Ещё в ASCII первые 32 символа имеют служебные цели. Вот практика показала, что вопросительный знак и звездочка — катят, а SUBSTITUTE — нет. Я думаю потому, что SUBSTITUTE — это неведомая хтоническая хрень и людям не близка.
Может можно было воплотить лучше, но сейчас едва ли поменяешь.
> Но ведь существует полно случаев, когда экранирование используется как будто так и надо: SQL, HTML
Ненене, когда я в html использую > — это язык HTML, с такой вот специальной разметкой. Меня интригует появление специального glob-языка для экранирования glob. Он же уникален для конкретного вот места применения, а язык должен быть переиспользуемым, универсальным.
DistortNeo
Естественно.
Это моё личное дело, как мне удобно называть файлы.
В контексте имён файлов этот ответ очевиден. В случае файловых систем, обычно используемых в Linux — это просто произвольный байт, в случае NTFS — uint16.
Так может, тогда дело в glob, раз его создатели придумали какой-то свой язык?
areht
> Это моё личное дело, как мне удобно называть файлы.
Ок, а
моёВаси личное дело не эскейпить, так что если приложение упадёт при встрече с вашим файлом — это ваше личное дело. У вас там опенсорс, форкните-почините, если что.> В контексте имён файлов этот ответ очевиден.
Ну как-бы нет: есть символы, которые с клавиатуры хрен введешь, и глифа им не положено (что сразу ограничивает применение в именах файлов только у больших затейников). Так что вряд ли вас расстроит использование символа с кодом 15776(random), но и меня использование вместо звездочки не порадует. Мне звездочку-вопросик на клавиатуре надо бы иметь.
> Так может, тогда дело в glob, раз его создатели придумали какой-то свой язык?
Виноватого нашли, ок, этих расстреляем. А как проблему решать?
ZyXI
Неиспользование экранирования сразу вывешивает флаг «здесь водятся уязвимости», а такие фразы ещё вызовут реакцию «этот чувак не Линус Торвальдс, но чего?то он заборзел». Если у вас нет большой базы пользователей, а ПО открытое, то позволить вы себе такого не можете. Если есть большая база, а ПО всё ещё открытое, то можете получить форк?конкурента, а не форк для PR с исправлением. Иногда они даже успешные.
ZyXI
Не замечал такого. Я как?то некоторое время назад решил, что вместо того, чтобы просто иметь свою и чужую (т.н. dotfiles) помойку в $HOME лучше иметь чужую помойку в $HOME, свою в $HOME/tmp, и переносить всё нужное куда?то под $HOME/.. Практически всё с таким именем каталога нормально справлялось, пока экранирование звёздочек при наборе команд в оболочке не надоело мне.
С чем будут реальные проблемы в огромном количестве мест — это с символом
\n
(LF) в имени файла: если нормально написанные программы на нормальных языках программирования (т.е. большинство что я видел, кроме того, что написано на *sh (т.е. скриптов) и VimL (т.е. дополнений для Vim)) такое имя файла отлично переварят, то написать даже bash скрипт, корректно обрабатывающий такие имена, часто может быть проблемой. Я уж не говорю про POSIX shell. Всё остальное нормально работает.А где, простите, общий стандарт на glob, чтобы можно было говорить об универсальности? Вот
man glob
ссылается на POSIX.1-2001, POSIX.1-2008, POSIX.2 — если я напишу в Windows[[=а=]]
, он меня поймёт?areht
> Практически всё с таким именем каталога нормально справлялось
«Практически всё» — это «редко» или «часто»? Я не говорил, что что-то не справиться, я сказал, что плохая идея.
> В маске обычно просто статические
«обычно» — это «часто» или «редко»? Если надо необычно — надо другой тулкит искать? Удобно.
> Это отдельное поле, и, да, здесь?таки нужно экранирование
Там нужно, тут не нужно. Опять удобно!
> если диалог поддерживает маски от пользователя в этом поле — а, насколько я понимаю, это нередкая ситуация.
Редкая ситуация — это когда пользователь способен вспомнить как ему надо заэскейпить в этом очередном тулките. Не программист — пользователь.
> А где, простите, общий стандарт на glob, чтобы можно было говорить об универсальности?
А я о чем? )
Стандарт есть, что ему соответствует — неизвестно. Удобно!!!
ZyXI
«Практически всё» — это все GUI программы, что я использовал, все программы на C (я в основном про coreutils), но не некоторые скрипты (бо?льшая часть — это от того, что у меня ещё не было привычки всё экранировать, то что из скриптов есть в системе не только обычно хорошо написано, но ещё и не имеет причин лезть в $HOME).
«Обычно» — это я ни разу не видел, чтобы маска определялась из источника, который может содержать произвольное имя файла. Так что на вопрос лучше ответите вы. И с какой радости нужно искать новый тулкит, а не функцию экранирования в старом?
Если бы вместо масок была нормальная статическая типизация, то не было бы нужно/не нужно. Было бы «здесь у нас вход типа „имя каталога“ (ну или хотя бы просто строка), здесь — структура, определяющая маску».
А так всегда нужно читать документацию.
Редкая ситуация — это когда пользователь вообще что?то там пишет. Обычно проще просто натыкать мышкой. Я вот про то, что поле с именем файла принимает маски не только в Vivaldi (где какой?то нестандартный диалог) только сейчас узнал, когда пошёл проверять.
areht
«бо?льшая часть — это от того… не имеет причин лезть в $HOME» — по вашей интонации не скажешь, но кажется вы таки согласны, что идея была не очень. Даже не очень важно почему именно, просто жизнь такая.
> здесь — структура, определяющая маску
Давайте правильно сформулируем: строка маски(пути/regexp/чеготамещё) — это и есть сериализованная структура, всё это экранирование — это про правила сериализации. Инициализировать структуры без промежуточного строкового представления — удовольствие так себе. Или вы знаете другой удобный способ ввести маску в поле с именем файла в том же диалоге открытия?
Что вы под статической типизацией тут понимаете — для меня загадка, структуры статической/динамической типизации ортогональны.
> А так всегда нужно читать документацию.
Ну раз нужно — тогда да, а вообще — нет.
Вы немножко отвлекитесь от мысли что нужно всех передрессировать — этого просто не случится.
Вообще как только возникает мысль, что вам все что-то должны — должно приходить чувство безысходности.
> только сейчас узнал, когда пошёл проверять
Как же вы этим диалогом пользовались, не ознакомившись с мануалом? Всегда нужно читать документацию!
DistortNeo
То есть весь сыр-бор из-за того, что программист ленится вызывать escape? Но ведь существует полно случаев, когда экранирование используется как будто так и надо: SQL, HTML, URI, XML, JSON, RegExp и т.д. И почему-то никто не требует запрета использования различных символов в этих случаях.
hdfan2
А как тогда в Windows быть с короткими именами файлов, которые укладываются в 8.3? Получается, они от регистра не зависят (для совместимости с DOS), а длинные зависят? Как объяснить пользователю, что A.txt и a.txt — один и тот же файл, а вот SomeLongName.txtx и somelongname.txt уже разные?
areht
Например, в Windows пусть все зависят. Конечно мы должны мочь создать A.txt и a.txt как разные файлы.
LFN — это не обязательно длинное, это [было бы] «второе» длинное/case sensitive имя.
hdfan2
Тогда при переходе из 3.1 в 95 сломалось бы куча Windows-программ, написанных в предположении, что ФС не регистрочувствительна. Тут никакие LFN не помогут — или мы ломаем совместимость, или нет. В Microsoft решили не ломать.
areht
Я думаю вы драматизируете, приложениям это достаточно безразлично.
Да и для приложений Win 3.1 можно было песочницу со своими правилами оставить.
khim
Вашими бы устами… хотя, впрочем, нет. Как раз разработчики десктопных диструбутивов именно так думают — потому использование Linux успешно и держится на уровне одного процента (иногда двух… пока кто-нибудь опять что-нибудь не поломает).
А вот там, где одного-двух процентов «гиков» недостаточно — пилят патчи к ядру…
areht
Не понял что вам не понравилось, но если вам вдруг показалось, что я case sensitive подход форшу — нет. Я просто описал когда и как его могли внедрить, если бы хотели.
И, кстати, популярный Linux называется android. И там вообще мало кто знает о существовании имен файлов.
khim
Похоже что вы так ничего и не поняли.
Не «если бы хотели», а «если бы Microsoft не было важно, сколько у них будет пользовалей».Вот с Windows Phone — Microsoft уже поступил, как вы описываете. Долой легаси! Кто не следует правилам — мы не виноваты! Даёшь чистую систему!
Ну и где теперь та Windows Phone?
Так точно.
Из разработчиков? Или из пользователей? Если вы про пользователей — так и среди пользователей Windows мало кто знает о существовании имён файлов, расширений и прочей подобной ерунды. А если о разработчиках — ну так программы, созданные этими разработчиками как раз и заставляют поддерживать
/sdcard
в case-insensitive состоянии.И если Android хочет иметь долю рынка близкую к той, что у Windows на десктопе, а не к той, что у Windows Phone на мобильниках — то так будет и впредь…
areht
В этот раз сверху напишу, что бы точно прочитали: приложения win 3.1 можно было запускать в песочнице, с 8.3, без потери совместимости ВООБЩЕ.
> Не «если бы хотели», а «если бы Microsoft не было важно, сколько у них будет пользовалей».
Вы тут видите противоречие? Ну то есть, вы видимо «держали свечку», раз уточняете, что именно из-за боязни что-то там сломать, непонятно в чем, в обратной совместимости они не захотели, но они не захотели.
Я думаю, они не захотели совсем по другим причинам.
> Вот с Windows Phone — Microsoft уже поступил, как вы описываете. Долой легаси! Кто не следует правилам — мы не виноваты! Даёшь чистую систему!
Я действительно ничего не понимаю. «Внедрение case sensetive» = «Даёшь чистую систему!»? Серьезно? Лучше аналогии не придумалось?
А, например, запрет хранения конфигов в Program files, сломавший каждую вторую, прогу вы не считаете нарушением обратной совместимости?
> так и среди пользователей Windows мало кто знает о существовании имён файлов
Остальные ваши факты той же степени достоверности?
sumanai
Винда перенаправляет запись в каталог пользователя, если что.
areht
В Vista и старше, на сколько я помню.
А ограничения прав неожиданно появилось в десктопном xp
sumanai
Да, вместе с UAC, где большинство программ исполнялись от ограниченной учётной записи, точнее, с урезанным маркером администратора, но это уже детали.
Вы ошибаетесь. Права доступа на Program Files не менялись как минимум с Windows 2000. Вот, поставил по быстрому и сделал скриншот. Не сильно отличается даже от Win10, в которой появились TrustedInstaller и пакеты приложений, и исчез PowerUsers.
areht
> Права доступа на Program Files не менялись как минимум с Windows 2000.
Только Windows 2000 никто не пользовался, в отличии от XP, по пришествию которого и встречал нежданчик.
Я там специально «десктопный» написал.
khim
Она туда, кстати, встала. А вот DirectX — уже не встал. Вернее встал, но не запустился: всё требовал свои файлы перенести из C:\PROGRA~1\WINDOWS в C:\PROGRAM FILES\WINDOWS…
А новые программы будут с нуля написаны, да? С Windows Phone попробовали. Результат мы знаем.
Проблема же не только в старых программах, но и в библиотеках. Которые, как выяснилось, могут и upcase «для красоты» делать (MS DOS превращал все символы в большие, но некоторые библиотеки превращали FileName.Ext в FILENAME.EXT принудительно) и отказываться работать, если у системного каталога имя в 8.3 не помещается и делать много разных других чудес.
Нет, потому что Workaround известен всем и каждому — запусти программу под Админом — она и перестанет ругаться.
areht
> Свечку не держал, но Windows 95 в c:\Program Files\Windows ставил.
«Но если бы у рыбы была шерсть...»
Вы как-то яснее мысль излагайте, а то я не улавливаю связи багов в DirectX с запуском софта Windows 3.1 на Win32 и ощущение, что вы случайные факты набрасываете.
express
Не спец по линуксам, но изредка ковыряясь в нем, обратил внимание, что чувствительность к регистру в нем стараются избегать написанием названий всех файлов строчными буквами. На мой взгляд у чувствительности к регистру больше минусов, чем плюсов. Не уверен, что какие-то значимые плюсы вообще есть.
Xalium
значимые плюсы будут в скорости доступа (наверно хоть и небольшие, но будут). Все-таки при чувствительности к регистру это фактически по битовое соответствие. А при нечувствительности наверно придется сначала привести оба значения к одному регистру, если нет лучшего алгоритма.
OldMaster Автор
Для того чтобы выполнять сравнение без учета регистра разработчикам Windows пришлось приложить значительные усилия. Сравнивать нужно не только латинские буквы, но и национальные.
Windows тоже считает что Ласточка и ласточка это один и тот же файл.
А приведение национальных символов к одному регистру это сложная задача.
Например, в греческом алфавите есть заглавная буква которой соответствует две различные строчные буквы. Правила, по котором используется одна или другая буква, учитывает расположение буквы в слове и предшествующую букву.
А в Турецком языке заглавной букве I соответствует строчная буква i, только без точки. И т.д.
Так что, для выполнения сравнения без учёта регистра в Windows приняли некоторые упрощенные правила приведения к верхнему регистру.
Зная все эти сложности я понимаю почему в Linux используется сравнение без учёта регистра.
Xalium
вот поэтому при чувствительности к регистру и будет скорость быстрее. О чем я и сказал.
Bozaro
Регистронезависимое сравнение очень шаткое и сильно зависит от локали.
К примеру, в Турции
windows
/WINDOWS
не то же самое, чтоWINDOWS
/w?ndows
.danfe
Это вы просто к венде привыкли. :-) Я вот каждый раз чертыхаюсь, когда напарываюсь на регистронезависимость венды: «да блин, ну это же разные имена!» Кроме того, это приучает к аккуратности, ибо нефиг писать
#include <stdafx.h>
, когда файл на самом деле называетсяStdAfx.h
. :-)express
Если выбирать между аккуратностью и тратой меньшего количества памяти на запоминание названий файлов, то я выберу, конечно второе. К тому же, на запоминание регестрозависимого файла я приложу больше чем вдвое. Т.к. имя файла обычно запоминающееся и можно запомнить мнемонически, а расположение прописных букв — уже как бог на душу положит — сидеть вспоминать как там было название папки camera или Camera на карте памяти — так себе удовольствие и аккуратность тут не при чем.
danfe
Это лишь один пример (про имена инклюдов). Если погуглить, там много было историй, когда регистронезависимость файлухи внезапно жалила в пятку. Это действительно создает больше проблем чем решает, причем решает-то оно сиюминутные проблемы (типа
camera
vs.Camera
, хотя тут tab-completion помогает), а создает отложенные, про которые заранее не знаешь и не ожидаешь их, пока они не выстрелят.express
Я не очень понял что с этими инклюдами не так. В си (или что это?) тоже регистрозависимость? Ну, тогда это не винда жалит, а си, нет?
Kobalt_x
Как раз винда которая позволяет преароцессору при #include A.h видеть файл a.h и подставлять его содержимое
beerware
Ответ на этот вопрос есть в замечательной книге Эви Немета сотоварищи «UNIX: Руководство системного администратора». Просто надоедает переключать регистр )
Sfinx88
Мне почему то кажется, что подход винды намного более интуитивен, в этом вопросе. Ведь человек тоже воспринимает «ЛАСТОЧКА» и «ласточка» как одно и тоже.
poznawatel
но Ласточка и ласточка — разное
Лопата и лопата
Canti
А в чем разница?
skymal4ik
Например, в том, что Ласточка может быть кличкой, а ласточка — видом птиц. Не думаю впрочем, что такое часто встречается, но оно есть.
poznawatel
Ласточка — скоростная электричка, Лопата — фамилия украинского генерала.
zemavo
А еще могут быть папки Разобрать срочно, Разобрать СРОЧНО и РАЗОБРАТЬ СРОЧНО
mapron
А когда и эти три забиты, создаётся РаЗоБрАтЬ он?оd?!
zemavo
Скорее, 111 РАЗОБРАТЬ СРОЧНО, ### РАЗОБРАТЬ СРОЧНО и потом!!! РАЗОБРАТЬ СРОЧНО, но это уже не относиться к теме нашего обсуждения.
mafia8
Можно сделать значок для конкретной папки такой же, но красного цвета.
Wyrd
Если у вас есть такие папки, то проблема не в файловой системе. Проблема в планировании.
Busla
На верхнем уровне в Linux/Unix то же самое — для человека поиск человеческий, с учётом локалей. И дело не только в больших/маленьких буквах, а и в подмене е/ё в русском, c/c во французском, португальском. Просто «для себя» компьютеры перелопачивают гораздо больше файлов, чем документов для человека.
third112
Ср. Земля (планета) и земля (грунт).
Xalium
ИМХО. Лучше бы сделали такой алгоритм:
* если файл/папка в единственном экземпляре – брать его
* если нет – то если есть с нужным регистром – брать его, если нет…
** если папка, то искать с первой буквой в верхнем, если тютю – смотреть только в нижнем, если и его тютю – обламывать
** если файл – смотреть только в нижнем, если тютю – обламывать
alexmay
Никак не могу представить — для чего такая лихая идеология?
pankraty
Хм. Вот, допустим, процесс 1 хочет открыть файл file.txt, но в папке есть только FILE.txt. В соответствии с вашим алгоритмом, процесс открывает этот файл и работает с ним. В это время процесс 2 создает рядом файл File.txt. После этого процесс 1 проверяет наличие файла с именем file.txt — и не находит его! «Как же так?» — думает он, — «Я ж держу дескриптор открытым, а файл исчез!» И от отчаяния
накладывает на себя рукивываливает ошибку.Xalium
И что в таком случае должен получить процесс? В папке стало 2 файла. Лучше обломить процесс, чем подсунуть ему фиктивный файл.
Изначально мой вариант был короче, но вспомнил, что в винде обычно в именах системных папок первые буквы слов большие, а большинство системных файлов (все не проверял) – мелкий регистр.
Или с помощью API можно получить реальное (т.е. с регистром) имя файла, уже держа дескриптор, то проблем нет (не знаю, есть ли такая возможность). Если нет – значит «неопределенное поведение».
michael_vostrikov
Можно установить флаг
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ObCaseInsensitive=dword:00000000
и использовать Cygwin. Подробнее здесь.На одной работе у нас был репозиторий с парочкой таких файлов. Рабочие машины на Винде. Столько возни было, пока патч не смержили. Stash не сделать, rebase не сделать, reset не работает, ветки не все переключаются. При необходимости делали через Cygwin с его медленным git.
guai
А что будет, если все папки скопом поменять на регистрозависимые? Всё умрёт?
khim
Скорее всего да. Потому что есть много программ, которые, по неизвестной науке причине, делают для имён UpCase, перед тем, как открывать их.
Именно поэтому в «старые добрые времена» регистронезависимость включалась не на уровне папок, а на уровне процессов. То есть сначала, конечно, старый добрый ObCaseInsensitive, а потом ещё каждый процесс должен был не забывать про FILE_FLAG_POSIX_SEMANTICS. Иначе птичка не вылетала…
quwy
Например для того, чтобы составить некий список файлов, не плодя дублей с разным регистром, имена нужно как-то привести к общему знаменателю. Если имена вводит юзер или они приходят из другого неподконтрольного источника, приходится кроме всего прочего нормализовать регистр.
Danil1404
Да. Вот тут прямо под вашим комментарием пример того, что происходит, если просто сделать поиск файлов регистрозависимым — программы не находят то, что ищут. Причем если в нескольких программах (или в нескольких местах одной) используется один и тот же файл, но к нему обращаются про разным именам, то совсем все грустно.
Это, наверное, можно обойти тотальным переименованием большинства файлов в системе, с созданием для них хардлинков, сразу после определения всех мест, где возникла такая проблема. В общем, в реальности это будет невозможно починить.
Averrin
Много лет назад решил я поиграть в Oblivion под Wine. Под виндой все чудесно работало, но вот под онтопиком почему-то некоторые модели и текстуры из дополнений пропадали.
Уже понятно в чем дело, да? Суть в том, что игра сначала искала файлы на диске (их там раскладывали моды), а потом искала в архиве с ресурсами. Разработчики модов называли файлы как бог на душу положит, а вот игра искала строго ImperialCityMageGuildBlahBlah. Ну в винде это не было проблемой, а вот ext4 отказывался считать, что это один и тот же файл.
a5b
Для линукса есть решение (или костыль) — http://www.brain-dump.org/projects/ciopfs/ ciopfs || case insensitive on purpose file system (fuse)
Или jfs/zfs с флагами https://superuser.com/questions/290480/case-insensitive-partition-under-linux
https://wiki.winehq.org/Case_Insensitive_Filenames
rrrrex
Теперь ломать java приложения на винде станет чуть проще.
pmcode
Я как-то создал под Linux папочку с именем aux (типа, вспомогательные файлы), запушил ее в репозиторий, а потом перенес на машину с Windows. Надо ли говорить, что своих файлов я не увидел, да еще и долго провозился с ее удалением. Вот где подстава так подстава. А создавать файлы в одним именем, но разных регистрах, мне бы и в голову не пришло, хотя хорошо что теперь хоть какую-то поддержку завезли.
hdfan2
О да. Файл aux.cpp. Такое не забывается.
third112
DistortNeo
Ещё весело имена файлов с backslash '\' создавать, ну или с двоеточиями.
EvilFox
Кто вдруг будет мучиться c этим, есть пути \\?\путь
Можно создавать и удалять папки/файлы, писать в файл и читать из них через командную строку стандартными командами.
Типа:
> echo hello > "\\?\D:\123\aux.cpp"
> more "\\?\D:\123\aux.cpp"
hello
> del "\\?\D:\123\aux.cpp"
> more "\\?\D:\123\aux.cpp"
Не удается получить доступ к файлу \\?\D:\123\aux.cpp
bliznezz
Раскажите про одинаковые имена файлов и каталогов, не вписывающиеся в архиткутуру линуксовых файловых систем.
Umr001
Что то я вообще не помню такой проблемы. Вина и раньше мне не позволяла создавать папки с разными регистрами но одинаковым названием и сейчас не позволяет. В каких параллельных мирах эта проблема существует?
sumanai
Винда имелась в виду? Просто кроме этой ОС существуют и другие, и печально, что для вас они находятся в параллельных мирах.
Umr001
Ты или писал этот коммент сильно уставшим или был сильно пьян, ежели нет то жаль уже мне тебя. Прочти свой комментарий еще раз, прочти статью и мой комментарий. Автор пишет что в винде(по крайней мере до 8 включительно) можно создавать папки с подобными именами: «новая папка» и «Новая папка» и винда это схавает. Однако нет, не дала мне ни 7 ни 8 так сделать. А если другие ОС чувствительны к регистру то у них и такой проблемы быть не может. Из этого и вопрос последовал, отсюда и параллельные миры
Umr001
sumanai Ты или писал этот коммент сильно уставшим или был сильно пьян, ежели нет то жаль уже мне тебя. Прочти свой комментарий еще раз, прочти статью и мой комментарий. Автор пишет что в винде(по крайней мере до 8 включительно) можно создавать папки с подобными именами: «новая папка» и «Новая папка» и винда это схавает. Однако нет, не дала мне ни 7 ни 8 так сделать. А если другие ОС чувствительны к регистру то у них и такой проблемы быть не может. Из этого и вопрос последовал, отсюда и параллельные миры.
Umr001
на случай если сейчас придут умники и напишут про дублирование коммента и кнопку ответить, я не знаю почему комментарий задублировался и не пошел в ответ, кнопку я нажимал
sumanai
Такого в статье нет, или процитируйте нужный фрагмент.
Проблема на стыке мира ОС, где имена файлов чувствительны к регистру, и мира Windows, где они не чувствительны. Об этом и статья.