Есть ли эквивалент MAX_PATH для WinAPI в linux / unix?
Вопрос
Если я хочу выделить массив символов (на C), который гарантированно будет достаточно большим, чтобы содержать любой допустимый абсолютный путь + имя файла, насколько большим он должен быть.
В Win32 есть определение MAX_PATH .Что является эквивалентом для Unix / linux?
Решение
Есть PATH_MAX
, но это немного проблематично. Из раздела ошибок realpath (3) справочной страницы: р>
POSIX.1-2001 стандартная версия этой функции нарушена дизайн, так как невозможно определить подходящий размер для выходной буфер, resolved_path . Согласно POSIX.1-2001 буфер размера PATH_MAX достаточно, но PATH_MAX не обязательно должен быть определен константа, и может потребоваться получить с помощью pathconf (3) , А также pathconf (3) не очень помогает, так как одна рука POSIX предупреждает, что результат pathconf (3) может быть огромным а также не подходит для неправильной памяти, а с другой стороны pathconf (3) может вернуть -1, чтобы показать, что PATH_MAX нет ограничено.
Другие советы
Все остальные ответы пока кажутся правильными в отношении * nix-стороны вещей, но я добавлю предупреждение об этом в Windows.
Документация обманула вас (по недомолвке).
MAX_PATH
действительно определен и, вероятно, даже применим к файлам, хранящимся в FAT или FAT32.Однако любое имя пути может иметь префикс \\?\
чтобы указать Windows API игнорировать MAX_PATH
и пусть драйвер файловой системы принимает решение сам.После этого определения становятся расплывчатыми.
Добавьте к этому тот факт, что имена путей на самом деле являются Unicode (ну, UTS-16) и что при использовании API "ANSI" преобразование во внутреннее имя Unicode и обратно зависит от множества факторов, включая текущую кодовую страницу, и вы получите рецепт путаницы.
Хорошее описание правил для Windows находится по адресу MSDN.Правила намного сложнее, чем я описал здесь вкратце.
Редактировать: Я изменился \\.\
Для \\?\
в приведенном выше примере спасибо за комментарий от KitsuneYMG.
Пути к Windows и пространства имен сложны.Кто-то может даже возразить, что они слишком сложны.Одним из источников сложности является то, что Win32 (а теперь и Win64) API - это подсистема, которая лежит поверх собственной системы Windows NT.
Путь без какого-либо префикса совместим с самым широким спектром платформ Windows.Если он ограничен 7-разрядными символами ASCII, то он совместим с 16-разрядной DOS начиная с версии 2.0 или около того (всякий раз, когда появлялись подкаталоги, которые на самом деле могли быть в DOS 3;но в DOS 1.0 были только корневые каталоги, и \
иероглиф не имел особого значения).
Тот Самый \\?\
префикс приводит к тому, что остаток имени пути передается дословно соответствующему драйверу файловой системы, что приводит к снятию ограничения на MAX_PATH
Персонажи.Если длинное имя пути также находится в общей сетевой папке, то вы можете использовать для него расширенное UNC-имя с префиксом \\?\UNC\server\share\
вместо обычного UNC - имени \\server\share\
.Использование этого префикса ограничивает переносимость на платформы Win32 и более поздние версии Windows, но если вам не требуется поддержка 16-разрядной Windows на устаревшем оборудовании, это не является большой проблемой.
Тот Самый \\.\
приставка - это другое животное.Это позволяет получить доступ к объектам устройств за пределами набора устройств со специальными именами, которые автоматически отображаются Windows в виде специальных имен файлов в каждой файловой папке.Эти специальные имена включают CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8 и LPT9.Обратите внимание, что все эти имена являются особенными независимо от того, используется расширение или нет, или в любом сочетании верхнего или нижнего регистра.Но вполне возможно, что у вас установлено 10 или более COM-портов.Это происходит быстро, если вы играете с USB-модемами или адаптерами последовательного порта USB, поскольку каждому уникальному последовательному порту на базе USB будет присвоено отдельное имя COMn.Если вам нужно получить доступ к 50-му последовательному порту, то вы можете сделать это только с помощью имени \\.\COM50
потому что COM50 - это нет такое специальное имя, как COM1, есть.
Страница MSDN, которую я процитировал выше, имела правильное различие, я просто ввел неправильный префикс в своем первоначальном ответе.
Ну, по крайней мере, в Linux есть:
PATH_MAX
(определено вlimits.h
)FILENAME_MAX
(определено вstdio.h
)
оба они установлены на 4096
в моей системе (x86 Linux).
Обновить: : Некоторая информация из руководства glibc по этому поводу
Каждый из следующих макросов определен в ограничениях.h только в том случае, если в системе установлен фиксированный, единый предел для рассматриваемого параметра.Если система разрешает разным файловым системам или файлам иметь разные ограничения, то макрос не определен;используйте pathconf или fpathconf, чтобы узнать ограничение, применимое к конкретному файлу
FILENAME_MAX является частью стандарта ISO C, он работает в UNIX и Windows. Однако документация библиотеки GNU C содержит следующие предупреждения:
" В отличие от PATH_MAX, этот макрос определяется, даже если нет действительного ограничения. В таком случае его значение обычно очень большое. Это всегда так в системе GNU. Р>
Примечание об использовании: не используйте FILENAME_MAX в качестве размера массива, в котором хранится имя файла! Вы не можете сделать массив таким большим! Использовать динамическое размещение. & Quot;
Вы можете использовать pathconf()
, чтобы выяснить это во время выполнения, но в <limits.h>
также есть определение препроцессора PATH_MAX.
Вы можете использовать функцию realpath
, чтобы выделить буфер, достаточно большой для определенного пути. Если вы передадите ему нулевой указатель в качестве второго аргумента, он выделит достаточно большой буфер для пути. Справочная страница, вероятно, объясняет это лучше, чем я:
realpath () раскрывает все символические ссылки и разрешает ссылки на /./, /../ и дополнительные символы '/' в строке с нулевым символом в конце, названной path, чтобы создать канонизированный абсолютный путь. Полученный путь сохраняется в виде строки с нулевым символом в конце, максимум до байтов PATH_MAX, в буфере, указанном resolved_path. Полученный путь не будет иметь символической ссылки, компонентов / ./ или /../.
Если resolved_path указан как NULL, то realpath () использует malloc (3) для выделения буфера размером до байтов PATH_MAX для хранения разрешенного пути и возвращает указатель на этот буфер. Вызывающий должен освободить этот буфер, используя free (3).
пределы.h
/*
* File system limits
*
* NOTE: Apparently the actual size of PATH_MAX is 260, but a space is
* required for the NUL. TODO: Test?
* NOTE: PATH_MAX is the POSIX equivalent for Microsoft's MAX_PATH; the two
* are semantically identical, with a limit of 259 characters for the
* path name, plus one for a terminating NUL, for a total of 260.
*/
#define PATH_MAX 260
minwindef.h
#define MAX_PATH 260