Б.1.1. Открытие файла

Б.1.1. Открытие файла

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

Если второй аргумент равен O_RDONLY, файл открывается только для чтения. При попытке записи в такой файл будет выдана ошибка. Точно так же флаг O_WRONLY объявляет файл доступным только для записи. В случае флага O_RDWR файл открывается и для чтения. и для записи. Не всякий файл можно открыть в любом из трех режимов. Например, существующие права доступа к файлу могут не позволить конкретному процессу открывать файл для чтения или записи. Файл, находящийся в устройстве, запись в которое невозможна (скажем, компакт-диск), тем более нельзя открыть для записи.

Существуют и другие флаги, определяющие режим открытия файла. Все они могут объединяться с помощью операции побитового ИЛИ. Перечислим наиболее распространенные флаги.

? O_TRUNC — приводит к очистке существующего файла. Данные, записываемые в файл, замещают предыдущее содержимое файла.

? O_APPEND — приводит к открытию файла в режиме добавления. Данные, записываемые в файл, добавляются в его конец.

? O_CREAT — означает создание нового файла. Если указанное имя соответствует несуществующему файлу, он будет создан при условии, что заданный каталог существует и процесс имеет разрешение создавать в нем файлы. Если файл уже существует, он будет открыт. При наличии дополнительного флага O_EXCL функция open() откажется открывать существующий файл.

Когда в функции open() задан флаг O_CREAT, должен присутствовать третий аргумент, определяющий права доступа к создаваемому файлу. О режиме доступа к файлу и битах режима рассказывалось в разделе 10.3, "Права доступа к файлам".

Программа, представленная в листинге Б.1, создает файл, имя которого задано в командной строке. Функции open() передается флаг O_EXCL, поэтому в случае указания существующего файла возникнет ошибка. Владельцу и группе нового файла предоставляются права чтения и записи, остальным пользователям — только право чтения (если для пользователя, которому принадлежит программа, установлено значение umask, права доступа к файлу могут оказаться более жесткими).

Значения umask

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

Для изменения значения umask предназначена одноименная команда, принимающая восьмеричный аргумент. Если требуется изменить значение umask работающего процесса, вызовите функцию umask().

Например, функция

umask(S_IRWXO | S_IWGPF);

и команда

% umask 027

означают, что право записи для группы а также права чтения, записи и выполнения для остальных пользователей будут всегда отниматься от прав доступа к создаваемым файлам.

Листинг Б.1. (createfile.c) Создание файла

#include <fcntl.h>

#include <stdio.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc, char* argv[]) {

 /* Путевое имя нового файла */

 char* path = argv[1];

 /* Права доступа к файлу. */

 mode_t mode =

  S_IRUSR | S_IWUSR| S_IRGRP | S_IWGRP | S_IROTH;

 /* Создание файла. */

 int fd = open(path, O_WRONLY | O_EXCL | O_CREAT, mode);

 if (fd == -1) {

  /* Произошла ошибка. Выводим сообщение и завершаем работу. */

  perror("open");

  return 1;

 }

 return 0;

}

Результаты работы программы будут такими:

% ./create-file testfile

% ls -l testfile

-rw-rw-r-- 1 samuel users 0 Feb 1 22:47 testfile

% ./create-file testfile

open: File exists

Обратите внимание на то, что длина файла равна нулю, так как программа не записывала в него никакие данные.