是否存在使用O_APPEND和O_RDONLY的有效情况?

时间:2015-03-24 00:47:53

标签: c io system-calls

在类似unix的系统上,尝试在文件描述符上调用write函数有时会导致错误:

[EBADF]  fildes is not a valid file descriptor open for writing.

这通常是在使用open以及不包含O_WRONLYO_RDWR的标记组合打开文件描述符时。

(参见man 2 open,man 2 write for more info)

所以,问题是:

在什么情况下永远有效openO_APPENDO_TRUNC中的任何一个调用O_CREAT,而不通过其中一个写标志?

这是因为最近我遇到的问题是只传递O_APPEND标志会成功打开文件,但是在fd上调用write会导致EBADF,因为我没有将O_RDONLY以外的内容传递给open来电。

如果标志的组合无效(例如open没有任何写标志),我希望O_APPEND失败并出现一些错误,但事实并非如此。这有什么理由,还是仅仅是历史posix标准的神器?

是否存在O_APPEND + O_RDONLY是有效组合的情况?

2 个答案:

答案 0 :(得分:2)

这取决于“有效”的含义。

AFAICT,POSIX没有具体提到这种标志组合。但确实说:

  

应用程序应指定前五个值中的一个(文件   访问模式)下面的oflag值:

     
      
  • 了O_EXEC
  •   
  • O_RDONLY
  •   
  • O_RDWR
  •   
  • O_SEARCH
  •   
  • O_WRONLY
  •   

然后

  

并非所有标志组合都有意义。例如,使用O_SEARCH | O_CREAT将成功打开一个预先存在的搜索目录,但如果该名称没有现有文件,则不指定是否会创建常规文件。

根据POSIX,我会得出结论认为单独的O_APPEND属于“未指定”的行为(即,不要这样做)。

有关详细信息,请参阅此处:http://pubs.opengroup.org/onlinepubs/9699919799/

答案 1 :(得分:2)

我无法想到传递O_APPENDO_RDONLY会产生与传递O_RDONLY不同的任何情况。 SUSv4 seems to imply至少应该允许它。

对于O_TRUNC,SUSv4在传递O_RDONLY时没有指定行为:

  

O_TRUNCO_RDWR使用O_WRONLY的结果未定义。

fcntl()可以在描述符创建后更改状态标志,因此可能看起来像是一种方式,例如打开文件O_APPENDO_RDONLY可能很重要。然而,

  

对应于文件访问模式的位和在< fcntl.h> 中定义的文件创建标志,在arg中设置的位应被忽略。如果应用程序更改了此处提到的arg中的任何位,则结果未指定

在Linux上,fcntl(2)可以更改O_APPENDO_ASYNCO_DIRECTO_NOATIMEO_NONBLOCK标记,但不能更改会有所作为。这个讨论。

有点做作,但我想传递O_RDONLY | O_APPEND可能会影响你fcntl(fd, F_GETFL, ...)时得到的标志。虽然我还没有确认过。

至于为什么事情是这样设计的,我不知道。