it-swarm.com.ru

Есть ли эквивалент Linux MAX_PATH в WinAPI под linux/unix?

Если я хочу выделить массив символов (в C), который гарантированно будет достаточно большим, чтобы содержать любой допустимый абсолютный путь + имя файла, насколько большим он должен быть. 

На Win32 есть определение MAX_PATH. Что эквивалентно для Unix/Linux?

55
AndrewR

Существует PATH_MAX, но это немного проблематично. Из раздела об ошибках страницы realpath (3) man:

Стандартная версия этой функции POSIX.1-2001 нарушена дизайн, так как невозможно определить подходящий размер для выходной буфер, resolved_path. Согласно POSIX.1-2001 буфер Размер PATH_MAX достаточен, но PATH_MAX не обязательно должен быть определен константа, и может потребоваться получить с помощью pathconf (3) . А также Запрос pathconf (3) на самом деле не помогает, так как, с одной стороны, POSIX предупреждает, что результат pathconf (3) может быть огромным и не подходит для неправильной памяти, а с другой стороны pathconf (3) может вернуть -1, чтобы показать, что PATH_MAX не ограничены.

48
stefanB

Остальные ответы до сих пор кажутся правильными в отношении стороны * nix, но я добавлю предупреждение об этом в Windows.

Вы были обмануты (бездействием) документацией. 

MAX_PATH действительно определен и, вероятно, даже применяется к файлам, хранящимся в FAT или FAT32. Однако любое имя пути может начинаться с префикса \\?\, чтобы указать Windows API игнорировать MAX_PATH и позволить драйверу файловой системы принять собственное решение. После этого определения становятся нечеткими.

Добавьте к этому тот факт, что имена путей на самом деле являются Unicode (ну, UTS-16) и что при использовании API «ANSI» преобразование во внутреннее имя Unicode и из него зависит от множества факторов, включая текущую кодовую страницу. и у вас есть рецепт путаницы.

Хорошее описание правил для Windows в MSDN . Правила намного сложнее, чем я здесь изложил.

Edit: Я изменил \\.\ на \\?\ выше благодаря комментарию от KitsuneYMG.

Пути Windows и пространства имен сложны. Некоторые могут даже утверждать, что они слишком сложны. Одним из источников сложности является то, что Win32 (а теперь и Win64) API - это подсистема, которая находится поверх собственной системы Windows NT. 

Путь без префикса совместим с самыми разными платформами Windows. Если он ограничен 7-битными ASCII символами, то он совместим с 16-битной DOS начиная с версии 2.0 или около того (всякий раз, когда были введены подкаталоги, которые могли фактически быть в DOS 3; но DOS 1.0 имел только root каталоги и символ \ не имели особого значения).

Префикс \\?\ приводит к тому, что баланс имени пути дословно передается в соответствующий драйвер файловой системы, что приводит к удалению ограничения на символы 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 - это not специальное имя, такое как COM1.

Страница MSDN, которую я цитировал выше, имела право на различие, я просто набрал неправильный префикс в своем исходном ответе.

42
RBerteig

Ну, по крайней мере, в Linux есть:

  • PATH_MAX (определено в limits.h)

  • FILENAME_MAX (определено в stdio.h)

в моей системе для них обоих установлено значение 4096 (x86 Linux).

Обновление:: Некоторая информация из руководства glibc по этому вопросу

Каждый из следующих макросов определяется в limit.h только в том случае, если система имеет фиксированный, равномерный предел для рассматриваемого параметра. Если система позволяет различным файловым системам или файлам иметь разные ограничения, то макрос не определен; используйте pathconf или fpathconf, чтобы узнать ограничение, которое применяется к конкретному файлу

18
AndrewR

FILENAME_MAX является частью стандарта ISO C, он работает в UNIX и Windows. Однако документация библиотеки GNU C содержит следующие предупреждения:

«В отличие от PATH_MAX, этот макрос определяется, даже если фактический предел не установлен. В этом случае его значение обычно очень большое. Это всегда так в системе GNU. 

Примечание об использовании: Не используйте FILENAME_MAX в качестве размера массива, в котором хранится имя файла! Вы не можете сделать массив таким большим! Используйте динамическое распределение. "

6
cdarke

Вы можете использовать pathconf(), чтобы выяснить это во время выполнения, но в <limits.h> также есть определение препроцессора PATH_MAX.

5
unwind

Вы можете использовать функцию realpath, чтобы выделить буфер, достаточно большой для определенного пути. Если вы передадите ему нулевой указатель в качестве второго аргумента, он выделит достаточно большой буфер для пути. Справочная страница, вероятно, объясняет это лучше, чем я:

realpath () раскрывает все символические ссылки и разрешает ссылки на /./, /../ и дополнительные символы '/' в строке с нулевым символом в конце, названной path, чтобы создать канонизированный абсолютный путь. Полученный путь сохраняется в виде строки с нулевым символом в конце, максимум до байтов PATH_MAX, в буфере, указанном resolved_path. Полученный путь не будет иметь символической ссылки, компонентов/./ или /../.

Если resolved_path указан как NULL, то realpath () использует malloc (3) для выделения буфера размером до PATH_MAX для хранения разрешенного пути и возвращает указатель на этот буфер. Вызывающая сторона должна освободить этот буфер, используя free (3). 

http://linux.die.net/man/3/realpath

2
user1091954

limits.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
0
Puddle