Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

 /* Обзор каталога /home */

 printf("Directory scan of /home:\n");

 printdir("/home", 0);

 printf("done.\n");

 exit(0);

}

Программа просматривает исходные каталоги и формирует вывод, похожий на приведенный далее (отредактированный для краткости). Для того чтобы заглянуть в каталоги других пользователей, вам могут понадобиться права доступа суперпользователя.

$ ./printdir

Directory scan of /home:

neil/

.Xdefaults

.Xmodmap

.Xresources

.bash_history

.bashrc

.kde/

share/

apps/

konqueror/

dirtree/

public_html.desktop

toolbar/

bookmarks.xml

konq_history

kdisplay/

color-schemes/

BLP4e/

Gnu_Public_License

chapter04/

argopt.с

args.с

chapter03/

file.out

mmap.с

printdir

done.

Как

это работает

Большинство операций сосредоточено в функции

printdir
. После некоторой начальной проверки ошибок с помощью функции
opendir
, проверяющей наличие каталога,
printdir
выполняет вызов функции
chdir
для заданного каталога. До тех пор пока элементы, возвращаемые функцией
readdir
, не нулевые, программа проверяет, не является ли очередной элемент каталогом. Если нет, она печатает элемент-файл с отступом, равным
depth
.

Если элемент — каталог, вы встречаетесь с рекурсией. После игнорирования элементов

.
и
..
(текущего и родительского каталогов) функция
printdir
вызывает саму себя и повторяет весь процесс снова. Как она выбирается из этих повторений? Как только цикл
while
заканчивается, вызов
chdir("..")
возвращает программу вверх по дереву каталогов, и предыдущий перечень можно продолжать. Вызов
closedir(dp)
гарантирует, что количество открытых потоков каталогов не больше того, которое должно быть.

Для того чтобы составить представление об окружении в системе Linux, обсуждаемом в главе 4, познакомьтесь с одним из способов, повышающих универсальность программы. Рассматриваемая программа ограничена, потому что привязана каталогу /home. Следующие изменения в функции

main
могли бы превратить эту программу в полезный обозреватель каталогов:

int main(int argc, char* argv[]) {

 char *topdir = ".";

 if (argc >= 2) topdir = argv[1];

 printf("Directory scan of %s\n", topdir);

 printdir(topdir, 0);

 printf("done.\n");

 exit(0);

}

Три

строки изменены и пять добавлено, но это уже универсальная утилита с необязательным параметром, содержащим имя каталога, по умолчанию равным текущему каталогу. Вы можете выполнять ее с помощью следующей командной строки:

$ ./printdir2 /usr/local | more

Вывод будет разбит на страницы, и пользователь сможет листать их. Таким образом, у него появится маленький удобный универсальный обозреватель дерева каталогов. Приложив минимум усилий, вы могли бы добавить статистический показатель использования пробелов, предельную глубину отображения и т.д.

Ошибки 

Как вы видели, многие системные вызовы и функции, описанные в этой главе, могут завершиться аварийно по ряду причин. Когда это происходит, они указывают причину сбоя, задавая значение внешней переменной

errno
. Многие стандартные библиотеки используют эту переменную как стандартный способ оповещения о возникших проблемах. Стоит повторить, что программа должна проверять переменную errno сразу же после возникновения проблемы в функции, поскольку errno может быть изменена следующей вызванной функцией, даже если она завершилась нормально.

Имена констант и варианты ошибок перечислены в заголовочном файле errno.h. К ним относятся следующие:

EPERM
— Operation not permitted (операция не разрешена);

ENOENT
— No such file or directory (нет такого файла или каталога);

EINTR
— Interrupted system call (прерванный системный вызов);

EIO
— I/O Error (ошибка ввода/вывода);

EBUSY
— Device or resource busy (устройство или ресурс заняты);

EEXIST
— File exists (файл существует);

EINVAL
— Invalid argument (неверный аргумент);

EMFILE
— Too many open files (слишком много открытых файлов);

ENODEV
— No such device (нет такого устройства);

EISDIR
— Is a directory (это каталог);

ENOTDIR
— Isn't a directory (это не каталог).

Есть пара полезных функций, сообщающих об ошибках при их возникновении:

strerror
и
perror
.

strerror

Функция

strerror
преобразует номер ошибки в строку, описывающую тип возникшей ошибки. Она может быть полезна для регистрации условий, вызывающих ошибку.

Далее приведена ее синтаксическая запись:

#include <string.h>

char *strerror(int errnum);

perror

Поделиться с друзьями: