- Выбираем длинный путь (или прощай MAX_PATH)
- Приложения Win API
- .Net Framework
- .Net Core
- Как включить поддержку длинных путей в Windows 10 (1607)
- Где путь MAX определен в Linux?
- 3 ответов
- Где в Linux определяется PATH_MAX?
- Is there an equivalent to WinAPI’s MAX_PATH under linux/unix?
- 7 Answers 7
- What is the maximum length of a file path in Ubuntu?
- 4 Answers 4
Выбираем длинный путь (или прощай MAX_PATH)
Многим пользователям ПК под управлением ОС Windows, не говоря о разработчиках, знакомы проблемы при работе с длинными (более 260 символов, MAX_PATH) путями файлов или каталогов.
В данной статье рассматриваются способы избавления от этого пережитка при разработке приложений на различных платформах (WinApi, .Net Framework, .Net Core) и активации нативной поддержки длинных путей в Windows 10 (Anniversary Update).
Приложения Win API
В приложениях, которые используют Win API для работы с файлами, рецепт избавления от ограничения MAX_PATH был известен с незапамятных времён – необходимо было использовать Unicode версию функции с окончанием «W» для работы с директорией или файлом и начинать путь с префикса \\?\. Это давало возможность использовать пути длинной до 32767 символов.
В Windows 10 (1607) поведение функций для работы с файлами изменилось: появилась возможность отключить проверку ограничений MAX_PATH на уровне системы.
Это избавляет от необходимости использовать префикса \\?\ и потенциально даёт шанс приложениям, работающим напрямую или косвенно через Win API, получить поддержку длинных путей без необходимости их пересборки. Как активировать эту возможность описано в конце статьи.
.Net Framework
Хотя .Net Framework и использует Win API для работы с файлами — предыдущее изменение не принесло бы результата, т.к. в код BCL встроены предварительные проверки на допустимость длинны имён каталогов и файлов, и до вызова функций Win API дело даже не доходило, выдавая известное исключение. По многочисленным просьбам сообщества (более 4500 на UserVoice) в версии 4.6.2 из кода BCL вырезали проверки ограничения длинны пути, отдав это на откуп операционной и файловой системам!
Вот что это даёт:
- При использовании префикса “\\?\” мы можем работать с длинными путями как в Win API,
- Если активировать нативную поддержку длинных имен файлов Windows 10 (1607), то даже не потребуется использовать префикс!
Как включить:
- Использовать .Net Framework 4.6.2 как цель при сборке приложения.
- Использовать конфигурационный файл, например, если приложение уже было собрано под .Net 4.0:
.Net Core
Тут поддержку длинных путей анонсировали ещё в ноябре 2015 года. Видимо сказалось Open Source природа проекта и отсутствие строгой необходимости обеспечения обратной совместимости.
Как включить:
Всё работает из коробки. В отличие от реализации в .Net Framework – тут нет необходимости в добавлении префикса “\\?\” – он добавляется автоматически при необходимости.
Вот тут можно посмотреть пример.
Как включить поддержку длинных путей в Windows 10 (1607)
Эта возможность по умолчанию отключена. Это объясняется тем, что данная функция является экспериментальной, и имеется необходимость дорабатывать различные подсистемы и приложения для полной поддержки.
Включить встроенную поддержку длинных путей можно создав или изменив следующий параметр системного реестра: HKLM\SYSTEM\CurrentControlSet\Control\FileSystem Параметр LongPathsEnabled (Тип: REG_DWORD) 1 – соответствует значению включено.
Или через групповые политики (Win+R\gpedit.msc) Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths.Оно же в локализованном варианте: Конфигурация компьютера > Административные шаблоны > Система > Файловая система > Включить длинные пути Win32.
Далее источники расходятся во мнении относительно манифеста (или я неправильно понял, но на данный момент проверить не имею возможности). Например, в документации MSDN написано, что манифест можно использовать в качестве альтернативного способа активации поддержки длинных путей в отдельных приложениях, а в блоге MSDN указано, что это является вторым обязательным шагом после активации в политиках.
Но они сходятся в формате задания данной опции:
С CMD, к сожалению, это не сработает, на данный момент, из-за особенностей работы с путями, а в PowerShell должно всё заработать.
На этом мой небольшой пятничный пост заканчивается, оставив за рамками вопросы полноты реализации поддержки длинных путей в Windows 10 (1607), или работоспособность при использовании различных комбинаций редакций Windows, файловых систем и API. По мере поступления новых фактов и результатов экспериментов пост будет обновляться.
Источник
Где путь MAX определен в Linux?
какой файл заголовка я должен вызвать с помощью #include чтобы иметь возможность использовать PATH_MAX в качестве int для определения размера строки?
Я хочу иметь возможность объявить:
но когда я это делаю, мой компилятор (Clang / LLVM в Linux) выдает следующую ошибку:
Я попытался сделать поиск google, но все равно не повезло.
#include
не устраняет проблему / ошибку.
Я также прав, что значение PATH_MAX является int?
3 ответов
его в linux/limits.h .
#define PATH_MAX 4096 /* # chars in a path name including nul */
PATH_MAX имеет некоторые недостатки, как говорится в этот блог (спасибо paulsm4)
имейте в виду, что все еще неясно, если PATH_MAX определяет максимальную длину с конечным нулевым байтом или без него. Это может быть одно или другое в разных операционных системах. Если вы не можете или не хотите проверять, в каком случае это происходит во время компиляции, безопаснее заставить искусственный предел PATH_MAX — 1 . Лучше перебдеть, чем недобдеть. (Очевидно, что вам все равно нужно зарезервировать хотя бы PATH_MAX байты памяти для буферизации строки.)
Это хороший вопрос. Я занимаюсь простым программированием на C и столкнулся с этой проблемой. В вашем конкретном каталоге Linux/Unix, to /usr/include, вот все файлы заголовков для вашей системы.
вы должны увидеть несколько заголовков, определяющих PATH_MAX. И вы можете видеть, что это значение определяется по-разному в разных местах. Вот список из моего Ubuntu (я также вручную удалил некоторые ложные положительные хиты из grep программа.)
выглядит как / linux / limits.h имеет наибольшее определенное число. Я беспокоюсь о переносимости этого файла. Поэтому для безопасности вы можете просто определить этот макрос самостоятельно с другим именем, скажем PATHLEN (4080 достаточно долго для большинства практических ситуаций). Если это для большого пакета программного обеспечения, у вас также есть контроль. Это мое мнение.
Источник
Где в Linux определяется PATH_MAX?
Какой файл заголовка следует вызвать, #include чтобы иметь возможность использовать PATH_MAX в качестве int для определения размера строки?
Я хочу иметь возможность заявить:
Но когда я это сделаю, мой компилятор (Clang / LLVM в Linux) выдает следующую ошибку:
Я попытался выполнить поиск в Google, но все равно не повезло.
#include
НЕ устраняет проблему / ошибку.
Правильно ли я, что значение PATH_MAX — это int?
Его в linux/limits.h .
#define PATH_MAX 4096 /* # chars in a path name including nul */
PATH_MAX имеет некоторые недостатки, упомянутые в этом блоге (спасибо paulsm4)
Имейте в виду, что до сих пор неясно, PATH_MAX определяется ли максимальная длина с завершающим нулевым байтом или без него. Это может быть одно или другое в разных операционных системах. Если вы не можете или не хотите проверять, какой это случай во время компиляции, безопаснее установить искусственное ограничение PATH_MAX — 1 . Береженого Бог бережет. (Очевидно, вам все равно нужно зарезервировать как минимум PATH_MAX байты памяти для буферизации строки.)
Портативный способ сделать это:
При выполнении простого программирования на C я столкнулся с той же проблемой. В вашей конкретной системе Linux каталог / usr / include содержит множество файлов заголовков, специфичных для ОС Linux.
Вы должны увидеть несколько заголовков, определяющих PATH_MAX; к сожалению, это значение определялось по-разному в разных заголовках. Вот список из моего Ubuntu (я также вручную удалил несколько ложных срабатываний из программы grep).
Заголовок /linux/limits.h имеет наибольший номер и должен быть наиболее аутентичным для включения. Альтернативная стратегия — определить свое собственное с другим именем, скажем PATHLEN (4080 достаточно длинный для большинства практических ситуаций). Моя главная цель — научиться использовать find для поиска ответов на ваш вопрос.
PATH_MAX — системный предел. В среде POSIX существуют три категории системных ограничений. Одна из этих категорий — значения переменных имени пути . Системные ограничения, которые зависят от файловой системы, попадают в эту категорию. PATHMAX также является значением переменной имени пути. (поэтому это значение может изменяться от файловой системы к файловой.) Итак, ограничение PATHNAME может быть получено с помощью функций POSIX pathconf () / fpathconf () . Этот способ является переносимым способом получить ограничение PATHNAME для конкретной файловой системы. Пример кода приведен ниже:
Источник
Is there an equivalent to WinAPI’s MAX_PATH under linux/unix?
If I want to allocate a char array (in C) that is guaranteed to be large enough to hold any valid absolute path+filename, how big does it need to be.
On Win32, there is the MAX_PATH define. What is the equivalent for Unix/linux?
7 Answers 7
There is a PATH_MAX , but it is a bit problematic. From the bugs section of the realpath(3) man page:
The POSIX.1-2001 standard version of this function is broken by design, since it is impossible to determine a suitable size for the output buffer, resolved_path. According to POSIX.1-2001 a buffer of size PATH_MAX suffices, but PATH_MAX need not be a defined constant, and may have to be obtained using pathconf(3). And asking pathconf(3) does not really help, since, on the one hand POSIX warns that the result of pathconf(3) may be huge and unsuitable for mallocing memory, and on the other hand pathconf(3) may return -1 to signify that PATH_MAXis not bounded.
The other answers so far all seem right on point about the *nix side of things, but I’ll add a warning about it on Windows.
You’ve been lied to (by omission) by the documentation.
MAX_PATH is indeed defined, and probably even applies to files stored on FAT or FAT32. However, any path name can be prefixed by \\?\ to tell the Windows API to ignore MAX_PATH and let the file system driver make up its own mind. After that, the definitions get fuzzy.
Add to the mix the fact that path names are actually Unicode (well, UTS-16) and that when the «ANSI» API is used the conversion to and from the internal Unicode name is dependent on a bunch of factors including the current code page, and you have a recipe for confusion.
A good description of the rules for Windows is at MSDN. The rules are much more complicated than I’ve summarized here.
Edit: I changed \\.\ to \\?\ in the above thanks to the comment from KitsuneYMG.
Windows paths and namespaces are complicated. Some might even argue they are too complicated. One source of complexity is that the Win32 (and now Win64) API is a subsystem that lays on top of the Windows NT native system.
A path without any prefix is compatible across the widest range of Windows platforms. If it is restricted to 7-bit ASCII characters, then it is compatible with 16-bit DOS since version 2.0 or so (whenever subdirectories were introduced, which might actually have been in DOS 3; but DOS 1.0 only had root directories and the \ character had no special meaning).
The \\?\ prefix causes the balance of the path name to be passed on verbatim to the appropriate file system driver, which is what produces the effect of dropping the restriction to MAX_PATH characters. If the long path name is also on a network share, then you can use an extended UNC name for it with the prefix \\?\UNC\server\share\ instead of the normal UNC name \\server\share\ . Using this prefix restricts portability to Win32 and later Windows platforms, but unless you require support for 16-bit Windows on legacy hardware, that isn’t a big issue.
The \\.\ prefix is a different animal. It allows access to device objects beyond the set of specially named devices that are automatically mapped by Windows as special file names into every file folder. Those special names include CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9. Note that all of those names are special whether or not an extension is used, or in any mix of upper or lower case. But it is possible that you have 10 or more COM ports installed. This happens quickly if you play with USB modems, or USB serial port adapters, since each unique USB-based serial port will be assigned a distinct COMn name. If you need to access the 50th serial port, then you can only do so with the name \\.\COM50 because COM50 is not a special name like COM1 is.
The MSDN page I cited above had the distinction right, I simply typed the incorrect prefix in my original answer.
Источник
What is the maximum length of a file path in Ubuntu?
Having used Windows systems for a long time, I know that at a certain point, an error window can appear when files and folder names become too long.
This happened to me when I tried to backup files with SFTP from a server to a folder in (for example):
As you can see, I tend to build very specified folder paths sometimes and if a file name happens to be long as well, NTFS might not be able to save it this way.
I’m currently worrying about my physical backups, as the folder path on my backup drive will add /backups/(drive name)/. to all file paths.
Is there any such limit (or a similar one) in ext4/Ubuntu that I would have to look out for?
4 Answers 4
The max filename length is 255 bytes. Found in the wiki page for ext4.
And a maximum path of 4096 characters. Found in this Unix&Linux SE Question.
Although, I did find this wiki article that does not specify a max file path in ext4.
$ echo «123abc» | wc -c 7 jtoscarson@Tylers-Ubuntu:
$ echo «123abc» | wc -m 7 The -m is counting characters and the -c is counting bytes. The reason why it is 7 instead of 6 is the end of line character which is not printed. So the total characters in the filename is going to be 255.
As @sergiy-kolodyazhnyy said, the maximum filename length will depend on the filesystem and the vast majority limit filename lengths to 255 bytes.
A notable omission from his chart is optical media. While UDF and the Rock Ridge extensions have the same 255-character limit for filenames, ISO9660 without Rock Ridge and Joliet both have much stricter limits that you may actually run up against if you’re doing something like backing up youtube-dl downloads.
Joliet filenames are limited to either 64 UTF-16 codepoints or 103 of them if your disc-mastering program has an option to break from the spec in ways which seem to cause no harm in practice.
Likewise, ISO 9660 Levels 2 & 3, without the Rock Ridge extensions, are limited to filenames of either 31 characters or 37 if you’re playing fast and loose with the spec.
ISO 9660:1999, which is supported by genisoimage but not by frontends like K3b, has a limit of either 207 bytes (without Rock Ridge) or 197 bytes (with Rock Ridge).
(Source: The genisoimage manpage)
As for the maximum path length, that’s a big misconception. There isn’t one for most Linux filesystems.
There’s a constant named PATH_MAX , but it’s only the maximum for certain POSIX APIs, which you can work around.
The only consequential exceptions to this «no limit on path length» convention are FAT32 and exFAT (32,760 Unicode characters), NTFS and ReFS (32,767 Unicode characters), UDF (1,023 bytes), and ISO 9660 (unclear, but I’ve seen it stated as 180, 207, 212, or 222 bytes).
This can be easily demonstrated by running this small Python program and then exploring the resulting directories.
My bash , which displays the whole path in the prompt, will have trouble with it. However my zsh , which displays only the current folder in the prompt will have no trouble and even has a pwd builtin that can display the entire 5000+-byte path without issue.
Источник