O_RDWR - открыть и на чтение, и на запись.
В System V UNIX эти константы определены в ‹fcntl.h›, а в версиях Berkley (BSD) - в ‹sys/file.h›.
Чтобы открыть существующий файл на чтение, можно написать
fd = open(name, 0_RDONLY, 0);
Далее везде, где мы пользуемся функцией open , ее аргумент perms равен нулю.
Попытка открыть несуществующий файл является ошибкой. Создание нового файла или перезапись старого обеспечивается системным вызовом creat. Например
int creat(char *name, int perms);
fd = creat(name, perms);
Функция creat возвращает дескриптор файла, если файл создан, и -1, если по каким-либо причинам файл создать не удалось. Если файл уже существует, creat "обрежет" его до нулевой длины, что равносильно выбрасыванию предыдущего содержимого данного файла; создание уже существующего файла не является ошибкой.
Если строится действительно новый файл, то creat его создаст с правами доступа, специфицированными в аргументе perms . В системе UNIX с каждым файлом ассоциированы девять битов, содержащие информацию о правах пользоваться этим файлом для чтения, записи и исполнения лицам трех категорий: собственнику файла, определенной им группе лиц и всем остальным. Таким образом, права доступа удобно специфицировать с помощью трех восьмеричных цифр. Например, 0755 специфицирует чтение, запись и право исполнения собственнику файла, а также чтение и право исполнения группе и всем остальным.
Для иллюстрации приведем упрощенную версию программы cp системы UNIX, которая копирует один файл в другой. В нашей версии копируется только один файл, не позволяется во втором аргументе указывать директорий (каталог), и права доступа не копируются, а задаются константой.
#include ‹stdio.h›
#include ‹fcntl.h›
#include "syscalls.h"
#define PERMS 0666 /* RW для собственника, группы и остальных */
void error(char *,…);
/* cp: копирование f1 в f2 */
main(int argc, char *argv[])
{
int f1, f2, n;
char buf[BUFSIZ];
if (argc != 3)
error("Обращение: cp откуда куда");
if ((f1 = open(argv[1], O_RDONLY, 0)) == -1)
error("cp: не могу открыть файл %s", argv[1]);
if ((f2 = creat(argv[2], PERMS)) == -1)
error("cp: не могу создать файл %s, режим %03o", argv[2], PERMS);
while ((n = read(f1, buf, BUFSIZ)) › 0)
if (write(f2, buf, n) != n)
error ("cp: ошибка при записи в файл %s", argv[2]);
return 0;
}
Данная программа создаст файл вывода с фиксированными правами доступа, определяемыми кодом 0666. С помощью системного вызова stat , который будет описан в параграфе 8.6, мы можем определить режим использования существующего файла и задать тот же режим для копии.
Заметим, что функция error , вызываемая с различным числом аргументов, во многом похожа на printf . Реализация error иллюстрирует, как пользоваться другими программами семейства printf . Библиотечная функция vprintf аналогична printf , с той лишь оговоркой, что переменная часть списка аргументов заменена в ней одним аргументом, который инициализируется макросом va_start . Подобным же образом соотносятся функции vfprinf с fprintf и vsprintf с sprintf .
#include ‹stdio.h›
#include ‹stdarg.h›
/* error: печатает сообщение об ошибке и умирает */
void error(char *fmt, …) {
va_list args;
va_start(args, fmt);
fprintf(stderr, "ошибка: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(1);
}
На количество одновременно открытых в программе файлов имеется ограничение (обычно их число колеблется около 20). Поэтому любая программа, которая намеревается работать с большим количеством файлов, должна быть готова повторно использовать их дескрипторы. Функция close( int fd ) разрывает связь между файловым дескриптором и открытым файлом и освобождает дескриптор для его применения с другим файлом. Она аналогична библиотечной функции fclose с тем лишь различием, что никакой очистки буфера не делает. Завершение программы с помощью exit или return в главной программе закрывает все открытые файлы.
Функция unlink( char *name ) удаляет имя файла из файловой системы. Она соответствует функции remove стандартной библиотеки.
Упражнение 8.1. Перепишите программу cat из главы 7, используя функции read , write , open и close . Замените ими соответствующие функции стандартной библиотеки. Поэкспериментируйте, чтобы сравнить быстродействие двух версий.
8.4 Произвольный доступ (lseek)
Читать дальше