Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Интернет » Linux программирование в примерах - Роббинс Арнольд

Linux программирование в примерах - Роббинс Арнольд

Читать онлайн Linux программирование в примерах - Роббинс Арнольд

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 36 37 38 39 40 41 42 43 44 ... 253
Перейти на страницу:

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] == '')

43    fi = stdin;

44   else {

45    if ((fi = fopen(*argv, "r")) == NULL) {

46     fprintf(stderr, "cat: can't open %sn", *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 outputn",

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*.) Идея в основе этого кода заключается в том, чтобы убедиться, что входной и выходной файлы не совпадают. Это предназначено для предотвращения бесконечного роста файла, в случае подобной команды:

$ <b>cat myfile &gt;&gt; myfile</b> /* Добавить копию myfile к себе? */

И конечно же, проверка работает:

$ <b>echo hi &gt; myfile</b> /* Создать файл */

$ <b>v7cat myfile &gt;&gt; myfile</b> /* Попытка добавить файл к себе */

cat: input myfile is output

Если вы попробуете это с ch04-cat, программа продолжит работу, и myfile будет расти до тех пор, пока вы не прервете ее. GNU версия cat осуществляет эту проверку. Обратите внимание, что что-то вроде этого выходит за рамки контроля cat:

$ <b>v7cat &lt; myfile &gt; myfile</b>

cat: input - is output

$ <b>ls -l myfile</b>

-rw-r--r-- 1 arnold devel 0 Mar 24 14:17 myfile

В данном случае это слишком поздно, поскольку оболочка урезала файл myfile (посредством оператора &gt;) еще до того, как cat получила возможность исследовать файл! В разделе 5.4.4.2 «Возвращаясь к V7 cat» мы объясним код с struct stat.

4.5. Произвольный доступ: перемещения внутри файла

До сих пор мы обсуждали последовательный ввод/вывод, при котором данные читаются или записываются с начала файла и продолжаются до его конца. Часто это все, что требуется программе. Однако, возможно осуществление произвольного ввода/вывода; т.е. читать данные из произвольного положения в файле без необходимости предварительного чтения всего, что находится перед этим местом.

Смещение дескриптора файла является положением внутри открытого файла, начиная с которого будет осуществляться следующая операция чтения или записи. Программа устанавливает смещение с помощью системного вызова lseek():

#include &lt;sys/types.h&gt; /* для off_t; POSIX */

#include &lt;unistd.h&gt; /* объявления lseek() и значений whence */

off_t lseek(int fd, off_t offset, int whence);

Тип off_t (тип смещения) является знаковым целым, представляющим позиции байтов (смещений от начала) внутри файла. На 32-разрядных системах тип представлен обычно как long. Однако, многие современные системы допускают очень большие файлы, в этом случае off_t может быть более необычным типом, таким, как C99 int64_t или какой-нибудь другой расширенный тип. lseek() принимает три следующих аргумента.

int fd

Дескриптор открытого файла.

off_t offset

Позиция, в которую нужно переместиться. Интерпретация этого значения зависит от параметра whence. offset может быть положительным или отрицательным; отрицательные значения перемещают к началу файла; положительные значения перемещают к концу файла.

1 ... 36 37 38 39 40 41 42 43 44 ... 253
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Роббинс Арнольд.
Комментарии