Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
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 files42 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()Код, работающий с
struct statfstat()fileno()FILE*$ <b>cat myfile >> myfile</b> /* Добавить копию myfile к себе? */И конечно же, проверка работает:
$ <b>echo hi > myfile</b> /* Создать файл */$ <b>v7cat myfile >> myfile</b> /* Попытка добавить файл к себе */cat: input myfile is outputЕсли вы попробуете это с
ch04-catmyfilecatcat$ <b>v7cat < myfile > myfile</b>cat: input - is output$ <b>ls -l myfile</b>-rw-r--r-- 1 arnold devel 0 Mar 24 14:17 myfileВ данном случае это слишком поздно, поскольку оболочка урезала файл
myfile>catstruct stat4.5. Произвольный доступ: перемещения внутри файла
До сих пор мы обсуждали последовательный ввод/вывод, при котором данные читаются или записываются с начала файла и продолжаются до его конца. Часто это все, что требуется программе. Однако, возможно осуществление произвольного ввода/вывода; т.е. читать данные из произвольного положения в файле без необходимости предварительного чтения всего, что находится перед этим местом.
Смещение дескриптора файла является положением внутри открытого файла, начиная с которого будет осуществляться следующая операция чтения или записи. Программа устанавливает смещение с помощью системного вызова
lseek()#include <sys/types.h> /* для off_t; POSIX */#include <unistd.h> /* объявления lseek() и значений whence */off_t lseek(int fd, off_t offset, int whence);Тип
off_tlongoff_tint64_tlseek()int fdДескриптор открытого файла.
off_t offsetПозиция, в которую нужно переместиться. Интерпретация этого значения зависит от параметра
whenceoffset