3

在 linux 和 macOS 上,目录可以嵌套到看似任意的深度,如下面的 C 程序所示。然而,在 macOS 而不是在 linux 上,getcwd 返回的嵌套级别似乎有一个硬性限制,特别是嵌套级别 256。当达到该限制时,getcwd 返回 ENOENT,这是一个相当奇怪的错误代码。这个限制从何而来?有办法解决吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>

void fail(char *msg) { perror(msg); exit(1); }

void create_nested_dirs(int n) {

  int i;
  char name[10];
  char cwd[10000];

  if (chdir("/tmp") < 0) fail("chdir(\"/tmp\")");

  for (i=2; i<=n; i++) {
    sprintf(name, "%09d", i);
    printf("%s\n",name);
    if (mkdir(name, 0777) < 0 && errno != EEXIST) fail("mkdir");
    if (chdir(name) < 0) fail("chdir(name)");
    if (getcwd(cwd, sizeof(cwd)) == NULL) fail("getcwd");
    printf("cwd = \"%s\" strlen(cwd)=%d\n", cwd, strlen(cwd));
  }
}

int main() {
  long ret = pathconf("/", _PC_PATH_MAX);
  printf("PATH_MAX is %ld\n", ret);
  create_nested_dirs(300);
  return 0;
}

更新

上面的程序被更新为打印返回的值pathconf("/", _PC_PATH_MAX)和打印返回的路径的长度getcwd

在我运行 macOS Mojave 10.14 的机器上,它PATH_MAX是 1024,正确返回的最长字符串getcwd是 2542 个字符。然后创建一个嵌套深度为 256 的 2552 个字符长的目录,mkdir然后在成功chdir到该目录后,agetcwd以 ENOENT 失败。

如果sprintf(name, "%09d", i);更改为sprintf(name, "%03d", i);路径相当短,getcwd但当目录嵌套深度达到 256 时仍然失败。

所以这里的限制因素是嵌套深度,而不是PATH_MAX.

我对这里源代码的理解是,工作的主体是由调用完成的,fcntl(fd, F_GETPATH, b)所以问题可能出在fcntl.

4

0 回答 0