Выбрать главу
4.3. Открытие файла: open()

Системный вызов open() либо открывает существующий файл, либо создает и открывает новый файл.

#include <sys/stat.h>

#include <fcntl.h>

int open(const char *pathname, int flags… /* mode_t mode */);

Возвращает дескриптор при успешном завершении или –1 при ошибке

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

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

В ранних версиях 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.

В листинге 4.2 показаны примеры использования open(). В некоторых из них указываются дополнительные биты флагов, которые вскоре будут рассмотрены.

Листинг 4.2. Примеры использования open()

/* Открытие существующего файла для чтения */

fd = open("startup", O_RDONLY);

if (fd == -1)

errExit("open");

/* Открытие нового или существующего файла для чтения и записи с усечением до нуля

байтов; предоставление владельцу исключительных прав доступа на чтение и запись */

fd = open("myfile", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

if (fd == -1)

errExit("open");

/* Открытие нового или существующего файла для записи; записываемые данные

должны всегда добавляться в конец файла */

fd = open("w.log", O_WRONLY | O_CREAT | O_APPEND,

S_IRUSR | S_IWUSR);

if (fd == -1)

errExit("open");

Номер дескриптора файла, возвращаемый системным вызовом open()

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

if (close(STDIN_FILENO) == -1) /* Закрытие нулевого файлового дескриптора */

errExit("close");

fd = open(pathname, O_RDONLY);

if (fd == -1)

errExit("open");

Поскольку дескриптор файла 0 не используется, open() гарантирует открытие файла с этим дескриптором. В разделе 5.5 показывается применение для получения аналогичного результата вызовов dup2() и fcntl(), но с более гибким управлением дескриптором файла. В этом разделе также приводится пример того, как можно извлечь пользу от управления файловым дескриптором, с которым открывается файл.

4.3.1. Аргумент flags системного вызова open()

В некоторых примерах вызова open(), показанных в листинге 4.2, во флаги, кроме режима доступа к файлу, включены дополнительные биты (O_CREAT, O_TRUNC и O_APPEND). Рассмотрим аргумент flags более подробно. В табл. 4.3 приведен полный набор констант, любая комбинация которых с помощью побитового ИЛИ (|), может быть передана в аргументе flags. В последнем столбце показано, какие из этих констант были включены в стандарт SUSv3 или SUSv4.