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

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

41 if ((dp = opendir(dir)) == NULL) {

42 fprintf(stderr, "%s: %s: cannot open for reading: %s\n",

43 myname, dir, strerror(errno));

44 return 1;

45 }

46

47 errno = 0;

48 while ((ent = readdir(dp)) != NULL)

49 printf("%8ld %s\n", ent->d_ino, ent->d_name);

50

51 if (errno != 0) {

52 fprintf(stderr, "%s: %s: reading directory entries: %s\n",

53 myname, dir, strerror(errno));

54 return 1;

55 }

56

57 if (closedir(dp) != 0) {

58 fprintf(stderr, "%s: %s: closedir: %s\n",

59 myname, dir, strerror(errno));

60 return 1;

61 }

62

63 return 0;

64 }

Функция

process
делает всю работу и большую часть кода проверки ошибок. Основой функции являются строки 48 и 49:

while ((ent = readdir(dp)) != NULL)

printf("%8ld %s\n", ent->d_ino, ent->d_name);

Этот цикл читает элементы каталога, по одной за раз, до тех пор, пока

readdir
не возвратит
NULL
. Тело цикла отображает для каждого элемента номер индекса и имя файла. Вот что происходит при запуске программы:

$ ch05-catdir /* По умолчанию текущий каталог */

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] .

55

В системах GNU/Linux могут монтироваться файловые системы многих операционных систем, не относящихся к Unix. Во многих коммерческих системах Unix также можно смонтировать файловые системы MS-DOS. В таких случаях предположения относительно файловых систем Unix неприменимы — Примеч. автора.

Во-вторых, стандарт 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
, интерфейс которого хорошо определен, стандартизован и переносим.

5.3.1.2. Элементы каталогов Linux и BSD

Хотя мы только что сказали, что вам следует использовать лишь члены

d_ino
и
d_name
структуры
struct dirent
, стоит знать о члене
d_type
в
struct dirent
BSD и Linux. Это значение
unsigned char
, в котором хранится тип файла, имя которого находится в элементе каталога:

struct dirent {

 ...

 ino_t d_ino; /* Как ранее */

 char d_name[...]; /* Как ранее */

 unsigned char d_type; /* Linux и современная BSD */

 ...

};

d_type
может принимать любые значения, описанные в табл. 5.1.

Таблица 5.1. Значения для

d_type

Имя Значение
DT_BLK
Файл блочного устройства
DT_CHR
Файл символьного устройства
DT_DIR
Каталог
DT_FIFO
FIFO или именованный канал
DT_LNK
Символическая ссылка
DT_REG
Обычный файл
DT_SOCK
Сокет
DT_UNKNOWN
Неизвестный тип файла
DT_WHT
Нет элемента (только системы BSD)

Знание типа файла просто путем чтения элемента каталога очень удобно; это может сэкономить на возможно дорогом системном вызове

stat
. (Вызов
stat
вскоре будет описан в разделе 5.4.2 «Получение информации о файле».)

5.3.2. Функции размещения каталогов BSD

Иногда полезно отметить текущее положение в каталоге для того, чтобы иметь возможность позже к нему вернуться. Например, вы пишете код, обходящий дерево каталога, и хотите рекурсивно входить в каждый подкаталог, когда его проходите. (Как отличить файлы от каталогов обсуждается в следующем разделе). По этой причине первоначальный интерфейс BSD включал две дополнительные процедуры:

Поделиться:
Популярные книги

Его наследник

Безрукова Елена
1. Наследники Сильных
Любовные романы:
современные любовные романы
эро литература
5.87
рейтинг книги
Его наследник

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

Адепт. Том 1. Обучение

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
9.27
рейтинг книги
Адепт. Том 1. Обучение

Я – Орк. Том 4

Лисицин Евгений
4. Я — Орк
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я – Орк. Том 4

Кротовский, не начинайте

Парсиев Дмитрий
2. РОС: Изнанка Империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, не начинайте

Я тебя верну

Вечная Ольга
2. Сага о подсолнухах
Любовные романы:
современные любовные романы
эро литература
5.50
рейтинг книги
Я тебя верну

Звезда сомнительного счастья

Шах Ольга
Фантастика:
фэнтези
6.00
рейтинг книги
Звезда сомнительного счастья

Идеальный мир для Лекаря 19

Сапфир Олег
19. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 19

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Real-Rpg. Еретик

Жгулёв Пётр Николаевич
2. Real-Rpg
Фантастика:
фэнтези
8.19
рейтинг книги
Real-Rpg. Еретик

Идеальный мир для Социопата 4

Сапфир Олег
4. Социопат
Фантастика:
боевая фантастика
6.82
рейтинг книги
Идеальный мир для Социопата 4

Бездомыш. Предземье

Рымин Андрей Олегович
3. К Вершине
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Бездомыш. Предземье

Ваше Сиятельство 3

Моури Эрли
3. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 3

Игра топа

Вяч Павел
1. Игра топа
Фантастика:
фэнтези
6.86
рейтинг книги
Игра топа