Linux программирование в примерах
Шрифт:
Как
read
, так и write
могут переместить меньше байтов, чем запрошено. Код приложения (т.е. ваш код) всегда должен учитывать это. 4.4.4. Пример: Unix
cat
Как и было обещано, вот версия cat V7 [47] . Она начинается с проверки опций,
cat
V7 принимает единственную опцию, – u
, для осуществления небуферированного вывода. Общая структура сходна с той, которую мы видели ранее; программа перечисляет файлы, указанные
<stdio.h>
. Во многих случаях код, использующий стандартную библиотеку ввода/вывода, проще читать и писать, поскольку все проблемы с буферами скрыты библиотекой.47
См.
/usr/src/cmd/cat.c
в дистрибутиве V7. Программа без изменений компилируется для GNU/Linux. — Примеч. автора.
1 /*
2 * Объединение файлов.
3 */
4
5 #include <stdio.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8
9 char stdbuf[BUFSIZ];
10
11 main(argc, argv) /* int main(int argc, char **argv) */
12 char **argv;
13 {
14 int fflg = 0;
15 register FILE *fi;
16 register c;
17 int dev, ino = -1;
18 struct stat statb;
19
20 setbuf(stdout, stdbuf);
21 for( ; argc>1 && argv[1][0] == '-'; argc--, argv++) {
22 switch(argv[1][1]) { /* Обработка опций */
23 case 0:
24 break;
25 case 'u':
26 setbuf(stdout, (char*)NULL);
27 continue;
28 }
29 break;
30 }
31 fstat(fileno(stdout), &statb); /* Строки 31-36 объясняются в главе 5 */
32 statb.st_mode &= S_IFMT;
33 if (statb.st_mode != S_IFCHR && statb.st_mode != S_IPBLK) {
34 dev = statb.st_dev;
35 ino = statb.st_ino;
36 }
37 if (argc < 2) {
38 argc = 2;
39 fflg++;
40 }
41 while (--argc > 0) { // Loop over files
42 if (fflg || (*++argv)[0] == '-' && (*argv)[1] == '\0')
43 fi = stdin;
44 else {
45 if ((fi = fopen(*argv, "r")) == NULL) {
46 fprintf(stderr, "cat: can't open %s\n", *argv);
47 continue;
48 }
49 }
50 fstat(fileno(fi), &statb); /*
Строки 50-56 объясняются в главе 5 */
51 if (statb.st_dev == dev && statb.st_ino == ino) {
52 fprintf(stderr, "cat: input %s is output\n",
53 fflg ? "-" : *argv);
54 fclose(fi);
55 continue;
56 }
57 while ((c=getc(fi)) != EOF) /* Копировать содержимое в stdout */
58 putchar(с);
59 if (fi != stdin)
60 fclose(fi);
61 }
62 return(0);
63 }
Следует заметить, что программа всегда завершается успешно (строка 62); можно было написать ее так, чтобы отмечать ошибки и указывать их в возвращаемом значении
main
. (Механизм завершения процесса и значение различных кодов завершения обсуждаются в разделе 9.1.5.1 «Определение статуса завершения процесса».) Код, работающий с
struct stat
и функцией fstat
(строки 31–36 и 50–56), без сомнения, непрозрачен, поскольку мы еще не рассматривали эти функции и не будем рассматривать до следующей главы (Но обратите внимание на использование fileno
в строке 50 для получения нижележащего дескриптора файла, связанного с переменными FILE*
.) Идея в основе этого кода заключается в том, чтобы убедиться, что входной и выходной файлы не совпадают. Это предназначено для предотвращения бесконечного роста файла, в случае подобной команды:
$ cat myfile >> myfile /* Добавить копию myfile к себе? */
И конечно же, проверка работает:
$ echo hi > myfile /* Создать файл */
$ v7cat myfile >> myfile /* Попытка добавить файл к себе */
cat: input myfile is output
Если вы попробуете это с
ch04-cat
, программа продолжит работу, и myfile
будет расти до тех пор, пока вы не прервете ее. GNU версия cat
осуществляет эту проверку. Обратите внимание, что что-то вроде этого выходит за рамки контроля cat
:
$ v7cat < myfile > myfile
cat: input - is output
$ ls -l myfile
– rw-r--r-- 1 arnold devel 0 Mar 24 14:17 myfile
В данном случае это слишком поздно, поскольку оболочка урезала файл
myfile
(посредством оператора >
) еще до того, как cat
получила возможность исследовать файл! В разделе 5.4.4.2 «Возвращаясь к V7 cat» мы объясним код с struct stat
.
Поделиться:
Популярные книги
Возвращение Безумного Бога 5
5. Возвращение Безумного Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Холодный ветер перемен
7. Девяностые
Фантастика:
попаданцы
альтернативная история
6.80
рейтинг книги
Кровь, золото и помидоры
4. Венецианский купец
Фантастика:
альтернативная история
5.40
рейтинг книги
Наследник павшего дома. Том I
1. Расколотый мир
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Книга 5. Империя на марше
5. Империя у края
Фантастика:
альтернативная история
5.00
рейтинг книги
Генерал Скала и сиротка
1. Генерал Скала и Лидия
Любовные романы:
любовно-фантастические романы
6.40
рейтинг книги
Мимик нового Мира 14
13. Мимик!
Фантастика:
юмористическое фэнтези
постапокалипсис
рпг
5.00
рейтинг книги
Стрелок
5. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Безумный Макс. Поручик Империи
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Сержант. Назад в СССР. Книга 4
4. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Третий. Том 2
2. Отпуск
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Боксер 2: назад в СССР
2. Боксер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вопреки судьбе, или В другой мир за счастьем
Любовные романы:
любовно-фантастические романы
6.46
рейтинг книги
Кротовский, сколько можно?
5. РОС: Изнанка Империи
Фантастика:
попаданцы
аниме
5.00