如您所知,
PATH_MAX
是用于指示环境变量的最大大小(在本例中为PATH
变量)的值,但在大多数情况下,情况并非如此,请看一下用于复制环境变量转换为大小为 PATH_MAX
的数组
char env[PATH_MAX];
strcpy(path, getenv("PATH"));
如果你看到它很容易溢出,有人会说使用
strncpy
这样你就可以避免溢出,但如果你使用它并且PATH
很大,那么MAX_PATH
我们将无法获得PATH
env 变量完整,这让我思考,如何在假设不应该溢出或数据丢失的情况下获取 PATH env 变量
一般来说,如果你需要复制一个未知长度的字符串,请参阅string_copying(7)
手册页:
strncpy
通常是错误的选择,而不是以0结尾的长字符串,并且浪费时间归零到短字符串大小限制的末尾。除了
strlen
+ 手动检查 +
memcpy
之外,便携式 ISO C 没有任何好的选择,即使这样也不是很好,因为它会读取输入两次。
string_copying
手册页显示了 POSIX.2008
stpecpy
中非标准化 memccpy
的实现,其中停止字符为 0
,添加手动终止符以防输入不合适.或使用
strdup
如您所知,不,不是;与
PATH_MAX
是用于指示环境变量的最大大小的值(在本例中为PATH
变量)
$PATH
或环境无关!!
它是单个文件系统路径名的最大长度。例如/foo/bar/verylongdirectoryname/x/y.txt
保证长度最多为
PATH_MAX
。否则您可能无法使用绝对路径读取它,而必须改为 chdir 到该树中并使用相对路径。
PATH
环境只是一个像任何其他环境变量一样的扁平字符串;内核不会将它们剪裁为固定长度。或者当然不限于
PATH_MAX
。
我如何在假设不应该溢出或数据丢失的情况下获取 PATH 环境变量
呃,你已经有了getenv("PATH")
getenv
的调用不会破坏指针。 (在 Linux 上,环境变量在进程启动时位于 argv 上方的堆栈上。在任何内容移动堆栈指针之前运行的 CRT 启动代码将指向它们的指针存储在全局
envp
中,
getenv
稍后可以找到它。)如果您想
复制环境变量的缓冲区,以便可以延长它,或者在不更改原始版本的情况下修改它,最简单的选项是strdup(3)
从
<string.h>
到malloc副本。(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)。
readdir(3)
手册页没有这么说,但是
struct dirent
成员
char d_name[256]; /* Null-terminated filename */
的大小是专门这样设置的,因为
PATH_MAX
= 255。(或者更准确地说,由于 readdir 大小限制,PATH_MAX 是 255。 )
chdir(2)
或
open(2)
这样的系统调用也可以在长于
PATH_MAX
(
ENAMETOOLONG
) 的路径上失败:
采用缓冲区大小,因此不需要限制链接目标的长度;它只提到 ENAMETOOLONG 作为您提供的路径中可能存在的错误,而不是链接名称。路径名或路径名的组成部分太长。
ENAMETOOLONG
require open()
错误,因此操作系统可以提供相当小的 PATH_MAX,但在可能的情况下仍然适用于更长的路径。
char *path = NULL;
const char *temp = getenv("PATH");
if (temp != NULL) {
path = (char*) malloc(strlen(temp) + 1);
if (path == NULL) {
/* Handle error condition */
} else {
strcpy(path, temp);
}
/* Use path */
}