3.3 open函数
调用open函数可以打开或创建一个文件。

我们将第三个参数写为...,ISO C用这种方法表明余下参数的数量及其类型根据具体的调用会有所不同。对于open函数而言,仅当创建新文件时才使用第三个参数(稍后将对此进行说明)。在函数原型中将此参数放置在注释中。
pathname是要打开或创建文件的名字。oflag参数可用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成oflag参数(这些常量定义在<fcntl.h>头文件中):
O_RDONLY 只读打开。
O_WRONLY 只写打开。
O_RDWR 读、写打开。
大多数实现将O_RDONLY定义为0,O_WRONLY定义为1,O_RDWR定义为2,以与早期的程序兼容。
在这三个常量中必须指定一个且只能指定一个。下列常量则是可选择的:

较早的系统V版本引入了O_NDELAY(不延迟)标志,它与O_NONBLOCK(不阻塞)选项类似,但它的读操作返回值具有二义性。如果不能从管道、FIFO或设备读取数据,则不延迟选项使read返回0,这与表示已读到文件尾端的返回值0相冲突。基于SVR4的系统仍支持这种语义的不延迟选项,但是新的应用程序应当使用不阻塞选项代替之。
下面三个标志也是可选的。它们是Single UNIX Specification(以及POSIX.1)中同步输入和输出选项的一部分。
O_DSYNC 使每次write等待物理I/O操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性被更新。
O_RSYNC 使每一个以文件描述符作为参数的read操作等待,直至任何对文件同一部
分进行的未决写操作都完成。
O_SYNC 使每次write都等到物理I/O操作完成,包括由write操作引起的文件属性
更新所需的I/O。3.14节将使用此选项。
O_DSYNC和O_SYNC标志有微妙的区别。仅当文件属性需要更新以反映文件数据变化(例如,更新文件大小以反映文件中包含了更多的数据)时,O_DSYNC标志才影响文件属性。而设置O_SYNC标志后,数据和属性总是同步更新。当文件用O_DSYN标志打开,在重写其现有的部分内容时,文件时间属性不会同步更新。与此相反,如果文件是用O_SYNC标志打开,那么对该文件的每一次write操作都将在write返回前更新文件时间,这与是否改写现有字节或增写文件无关。
Solaris 9支持所有这三个标志。FreeBSD 5.2.1和Mac OS X 10.3设置了另外一个标志(O_FSYNC),它与标志O_SYNC的作用相同。因为这两个标志是等效的,所以FreeBSD 5.2.1定义它们为同一值(但奇怪的是,Mac OS X 10.3没有定义O_SYNC)。FreeBSD 5.2.1和Mac OS X 10.3不支持O_DSYNC或O_RSYNC 标志。Linux 2.4.22将它们处理成与O_SYNC相同。
由open返回的文件描述符一定是最小的未用描述符数值。这一点被某些应用程序用来在标准输入、标准输出或标准出错输出上打开新的文件。例如,一个应用程序可以先关闭标准输出(通常是文件描述符1),然后打开另一个文件,执行打开操作前就能了解到该文件一定会在文件描述符1上打开。在3.12节说明dup2函数时,可以了解到有更好的方法来保证在一个给定的描述符上打开一个文件。
文件名和路径名截短
如果NAME_MAX是14,而我们却试图在当前目录中创建一个其文件名包含15个字符的新文件,此时会发生什么呢?按照传统,早期的系统V版本(例如SVR2)允许这种使用方法,但总是将文件名截短为14个字符,而且不给出任何信息,而BSD类的系统则返回出错状态,并将errno设置为ENAMETOOLONG。无声无息地截短文件名会引起问题,而且它不仅仅影响到创建新文件。如果NAME_MAX是14,并且存在一个其文件名恰好就是14个字符的文件,那么以pathname作为其参数的任一函数(open、stat等)都无法确定该文件的原始名是什么?其原因是这些函数无法判断该文件名是否被截短过。
在POSIX.1中,常量_POSIX_NO_TRUNC决定了是要截短过长的文件名或路径名,还是返回一个出错。正如我们在第2章中已见过的,根据文件系统的类型,此值可以变化。
是否返回一个出错值在很大程度上是历史形成的。例如,基于SVR4的系统对传统的系统V文件系统(S5)并不产生出错返回,但是它对BSD风格的文件系统(UFS)则产生出错返回。
作为另一个例子,参见表2-15。Solaris对UFS返回出错,对与DOS兼容的文件系统PCFS则不返回出错,其原因是DOS会无声无息地截短不适配8.3格式的文件名。BSD类系统和Linux总是会返回出错。
若_POSIX_NO_TRUNC有效,则在整个路径名超过PATH_MAX,或路径名中的任一文件名超过NAME_MAX时,返回出错状态,并将errno设置为ENAMETOOLONG。







