Есть ли эквивалент Linux MAX_PATH в WinAPI под linux / unix? - PullRequest
58 голосов
/ 07 мая 2009

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

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

Ответы [ 7 ]

53 голосов
/ 07 мая 2009

Есть 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 не ограниченная.

43 голосов
/ 08 мая 2009

Остальные ответы до сих пор кажутся правильными в отношении * 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, которую я цитировал выше, имела право на различие, я просто ввела неправильный префикс в своем исходном ответе.

18 голосов
/ 07 мая 2009

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

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

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

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

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

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

6 голосов
/ 28 июня 2011

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

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

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

5 голосов
/ 07 мая 2009

Вы можете использовать <a href="http://linux.about.com/library/cmd/blcmdl3_pathconf.htm" rel="noreferrer">pathconf()</a>, чтобы выяснить это во время выполнения, но есть также определение препроцессора PATH_MAX в <limits.h>.

2 голосов
/ 13 мая 2014

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

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

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

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

0 голосов
/ 20 декабря 2018

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...