Linux программирование в примерах
Новым каталогам, как и всем файлам, присваивается идентификационный номер группы. К сожалению, его работа запутана. Мы отложим обсуждение до раздела 11.5.1 «Группа по умолчанию для новых файлов и каталогов».
Обе функции работают на одном уровне каталога за раз. Если
существует, a/somedirнет, '/somedir/sub1' завершится неудачей. Каждый компонент в длинном пути должен создаваться отдельно (в соответствии с опциейmkdir("/somedir/sub1/sub2"), см. mkdir(1)).-р mkdirТакже, если
завершается символом 'pathname', на некоторых системах/иmkdir()потерпят неудачу, а на других нет. Следующая программа,rmdir(), демонстрирует оба аспекта.ch05-trymkdir.с1 /* ch05-trymkdir.c --- Демонстрирует поведение mkdir().2 Любезность Nelson H.F. Beebe. */34 #include <stdio.h>5 #include <stdlib.h>6 #include <errno.h>78 #if !defined(EXIT_SUCCESS)9 #define EXIT_SUCCESS 010 #endif1112 void do_test(const char *path)13 {14 int retcode;1516 errno = 0;17 retcode = mkdir(path, 0755);18 printf("mkdir(\"%s\") returns %d: errno = %d [%s)\n",19 path, retcode, errno, strerror(errno));20 }2122 int main(void)23 {24 do_test("/tmp/t1/t2/t3/t4"); /*Попытка создания в подкаталоге*/25 do_test("/tmp/t1/t2/t3");26 do_test("/tmp/t1/t2");27 do_test("/tmp/t1");2829 do_test("/tmp/u1"); /* Создать подкаталоги */30 do_test("/tmp/u1/u2");31 do_test("/tmp/u1/u2/u3");32 do_test("/tmp/u1/u2/u3/u4");3334 do_test("/tmp/v1/"); /* Как обрабатывается завершающий '/'? */35 do_test("/tmp/v1/v2/");36 do_test("/tmp/v1/v2/v3/");37 do_test("/tmp/v1/v2/v3/v4/");3839 return(EXIT_SUCCESS);40 }Вот результаты для GNU/Linux:
$ <b>ch05-trymkdir</b>mkdir("/tmp/t1/t2/t3/t4") returns -1: errno = 2 [No such file or directory)mkdir("/tmp/t1/t2/t3") returns -1: errno = 2 [No such file or directory)mkdir("/tmp/t1/t2") returns -1: errno = 2 [No such file or directory]mkdir("/tmp/t1") returns 0: errno = 0 [Success]mkdir("/tmp/u1") returns 0: errno = 0 [Success]mkdir("/tmp/u1/u2") returns 0: errno = 0 [Success]mkdir("/tmp/u1/u2/u3") returns 0: errno = 0 [Success]mkdir("/tmp/u1/u2/u3/u4") returns 0: errno = 0 [Success]mkdir("/tmp/v1/") returns 0: errno = 0 [Success]mkdir("/tmp/v1/v2/") returns 0: errno = 0 (Success]mkdir("/tmp/v1/v2/v3/") returns 0: errno = 0 [Success]mkdir("/tmp/v1/v2/v3/v4/") returns 0: errno = 0 [Success]Обратите внимание, как GNU/Linux принимает завершающий слеш. Не все системы так делают.
5.3. Чтение каталогов
В оригинальных системах Unix чтение содержимого каталогов было просто. Программа открывала каталог с помощью
и непосредственно читала двоичные структурыopen(), по 16 байтов за раз. Следующий фрагмент кода из программы V7struct direct[53], строки 60–74. Он показывает проверку на пустоту каталога.rmdir60 if ((fd = open(name, 0)) < 0) {61 fprintf(stderr, "rmdir: %s unreadable\n", name);62 ++Errors;63 return;64 }65 while (read(fd, (char*)&dir, sizeof dir) == sizeof dir) {66 if (dir.d_ino == 0) continue;67 if (!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, ".."))68 continue;69 fprintf(stderr, "rmdir: %s not empty\n", name);70 ++Errors;71 close(fd);72 return;73 }74 close(fd);В строке 60 каталог открывается для чтения (второй аргумент равен 0, что означает
). В строке 65 читаетсяO_RDONLY. В строке 66 проверяется, не является ли элемент каталога пустым, т. е. с номером индекса 0. Строки 67 и 68 проверяют на наличие 'struct direct' и '.'. По достижении строки 69 мы знаем, что было встречено какое-то другое имя файла, следовательно, этот каталог не пустой...