В общем случае , если вам вообще нужно скопировать строку неизвестной длины, используйте strncpy
для копирования в буфер фиксированного размера с ограничением размера (но остерегайтесь неудобного не завершать строку, если она слишком длинная).
Или используйте strdup
для выделения копии.
как вы знаете PATH_MAX
- это значение, используемое для указания максимального размера переменной среды (в данном случае PATH
переменная)
Нет, это не так; это не имеет ничего общего с $PATH
или окружающей средой !!
Максимальная длина пути к одной файловой системе . например /foo/bar/verylongdirectoryname/x/y.txt
гарантированно будет иметь длину PATH_MAX
. В противном случае вы не сможете прочитать его с абсолютным путем, и вместо этого вам придется chdir в это дерево и использовать относительный путь.
Среда PATH
- это просто плоская строка, как и любой другой env var; ядро не обрезает их до фиксированной длины. Или, конечно, не ограничен PATH_MAX
.
как я могу получить переменную PATH env с предположением, что не должно быть ни переполнения, ни потери данных
Э-э, у вас уже есть getenv("PATH")
. Это возвращает указатель на существующую строку в области памяти вашего процесса. Это эффективно в статическом хранилище; вам не нужно копировать его, и будущие вызовы на getenv
не сломают указатель. (В Linux env vars находятся в стеке выше argv при запуске процесса. Код запуска CRT, который запускается до того, как что-либо перемещается, указатель стека сохраняет указатель на них в глобальном envp
, где getenv
может найти его позже.)
Если вы хотите скопировать буфер для env var, чтобы вы могли удлинить его или изменить без изменения оригинала, самый простой вариант - strdup(3)
из <string.h>
для размещения копии. (POSIX 2008, а до этого BSD, GNU C и другие системы до этого). Или strndup
, чтобы установить ограничение на количество копируемых байтов.
GNU C даже имеет версию, основанную на alloca, а не malloc, на случай, если вам понадобится более дешевое временное хранилище для автоматического хранения.
PATH_MAX
PATH_MAX
относится, например, к функциям POSIX, таким как getwd(3)
, где вы предоставляете буфер, но без ограничения длины. (Но на самом деле вы должны использовать char *getcwd(char *buf, size_t size)
вместо этого; смотрите ту же ссылку, что и getwd
. На странице руководства также написано:
Обратите внимание, что в некоторых системах PATH_MAX
не может быть константой времени компиляции; кроме того, его стоимость может зависеть
в файловой системе см. pathconf (3).
Справочная страница Linux readdir(3)
не говорит об этом, но размер struct dirent
члена char d_name[256]; /* Null-terminated filename */
определен именно таким образом, потому что PATH_MAX
= 255. (Точнее, PATH_MAX равен 255 из-за размера readdir ограничение.)
Кроме того, системные вызовы, такие как chdir(2)
или open(2)
, допускаются сбои на путях длиннее PATH_MAX
(ENAMETOOLONG
):
ENAMETOOLONG
Имя пути или компонент имени пути был слишком длинным.
readlink(2)
принимает размер буфера, поэтому ему не нужно ограничивать длину целевой ссылки; ENAMETOOLONG упоминается только как возможная ошибка в указанном вами пути, а не в имени ссылки.
Даже в современном Linux 255 байт для одного имени файла является жестким ограничением. Но IIRC разрешает использовать более длинные пути (с несколькими компонентами каталогов). Спецификация POSIX не требует ошибок для open()
на длинном пути, поэтому ОС может выдавать достаточно малый PATH_MAX, но при этом по-прежнему работать с более длинными путями, когда это возможно.