В чем причина жесткого ограничения глубины вложенности каталога, возвращаемого getcwd в macOS, и как его можно обойти?

#linux #macos #getcwd

#linux #macos #getcwd

Вопрос:

В 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, "	d", i);
    printf("%sn",name);
    if (mkdir(name, 0777) < 0 amp;amp; errno != EEXIST) fail("mkdir");
    if (chdir(name) < 0) fail("chdir(name)");
    if (getcwd(cwd, sizeof(cwd)) == NULL) fail("getcwd");
    printf("cwd = "%s" strlen(cwd)=%dn", cwd, strlen(cwd));
  }
}

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

Обновить

Вышеупомянутая программа была обновлена для печати значения, возвращаемого pathconf("/", _PC_PATH_MAX) и для печати длины пути, возвращаемого getcwd .

На моей машине под управлением macOS Mojave 10.14 PATH_MAX равно 1024, а самая длинная строка, правильно возвращаемая getcwd , имеет длину 2542 символа. Затем с помощью mkdir создается каталог длиной 2552 символа с глубиной вложенности 256, а затем после успешного chdir перехода к этому каталогу происходит getcwd сбой с ENOENT.

Если sprintf(name, " d", i); изменить на sprintf(name, "d", i); , пути будут значительно короче, но getcwd все равно произойдет сбой, когда глубина вложенности каталога достигнет 256.

Итак, ограничивающим фактором здесь является глубина вложенности, а не PATH_MAX .

Мое понимание здесь исходного кода заключается в том, что основная часть работы выполняется вызовом, fcntl(fd, F_GETPATH, b) поэтому проблема может заключаться в fcntl .

Комментарии:

1. Похоже, что это не Posix; см. Ограничивает ли POSIX количество каталогов в корне ОС? . Однако, я, кажется, припоминаю, что OS X имеет ограничение 4K на PATH_MAX . Вы можете запросить его во время выполнения с помощью long ret = pathconf(name, _PC_PATH_MAX); .

2. Источник находится здесь .