Linux программирование в примерах - Роббинс Арнольд
38 DIR *dp;
39 struct dirent *ent;
40
41 if ((dp = opendir(dir)) == NULL) {
42 fprintf(stderr, "%s: %s: cannot open for reading: %sn",
43 myname, dir, strerror(errno));
44 return 1;
45 }
46
47 errno = 0;
48 while ((ent = readdir(dp)) != NULL)
49 printf("%8ld %sn", ent->d_ino, ent->d_name);
50
51 if (errno != 0) {
52 fprintf(stderr, "%s: %s: reading directory entries: %sn",
53 myname, dir, strerror(errno));
54 return 1;
55 }
56
57 if (closedir(dp) != 0) {
58 fprintf(stderr, "%s: %s: closedir: %sn",
59 myname, dir, strerror(errno));
60 return 1;
61 }
62
63 return 0;
64 }
Функция process() делает всю работу и большую часть кода проверки ошибок. Основой функции являются строки 48 и 49:
while ((ent = readdir(dp)) != NULL)
printf("%8ld %sn", ent->d_ino, ent->d_name);
Этот цикл читает элементы каталога, по одной за раз, до тех пор, пока readdir() не возвратит NULL. Тело цикла отображает для каждого элемента номер индекса и имя файла. Вот что происходит при запуске программы:
$ <b>ch05-catdir</b> /* По умолчанию текущий каталог */
639063 .
639062 ..
639064 proposal.txt
639012 lightsabers.url
688470 code
638976 progex.texi
639305 texinfo.tex
639007 15-processes.texi
639011 00-preface.texi
639020 18-tty.texi
638980 Makefile
639239 19-i18n.texi
...
Вывод никаким образом не сортируется; он представляет линейное содержимое каталога. (Как сортировать содержимое каталога мы опишем в разделе 6.2 «Функции сортировки и поиска»).
5.3.1.1. Анализ переносимости
Есть несколько соображений по переносимости. Во-первых, не следует предполагать, что двумя первыми элементами, возвращаемыми readdir(), всегда будут '.' и '..'. Многие файловые системы используют организацию каталогов, которые отличаются от первоначального дизайна Unix, и '.' и '..' могут быть в середине каталога или даже вовсе не присутствовать[55].
Во-вторых, стандарт POSIX ничего не говорит о возможных значениях d_info. Он говорит, что возвращенные структуры представляют элементы каталогов для файлов; это предполагает, что readdir() не возвращает пустые элементы, поэтому реализация GNU/Linux readdir() не беспокоится с возвратом элементов, когда 'd_ino == 0'; она переходит к следующему действительному элементу.
Поэтому по крайней мере на системах GNU/Linux и Unix маловероятно, что d_ino когда-нибудь будет равен нулю. Однако, лучше по возможности вообще избегать использования этого поля.
Наконец, некоторые системы используют d_fileno вместо d_ino в struct dirent. Знайте об этом, когда нужно перенести на такие системы код, читающий каталоги.
Косвенные системные вызовы«Не пробуйте это дома, дети!»
- М-р Wizard -
Многие системные вызовы, такие, как open(), read() и write(), предназначены для вызова непосредственно из кода пользователя: другими словами, из кода, который пишете вы как разработчик GNU/Linux.
Однако, другие системные вызовы существуют лишь для того, чтобы дать возможность реализовать стандартные библиотечные функции более высокого уровня, и никогда не должны вызываться непосредственно. Одним из таких системных вызовов является GNU/Linux getdents(); он читает несколько элементов каталога в буфер, предоставленный вызывающим — в данном случае, кодом реализации readdir(). Затем код readdir() возвращает действительные элементы каталога, по одному за раз, пополняя при необходимости буфер.
Эти системные вызовы только-для-библиотечного-использования можно отличить от вызовов для-использования-пользователем по их представлению в странице справки. Например, из getdents(2).
ИМЯ
getdents - получить элементы каталога
ОПИСАНИЕ
#include <unistd.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <linux/unistd.h>
_syscall3(int, getdents, uint, fd, struct dirent*,
dirp, uint, count);
int getdents(unsigned int fd, struct dirent *dirp,
unsigned int count);
Любой системный вызов, использующий макрос _syscallX(), не должен вызываться кодом приложения. (Дополнительную информацию об этих вызовах можно найти в справочной странице для intro(2); вам следует прочесть эту справочную страницу, если вы этого еще не сделали.)
В случае getdents() на многих других системах Unix есть сходный системный вызов; иногда с тем же именем, иногда с другим. Поэтому попытка использования этих вызовов привела бы в любом случае лишь к большому беспорядку с переносимостью; гораздо лучше во всех случаях использовать readdir(), интерфейс которого хорошо определен, стандартизован и переносим.
Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Linux программирование в примерах - Роббинс Арнольд, относящееся к жанру Интернет. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.


