OPEN(2)

НАЗВАНИЕ
open, creat -- открыть и, вероятно, создать файл или устройство

КРАТКАЯ СВОДКА
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

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

ОПИСАНИЕ
Системный вызов open превращает имя файла в дескриптор файла (небольшое неотрицательное число, используемое при последующем вводе-выводе, например, с read, write, и т. п. Если системный вызов завершается успешно, возвращенный файловый дескриптор является самым маленьким дескриптором, который еще не открыт процессом. В результате этого вызова появляется новый открытый файл, не разделяемый ни с каким процессом (разделяемые открытые файлы могут возникнуть в результате системного вызова fork(2). Новый файловый дескриптор будет оставаться открытым при выполнении функции exec(2) (смотри описание fcntl(2)). Указатель в файле устанавливается в начало. Параметр flags -- это O_RDONLY, O_WRONLY или O_RDWR, задающие, соответственно, открытие файла только для чтения, только для записи и для чтения и записи, которые можно комбинировать с помощью логического ИЛИ с нулем или более нижеследующих флагов:

O_CREAT
    Если файл не существует, то он будет создан. Владелец (uid) файла устанавливается в фактический идентификатор владельца процесса. Группа (gid) устанавливается либо в фактический идентификатор группы процесса или же в идентификатор группы родительского каталога (зависит от типа файловой системы и флагов программы mount, а также прав доступа к родительскому каталогу. См., например, флаги bsdgroups и sysvgroups в файловой системе ext2, которые описаны в mount(8)).

O_EXCL
    Если используется совместно с O_CREAT, то если файл уже существует, то open завершится с ошибкой. В этом контексте символьная ссылка существует, независимо от того, куда она указывает. O_EXCL не работает на файловых системах NFS, а в программах, полагающихся на этот флаг для реализации блокировки, возникнет race condition. Решение для атомарной блокировки с помощью файла: создать файл с уникальным именем на той же самой файловой системе (это имя может содержать, например, имя машины и идентификатор процесса), использовать link(2), чтобы создать ссылку на файл блокировки. Если link() возвращает 0, значит, блокировка была успешной. В противном случае используйте stat(2), чтобы убедиться, что количество ссылок на уникальный файл возросло до двух, что опять означает, что блокировка была успешной.

O_NOCTTY
    Если pathname ссылается на терминальное устройство — см. tty(4), — то оно не станет контролирующим терминалом процесса, даже если у этого процесса нет такового.

O_TRUNC
    Если файл уже существует, является обычным файлом, а режим открытия позволяет запись (то бишь это O_RDWR или O_WRONLY), то он будет обрезан до нулевой длины. Если файл является FIFO или устройством терминала, то флаг O_TRUNC игнорируется. В противном случае действие O_TRUNC не описано. (На многих версиях Linux этот флаг будет игнорирован; на других версиях будет возвращена ошибка.)

O_APPEND
    Файл открывается в режиме добавления. Перед каждым write, файловый указатель перемещается в конец файла, как если бы использовался lseek. O_APPEND может привести к повреждению файлов на файловой системе NFS, если несколько процессов одновременно добавляют данные в один файл. Это происходит из-за того, что NFS не поддерживает добавление в файл, поэтому ядро на машине-клиенте должно эмулировать эту поддержку, что не может быть выполнено без race condition.

O_NONBLOCK или O_NDELAY
    Если возможно, то файл открывается в неблокирующем режиме. Ни open, ни другие последующие операции над возвращенным дескриптором файла не заставят вызывающий процесс ждать. Работа с каналами FIFO также описана в fifo(4). Этот режим не обязан как-либо действовать на файлы, не являющиеся FIFO.

O_SYNC
    Файл открывается в режиме синхронного ввода-вывода. Все вызовы write для соответствующего дескриптора файла блокируют вызывающий процесс до тех пор, пока данные не будут физически записаны оборудованием, на котором находится файл. Однако же, смотри в разделе ОГРАНИЧЕНИЯ.

O_NOFOLLOW
    Если pathname -- это символическая ссылка, то open завершается с кодом ошибки. Это расширение из FreeBSD, которое было добавлено в Linux в версии 2.1.126. Все прочие символические ссылки в имени будут обработаны как обычно. Заголовочные файлы из glibc 2.0.100 и позже содержат определение этого флага; ядра с версиями меньше, чем 2.1.126, игнорируют этот флаг.

O_DIRECTORY
    Если pathname не является каталогом, то open завершится с кодом ошибки. Этот флаг используется только в Linux, и был добавлен в ядре 2.1.126, чтобы избежать проблем с атаками типа "отказ обслуживания", если opendir(2) был вызван с каналом FIFO или ленточным устройством. Этот флаг не следует использовать вне реализации opendir.

O_LARGEFILE
    На 32-битных системах, поддерживающих Большие Файловые Системы, этот флаг позволяет открывать файлы, длина которых не помещается в 31 бит.

Некоторые из вышеописанных флагов могут быть изменены после открытия файла с помощью fctnl. Аргумент mode задает права доступа, которые используются в случае создания нового файла. Они модифицируются обычным способом, используя umask процесса: права доступа свежесозданного файла равны (mode & ~umask). Заметьте, что этот режим доступа относится только к последующим обращениям к свежесозданному файлу; системный вызов open, который создает новый файл только для чтения, вполне может вернуть файловый дескриптор для чтения/записи.

Нижеследующие символические константы можно использовать в mode:

S_IRWXU
    00700 пользователь (владелец файла) имеет права чтения, записи и выполнения.

S_IRUSR (S_IREAD)
    00400 пользователь имеет право чтения

S_IWUSR (S_IWRITE)
    00200 пользователь имеет право записи

S_IXUSR (S_IEXEC)
    00100 пользователь имеет право выполнения

S_IRWXG
    00070 группа имеет права чтения, записи и выполнения

S_IRGRP
    00040 группа имеет право чтения

S_IWGRP
    00020 группа имеет право записи

S_IXGRP
    00010 группа имеет право выполнения

S_IRWXO
    00007 все остальные имеют права чтения, записи и выполнения

S_IROTH
    00004 все остальные имеют право чтения

S_IWOTH
    00002 все остальные имеют право записи

S_IXOTH
    00001 все остальные имеют право выполнения

mode всегда должен быть указан при использовании O_CREAT, во всех остальных случаях этот параметр игнорируется. creat эквивалентен open с flags, равными O_CREAT | O_WRONLY | O_TRUNC.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
open и creat возвращают новый дескриптор файла, или -1, если произошла ошибка (в этом случае errno устанавливается должным образом). Заметьте, что open может открывать файлы устройств, но creat не может создавать их -- используйте для этого mknod(2).

На файловых системах NFS с включенным преобразованием идентификаторов пользователей open может вернуть файловый дескриптор, но, например, read(2) вернет ошибку EACCES. Это из-за того, что клиент выполняет open, проверяя права доступа, но преобразование идентификаторов производится сервером при запросах на чтение и запись. Если файл только что создан, его atime, ctime и mtime, а также ctime и mtime родительского каталога, установлены в текущее время, В противном случае если файл модифицирован из-за флага O_TRUNC, его поля ctime и mtime устанавливаются в текущее время.

ОШИБКИ

EEXIST
    pathname уже существует, и были использованы O_CREAT и O_EXCL.

EISDIR
    pathname ссылается на каталог, а тип доступа подразумевает запись.

EACCES
    Запрошенный доступ к файлу не разрешен, или же один из каталогов в pathname не позволяет поиск (выполнение), или же файл еще не существует, а доступ для записи в родительский каталог не разрешен. error_ENAMETOOLONG(pathname) error_ENOENT(pathname)

ENOTDIR
    Компонент, использованный как каталог в pathname, таковым не является, или был указан флаг O_DIRECTORY, а pathname не является каталогом.

ENXIO
    Установлены O_NONBLOCK | O_WRONLY, файл является каналом FIFO, но нет процессов, которые открыли этот канал для чтения. Возможно также, что файл является файлом устройства, но соответствующее устройство не установлено.

ENODEV
    pathname ссылается на файл устройства, но соответствующего устройства не существует. (Это ошибка в ядре Linux: должен возвращаться ENXIO.)

EROFS
    pathname ссылается на файл, находящийся на файловой системе, смонтированной только для чтения, и был запрошен доступ для записи.

ETXTBSY
    pathname ссылается на исполняемый файл, который в настоящее время исполняется, и был запрошен доступ для записи. error_EFAULT(pathname)

ELOOP
    Слишком много символических ссылок было пройдено при обнаружении pathname, или был указан флаг O_NOFOLLOW, а pathname является символической ссылкой.

ENOSPC
    pathname нужно было создать на устройстве, на котором не было места для нового файла. error_ENOMEM

EMFILE
    Процесс уже открыл максимально допустимое количество файлов.

ENFILE
    Достигнут предел на максимальное общее количество файлов, открытых в системе.

СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID, POSIX, X/OPEN, BSD 4.3 Флаги O_NOFOLLOW и O_DIRECTORY специфичны для Linux. Для того, чтобы получить их определение, может потребоваться определить (через #define) символ _GNU_SOURCE.

ОГРАНИЧЕНИЯ
В протоколе, на котором работает NFS, существует множество недоработок, в числе прочего, оказывающих влияние на O_SYNC и O_NDELAY. POSIX предоставляет три разных варианта синхронного ввода-вывода, соответствующего флагам O_SYNC, O_DSYNC и O_RSYNC. В настоящее время (версия 2.1.130), все они являются синонимами под Linux.

СМОТРИ ТАКЖЕ
read(2), write(2), fcntl(2), close(2), link(2), mknod(2), mount(2), stat(2), umask(2), unlink(2), socket(2), fopen(3), fifo(4)

ПЕРЕВОД
Copyright (C) Alexey Mahotkin <alexm@hsys.msk.ru> 1999-2001