Linux программирование в примерах
160 || <(opt_all && info->level <= max_depth) || info->level == 0))161 {162 print_only_size(size_to_print);163 fputc('\t', stdout);164 if (arg_length)165 {166 /* Вывести имя файла, но без суффикса каталога '.' или '/.'167 который мы, возможно, добавили в main. */168 /* Вывести все до добавленной нами части. */169 fwrite(file, arg_length, 1, stdout);170 /* Вывести все после добавленного нами. */171 fputs(file + arg_length + suffix_length172 + (file[arg_length + suffix_length] == '/'), stdout);173 }174 else175 {176 fputs(file, stdout);177 }178 fputc('\n', stdout);179 fflush(stdout);180 }181182 return 0;183 }Условие в строках 158–160 сбивает с толку, и комментарий в строке 157 указывает на это. Условие утверждает: «Если (1a) файл является каталогом и (1b) уровень меньше максимального для вывода (переменные —
и-max-depth) или нулевой, или (2a) должны быть выведены все файлы и уровень меньше, чем максимальный для вывода, или (2b) уровень нулевой», тогда вывести файл. (Версияmax_depthпосле 5.0 использует в этом случае несколько менее запутанное условие.)duСтроки 162–179 осуществляют вывод. Строки 162–163 выводят размер и символ TAB Строки 164–173 обрабатывают специальный случай. Это объяснено далее в
, в строках файла 524–529:du.c524 /* При разыменовании лишь аргументов командной строки мы525 используем флаг nftw FTW_PHYS, поэтому символическая ссылка526 на каталог, указанная в командной строке, в норме не527 разыменовывается. Для решения этого мы идем на издержки,528 сначала добавляя '/.' (или '.'), а затем удаляем их каждый раз529 при выводе имени производного файла или каталога. */В этом случае
равен true, поэтому строки 164–173 должны вывести первоначальное имя, а не измененное В противном случае строки 174–177 могут вывести имя как есть.arg_lengthФу! Куча кода. Мы находим, что это верхний уровень спектра сложности, по крайней мере, насколько это может быть просто представлено в книге данного содержания. Однако, он демонстрирует, что код из реальной жизни часто бывает сложным. Лучшим способом справиться с этой сложностью является ясное именование переменных и подробные комментарии
в этом отношении хорош; мы довольно легко смогли извлечь и изучить код без необходимости показывать все 735 строк программы!du.с8.6. Изменение корневого каталога:
chroot()Текущий рабочий каталог, установленный с помощью
) (см. раздел 8.4.1 «Изменение каталога —chdir(иchdir()»), является атрибутом процесса, таким же, как набор открытых файлов. Он также наследуется новыми процессами.fchdir()Менее известным является то, что у каждого процесса есть также текущий корневой каталог. Это именно на этот каталог ссылается имя пути
. В большинстве случаев корневые каталоги процесса и системы идентичны. Однако, суперпользователь может изменить корневой каталог с помощью (как вы догадались) системного вызова/:chroot()#include <unistd.h> /* Обычный */int chroot(const char *path);Возвращаемое значение равно 0 при успешном завершении и -1 при ошибке.
Как указывает справочная страница GNU/Linux chroot(2), изменение корневого каталога не изменяет текущий каталог: программы, которые должны обеспечить нахождение под новым корневым каталогом, должны также вызвать затем
:chdir()if (chroot("/new/root") < 0) /* Установить новый корневой каталог *//* обработать ошибку */if (chdir("/some/dir") < 0) /* Пути даны не относительно нового корневого каталога *//* обработать ошибку */Системный вызов
чаще всего используется для демонов — фоновых программ, которые должны работать в специальном ограниченном окружении. Например, рассмотрите демон Интернета FTP, допускающий анонимный FTP (соединение любого клиента из любого места, без обычных имени пользователя и пароля). Очевидно, такое соединение не должно быть способным видеть все файлы целой системы. Вместо этого демон FTP выполняетchroot()в специальный каталог со структурой, достаточной лишь чтобы позволить ему функционировать. (Например, со своим собственнымchroot()для перечисления файлов, со своей копией библиотеки С времени исполнения, если она разделяется, и, возможно, со своей копией/bin/lsи/etc/passwdдля отображения ограниченного набора имен пользователей и групп.)/etc/groupPOSIX не стандартизует этот системный вызов, хотя GNU/Linux и все системы Unix его поддерживают. (Он популярен с V7.) Он специализирован, но при необходимости очень удобен.
8.7. Резюме
• Файловые системы являются коллекциями блоков индексов, данных, вспомогательных данных и свободных блоков, организованных особым способом. Файловые системы один к одному соответствуют (физическим или логическим) разделам, на которых они создаются. У каждой файловой системы есть свой корневой каталог; по соглашению, у корневого каталога номер индекса всегда равен 2.
• Команда
монтирует файловую систему, наращивая логическое иерархическое пространство имен файлов. Командаmountотсоединяет файловую систему. Ядро делаетumountи/.одним и тем же; корневой каталог всего пространства имен является своим собственным родителем. Во всех остальных случаях ядро устанавливает в корневом каталоге смонтированной файловой системы указывающим на родительский каталог точки монтирования./..