是否有任何有效的情况可以使用 O_APPEND 和 O_RDONLY?

Is there any valid situation where you would use O_APPEND and O_RDONLY?

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

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

这通常是在使用 open 和不包括 O_WRONLYO_RDWR.

的标志组合打开文件描述符时出现的

(查看 man 2 open,man 2 write 获取更多信息)

所以,问题:

在什么情况下O_APPENDO_TRUNCO_CREAT调用open是有效的也没有传递写入标志之一?

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

如果标志组合无效(例如 O_APPEND 没有任何写入标志),我希望 open 会失败并出现一些错误,但事实并非如此。这有什么原因吗,或者它只是历史 posix 标准的产物?

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

这取决于你"valid"的意思。

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

Applications shall specify exactly one of the first five values (file access modes) below in the value of oflag:

  • O_EXEC
  • O_RDONLY
  • O_RDWR
  • O_SEARCH
  • O_WRONLY

然后

Not all combinations of flags make sense. For example, using O_SEARCH | O_CREAT will successfully open a pre-existing directory for searching, but if there is no existing file by that name, then it is unspecified whether a regular file will be created.

我会得出结论,根据 POSIX,一个孤独的 O_APPEND 会属于 "unspecified" 行为(即,不要那样做)。

查看此处了解更多信息:http://pubs.opengroup.org/onlinepubs/9699919799/

我想不出在任何情况下传递 O_APPENDO_RDONLY 会产生与传递 O_RDONLY 不同的效果。 SUSv4 seems to imply 至少应该允许。

对于 O_TRUNC,SUSv4 未指定传递 O_RDONLY:

时的行为

The result of using O_TRUNC without either O_RDWR or O_WRONLY is undefined.

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

Bits corresponding to the file access mode and the file creation flags, as defined in <fcntl.h>, that are set in arg shall be ignored. If any bits in arg other than those mentioned here are changed by the application, the result is unspecified

在Linux、fcntl(2)上可以改变O_APPENDO_ASYNCO_DIRECTO_NOATIMEO_NONBLOCK标志,但其中 none 会有所不同。这个讨论。

有点做作,但我想传递 O_RDONLY | O_APPEND 可能会影响你在传递 fcntl(fd, F_GETFL, ...) 时返回的标志。不过我还没有真正证实这一点。

至于为什么要这样设计,我也不知道。