调用open函数可以打开或创建一个文件。
#include <fcntl.h>
int open( const char *pathname, int oflag, ... /* mode_t mode */ );
返回值:若成功则返回文件描述符,若出错则返回-1。
我们将第三个参数写为...,ISO C用这种方法表明余下参数的数量及其类型根据具体的调用会有所不同。对于open函数而言,仅当创建新文件时才使用第三个参数。在函数原型中将此参数放置在注释中。
pathname是要打开或创建的文件的名字。oflag参数可用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成oflag参数(这些常量定义在<fcntl.h>头文件中):
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读、写打开
大多数实现将O_RDONLY 定义为0,O_WRONLY定义为1,O_RDWR定义为2,以与早期的程序兼容。
在这三个常量中必须指定一个且只能指定一个。而下列常量则是可选择的:
O_APPEND 每次写时都追加到文件的尾端。
O_CREAT 若此文件不存在,则创建它。使用此选项时,需要第三个参数mode,用其指定该新文件的访问权限位。
O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则会出错。用此可以测试一个文件是否存在,如果不存在,
则创建此文件,这使测试和创建两者成为一个原子操作。
O_TRUNC 如果此文件存在,而且为只写或读写打开,则将其长度截短为0。
O_NOCTTY 如果pathname指的是终端设备,则不将该设备分配作为此进程的控制终端。
O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选项为文件的本次打开操作和后续的I/O操作设置非阻塞模式。
下面的三个标志也是可选的。它们是Single UNIX Specification(以及POSIX.1)中同步输入和输出选项的一部分:
O_DSYNC 使每次write等待物理I/O操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性被更新。
O_RSYNC 使每一个以文件描述符作为参数的read操作等待,直至任何对文件同一部分进行的未决写操作都完成。
O_SYNC 使每次write都等到物理I/O操作完成,包括由write操作引起的文件属性更新所需的I/O。
O_DSYNC和O_SYNC标志有微妙的区别。仅当文件属性需要更新以反映文件数据变化(例如,更新文件大小以反映文件中包含了更多的数据)时,O_DSYNC标志才影响文件属性。而设置O_SYNC标志后,数据和属性总是同步更新。当文件用O_DSYNC标志打开,在重写其现有的部分内容时,文件时间属性不会同步更新。与此相反,如果文件是用O_SYNC标志打开,那么对文件的每一次write操作都将在write返回前更新文件时间,这与是否改写现有字节或增写文件无关。
由open返回的文件描述符一定是最小的未用到描述符数值。这一点被某些应用程序用来在标准输入、标准输出或标准出错输出上打开新的文件。例如,一个应用程序可以先关闭标志输出(通常是文件描述符1),然后打开另一个文件,执行打开操作前就能了解到该文件一定会在文件描述符1上打开。
文件名和路径名截短
如果NAME_MAX是14,而我们却试图在当前目录中创建一个其文件名包含15个字符的新文件,此时会发生什么呢?按照传统,早期的系统V版本(例如SVR2)允许这种使用方法,但总是将文件名截短为14个字符,而且不给出任何信息,而BSD类的系统和Linux则会返回出错状态,并将errno设置为ENAMETOOLONG。无声无息地截短文件名会引起问题,而且它不仅仅影响到创建新文件。试想,如果NAME_MAX是14,并且存在一个其文件名恰好是14个字符的文件,那么以pathname作为其参数的任一函数(open、stat等)都无法确定该文件的原始名是什么。其原因是这些函数无法判断该文件名是否被截短过。
在POSIX.1中,常量_POSIX_NO_TRUNC决定了是要截短过长的文件名或路径名,还是返回一个出错。
若_POSIX_NO_TRUNC有效,则在整个路径名超过PATH_MAX,或路径名中的任一文件名超过NAME_MAX时,返回出错状态,并将errno设置为ENAMETOOLONG。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。