• O_NOFOLLOW — обычно системный вызов open() разыменовывает символьную ссылку. Но, если задан флаг O_NOFOLLOW и аргумент pathname является символьной ссылкой, вызов open() не выполняется (в errno заносится значение ELOOP). Этот флаг особенно пригодится в привилегированных программах, чтобы обеспечить отказ от разыменования символьной ссылки при системном вызове open(). Для предоставления определения этого флага из <fcntl.h> следует добавить макрос проверки возможностей _GNU_SOURCE.
• O_NONBLOCK — открытие файла в неблокируемом режиме (см. раздел 5.9).
• O_SYNC — открытие файла для синхронизированного ввода-вывода. Обратите внимание на буферизацию ввода-вывода на уровне ядра, рассматриваемую в разделе 13.3.
• O_TRUNC — усечение файла до нулевой длины с удалением любых существующих данных, если файл уже существует и является обычным. В Linux усечение происходит, когда файл открывается для чтения или для записи (в обоих случаях нужны права доступа к файлу для записи). В SUSv3 сочетание флагов O_RDONLY и O_TRUNC не оговорено техническими условиями, но большинство других реализаций UNIX ведут себя так же, как и Linux.
4.3.2. Ошибки, возвращаемые из системного вызова open()
В случае возникновения ошибки при попытке открытия файла системный вызов open() возвращает –1, а в errno идентифицируется причина ошибки. Далее перечислены возможные ошибки, которые могут произойти (вдобавок к тем, что уже были упомянуты при описании только что рассмотренного аргумента flags).
• EACCES — права доступа к файлу не позволяют вызывающему процессу открыть файл в режиме, указанном флагами. Из-за прав доступа к каталогу доступ к файлу невозможен или файл не существует и не может быть создан.
• EISDIR — указанный файл является каталогом, а вызывающий процесс пытается открыть его для записи. Это запрещено. (С другой стороны, есть случаи, когда может быть полезно открыть каталог для чтения. Пример будет рассмотрен в разделе 18.11.)
• EMFILE — достигнуто ограничение ресурса процесса на количество файловых дескрипторов (RLIMIT_NOFILE, рассматривается в разделе 36.3).
• ENFILE — достигнуто ограничение на количество открытых файлов, накладываемое на всю систему.
• ENOENT — заданный файл не существует, и ключ O_CREAT не указан; или O_CREAT был указан, и один из каталогов в путевом имени не существует или является символьной ссылкой, ведущей на несуществующее путевое имя (битой ссылкой).
• EROFS — указанный файл находится в файловой системе, предназначенной только для чтения, а вызывающий процесс пытается открыть его для записи.
• ETXTBSY — заданный файл является исполняемым (программой), и в данный момент выполняется. Изменение исполняемого файла, связанного с выполняемой программой (то есть его открытие для записи), запрещено. (Чтобы изменить исполняемый файл, сначала следует завершить программы.)
При дальнейшем описании других системных вызовов или библиотечных функций мы не будем перечислять возможные ошибки, которые могут произойти при подобных обстоятельствах. (Этот перечень можно найти на соответствующих страницах руководства для каждого системного вызова или библиотечной функции.) Во-первых, это связано с тем, что open() — первый системный вызов, который мы подробно рассматриваем, и из списка выше можно увидеть, что системный вызов или библиотечная функция может потерпеть неудачу по любой из множества причин. Во-вторых, конкретные причины, по которым вызов open() может закончиться неудачей, сами по себе составляют весьма интересный список, иллюстрируя множество факторов и проверок, которые нужно учитывать при обращении к файлу. (Приведенный выше список неполон: дополнительные причины отказа open() можно найти на странице руководства open(2).)
4.3.3. Системный вызов creat()
В ранних реализациях UNIX у open() было только два аргумента, и этот вызов нельзя было использовать для создания нового файла. Вместо него для создания и открытия нового файла использовался системный вызов creat().
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
Возвращает дескриптор файла или –1 при ошибке
Системный вызов creat() создает и открывает новый файл с заданным путевым именем или, если файл уже существует, открывает файл и усекает его до нулевой длины. В качестве результата своей работы creat() возвращает дескриптор файла, который может быть использован в последующих системных вызовах. Вызов creat() эквивалентен такому вызову open():
fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
Поскольку аргумент flags системного вызова open() предоставляет больше контроля над тем, как открывается файл (например, вместо O_WRONLY можно указать O_RDWR), системный вызов creat() теперь считается устаревшим, хотя в старых программах он еще встречается.