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

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

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

 if (S_ISCHR(sbuf.st_mode))

devtype = "char";

 else if (S_ISBLK(sbuf.st_mode))

devtype = "block";

 else {

fprintf(stderr, "%s is not a block or character device\n",

argv[1]);

exit(1);

 }

 printf("%s: major: %d, minor: %d\n", devtype,

major(sbuf.st_rdev), minor(sbuf.st_rdev));

 exit(0);

}

Вот что происходит при запуске программы:

$ ch05-devnum /tmp /* Попробовать не устройство */

/tmp is not a block or character device

$ ch05-devnum /dev/null /* Символьное устройство */

char: major: 1, minor: 3

$ ch05-devnum /dev/hda2 /* Блочное устройство */

block: major: 3, minor: 2

К счастью, вывод согласуется с выводом

ls
, давая нам уверенность [59] , что мы в самом деле написали правильный код.

Воспроизведение вывода ls замечательно и хорошо, но действительно ли это полезно? Ответ — да. Любое приложение, работающее с иерархиями файлов, должно быть способно различать различные типы файлов. Подумайте об архиваторе, таком как

tar
или
cpio
. Было бы пагубно, если бы такая программа рассматривала файл дискового устройства как обычный файл, пытаясь прочесть его и сохранить его содержимое в архиве! Или подумайте о
find
, которая может выполнять произвольные действия, основываясь на типе и других атрибутах файлов, с которыми она сталкивается, (
find
является сложной программой; посмотрите find(1), если вы с ней не знакомы.) Или даже нечто простое, как пакет, оценивающий свободное дисковое пространство, тоже должно отличать обычные файлы от всего остального.

59

Технический термин warm fuzzyПримеч. автора.

5.4.4.2. Возвращаясь к V7

cat

В разделе 4.4.4 «Пример: Unix cat» мы обещали вернуться к программе V7

cat
, чтобы посмотреть, как она использует системный вызов
stat
. Первая группа строк, использовавшая ее, была такой:

31 fstat(fileno(stdout), &statb);

32 statb.st_mode &= S_IFMT;

33 if (statb.st_mode != S_IFCHR && statb.st_mode != S_IFBLK) {

34 dev = statb.st_dev;

35 ino = statb.st_ino;

36 }

Этот код теперь должен иметь смысл. В строке 31 вызывается

fstat
для стандартного вывода, чтобы заполнить структуру
statb
. Строка 32 отбрасывает всю информацию в
statb.st_mode
за исключением типа файла, используя логическое AND с маской
S_IFMT
. Строка 33 проверяет, что используемый для стандартного вывода файл не является файлом устройства. В таком случае программа сохраняет номера устройства и индекса в
dev
и
ino
. Эти значения затем проверяются для каждого входного файла в строках 50–56.

50 fstat(fileno(fi), &statb);

51 if (statb.st_dev == dev && statb.st_ino == ino) {

52 fprintf(stderr, "cat: input %s is output\n",

53 ffig ? "-" : *argv);

54 fclose(fi);

55 continue;

56 }

Если значения

st_dev
и
st_ino
входного файла совпадают с соответствующими значениями выходного файла,
cat
выдает сообщение и продолжает со следующего файла, указанного в командной строке.

Проверка сделана безусловно, хотя

dev
и
ino
устанавливаются, лишь если вывод не является файлом устройства. Это срабатывает нормально из-за того, как эти переменные объявлены:

int dev, ino = -1;

Поскольку

ino
инициализирован значением (-1), ни один действительный номер индекса не будет ему соответствовать [60] . То, что
dev
не инициализирован так, является небрежным, но не представляет проблемы, поскольку тест в строке 51 требует, чтобы были равными значения как устройства, так и индекса. (Хороший компилятор выдаст предупреждение, что
dev
используется без инициализации: '
gcc -Wall
' сделает это.)

60

Это утверждение было верно для V7, на современных системах больше нет таких гарантий — Примеч. автора.

Обратите также внимание, что ни один вызов

fstat
не проверяется на ошибки. Это также небрежность, хотя не такая большая, маловероятно, что
fstat
завершится неудачей с действительным дескриптором файла

Проверка того, что входной файл не равен выходному файлу, осуществляется лишь для файлов, не являющихся устройствами. Это дает возможность использовать

cat
для копирования ввода из файлов устройств в самих себя, как в случае с терминалами:

$ tty /* Вывести имя устройства текущего терминала */

/dev/pts/3

$ cat /dev/pts/3 > /dev/pts/3 /* Копировать ввод от клавиатуры на экран */

this is a line of text /* Набираемое в строке */

this is a line of text /* cat это повторяет */

5.4.5. Работа с символическими ссылками

В общем, символические ссылки ведут себя подобно прямым ссылкам; файловые операции, такие, как

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

По этой причине существует системный вызов

lstat
. Он действует точно также, как
stat
, но если проверяемый файл окажется символической ссылкой, возвращаемые сведения относятся к символической ссылке, а не к указываемому файлу. А именно:

• 

S_ISLNK(sbuf.st_mode)
будет
true
.

• 

sbuf.st_size
содержит число байтов в имени указываемого файла.

Мы уже видели, что системный вызов

symlink
создает символическую ссылку. Но если дана существующая символическая ссылка, как можно получить имя файла, на которую она указывает? (Очевидно,
ls
может получить это имя; поэтому мы должны быть способны это сделать.)

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

Варвара Асенкова

Алянский Юрий Лазаревич
Корифеи русской и зарубежной сцены
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Варвара Асенкова

Государь

Кулаков Алексей Иванович
3. Рюрикова кровь
Фантастика:
мистика
альтернативная история
историческое фэнтези
6.25
рейтинг книги
Государь

Газлайтер. Том 22

Володин Григорий Григорьевич
22. История Телепата
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Газлайтер. Том 22

Меняя маски

Метельский Николай Александрович
1. Унесенный ветром
Фантастика:
боевая фантастика
попаданцы
9.22
рейтинг книги
Меняя маски

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II

Моров. Том 4

Кощеев Владимир
3. Моров
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Моров. Том 4

Я снова граф. Книга XI

Дрейк Сириус
11. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я снова граф. Книга XI

Жена по ошибке

Ардова Алиса
Любовные романы:
любовно-фантастические романы
7.71
рейтинг книги
Жена по ошибке

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Страх

Рыбаков Анатолий Наумович
2. Дети Арбата
Проза:
историческая проза
9.49
рейтинг книги
Страх

Инженер Петра Великого 2

Гросов Виктор
2. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Инженер Петра Великого 2

Черта прикрытия

Бэнкс Иэн М.
9. Культура
Фантастика:
боевая фантастика
космическая фантастика
киберпанк
6.67
рейтинг книги
Черта прикрытия

Газлайтер. Том 18

Володин Григорий Григорьевич
18. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 18

Афганский рубеж 2

Дорин Михаил
2. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Афганский рубеж 2