PATH_MAX
是用于表示环境变量(在这种情况下为PATH
变量)的最大大小的值,但是在大多数情况下并不是这样,请看下面的代码用于将环境变量复制到大小为PATH_MAX
char env[PATH_MAX];
strcpy(path, getenv("PATH"));
如果您可以看到它很容易溢出,可以说使用strncpy
这样可以避免溢出,但是如果您使用它并且PATH
很大,那么MAX_PATH
我们将无法完成PATH
env变量,这让我开始思考如何在不应该溢出也不丢失数据的前提下获取PATH env变量
答案 0 :(得分:5)
通常如果您根本需要复制未知长度的字符串,请使用 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
可以找到它以后。)
如果您要为一个环境变量复制,以便可以延长它或修改它而不更改原始缓冲区,最简单的选择是strdup(3)
from <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。(或更准确地说,由于readdir的大小限制,PATH_MAX为255。)
此外,允许chdir(2)
或open(2)
之类的系统调用在长度超过PATH_MAX
(ENAMETOOLONG
)的路径上失败:
ENAMETOOLONG
路径名或路径名的组成部分太长。
readlink(2)
采用缓冲区大小,因此不需要限制链接目标的长度。只会在您提供的路径中提及ENAMETOOLONG作为可能的错误,而不是链接名称。
即使在现代Linux上,单个文件名的255个字节也是一个硬限制。但是IIRC确实选择允许更长的路径名(具有多个目录组件)。 POSIX规范在长路径上不会open()
出现 require 错误,因此OS可以给出相当小的PATH_MAX,但在可能的情况下仍然可以在更长的路径上工作。
答案 1 :(得分:3)
避免假设已定义$ PATH或长度受限,这是您解决问题的方法,请使用下面的通用代码。
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 */
}