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

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

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 outputn",
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' сделает это.)

Обратите также внимание, что ни один вызов 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 это повторяет */

Оглавление книги


Генерация: 2.790. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз