if (argc!= 3 || strcmp(argv[1], "-help") == 0)
usageErr("%s old-file new-file\n", argv[0]);
/* Открытие файлов ввода и вывода */
inputFd = open(argv[1], O_RDONLY);
if (inputFd == -1)
errExit("opening file %s", argv[1]);
openFlags = O_CREAT | O_WRONLY | O_TRUNC;
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH; /* rw-rw-rw- */
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd == -1)
errExit("opening file %s", argv[2]);
/* Перемещение данных до достижения конца файла ввода или возникновения ошибки */
while ((numRead = read(inputFd, buf, BUF_SIZE)) > 0)
if (write(outputFd, buf, numRead)!= numRead)
fatal("couldn't write whole buffer");
if (numRead == -1)
errExit("read");
if (close(inputFd) == -1)
errExit("close input");
if (close(outputFd) == -1)
errExit("close output");
exit(EXIT_SUCCESS);
}
fileio/copy.c
Одна из отличительных особенностей модели ввода-вывода UNIX состоит в
$ ./copy test test.old
$ ./copy a.txt /dev/tty
$ ./copy /dev/tty b.txt
$ ./copy /dev/pts/16 /dev/tty
Универсальность ввода-вывода достигается обеспечением того, что в каждой файловой системе и в каждом драйвере устройства реализуется один и тот же набор системных вызовов ввода-вывода. Поскольку детали реализации конкретной файловой системы или устройства обрабатываются внутри ядра, при написании прикладных программ мы можем вообще игнорировать факторы, относящиеся к устройству. Когда требуется получить доступ к конкретным свойствам файловой системы или устройства, в программе можно использовать всеобъемлющий системный вызов ioctl() (см. раздел 4.8). Он предоставляет интерфейс для доступа к свойствам, которые выходят за пределы универсальной модели ввода-вывода.
Системный вызов open() либо открывает существующий файл, либо создает и открывает новый файл.
#include
#include
int open(const char *
Возвращает дескриптор при успешном завершении или –1 при ошибке
Чтобы файл открылся, он должен пройти идентификацию по аргументу pathname. Если в этом аргументе находится символьная ссылка, она разыменовывается. В случае успеха open() возвращает дескриптор файла, который используется для ссылки на файл в последующих системных вызовах. В случае ошибки open() возвращает –1, а для errno устанавливается соответствующее значение.
Аргумент flags является битовой маской, указывающей
В ранних версиях UNIX вместо имен, приведенных в табл. 4.2, использовались числа 0, 1 и 2. В более современных реализациях UNIX эти константы определяются с указанными в таблице значениями. Из нее видно, что O_RWDW (10 в двоичном представлении) не совпадает с результатом операции O_RDONLY | O_WRONLY (0 | 1 = 1); последняя комбинация прав доступа является логической ошибкой.
Когда open() применяется для создания нового файла, аргумент битовой маски режима (mode) указывает на права доступа, которые должны быть присвоены файлу. (Используемый тип данных mode_t является целочисленным типом, определенным в SUSv3.) Если при вызове open() не указывается флаг O_CREAT, то аргумент mode может быть опущен.
Таблица 4.2. Режимы доступа к файлам
Режим доступа
Описание
O_RDONLY
Открытие файла только для чтения
O_WRONLY
Открытие файла только для записи
O_RDWR
Открытие файла как для чтения, так и для записи
Подробное описание прав доступа дается в разделе 15.4. Позже будет показано, что права доступа, фактически присваиваемые новому файлу, зависят не только от аргумента mode, но и от значения umask процесса (см. подраздел 15.4.6) и от (дополнительно имеющегося) списка контроля доступа по умолчанию (access control list) (см. раздел 17.6) родительского каталога. А пока просто отметим для себя, что аргумент mode может быть указан в виде числа (обычно восьмеричного) или, что более предпочтительно, путем применения операции логического ИЛИ (|) к нескольким константам битовой маски, перечисленным в табл. 15.4.