open(name,O_CREAT | O_DIRECTORY,mode)的预期行为是什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了open(name,O_CREAT | O_DIRECTORY,mode)的预期行为是什么?相关的知识,希望对你有一定的参考价值。

尽管仔细阅读了the related standard documentation,但是当使用包含open的标志调用O_CREAT|O_DIRECTORY系统调用时,我无法理解POSIX兼容系统中的预期行为。

该标准规定了

如果设置了O_CREAT和O_DIRECTORY且请求的访问模式既不是O_WRONLY也不是O_RDWR,则结果未指定。

但是它没有指定系统的行为,既没有(O_CREAT|O_DIRECTORY|O_WRONLY)也没有(O_CREAT|O_DIRECTORY|O_RDWR)。确实(据我所知)EISDIR上的行为仅适用于现有目录。

在与O_CREATE相关的部分中,标准指定当命名文件不存在时,

如果未设置O_DIRECTORY,则应将文件创建为常规文件; [...]

但同样没有说明如果设置O_DIRECTORY会发生什么。

我看过NetBSD(非常关心POSIX合规性)和Linux(这是一个广泛使用的系统,尽管实际上并不是POSIX)的手册页,但我找不到任何澄清。

说两个标志的使用是否未指定是否正确?如果是这样,最常见的行为是什么?

open(name, O_CREAT|O_DIRECTORY, mode)在任何符合POSIX标准的操作系统上都相当于mkdir吗?

答案

netbsd本身在vn_open中包含以下内容:

if ((fmode & (O_CREAT | O_DIRECTORY)) == (O_CREAT | O_DIRECTORY))
        return EINVAL;

所以与这两个人的任何组合都会被直接拒绝。

在Linux中它有点多毛,但任何琐碎的测试都会告诉你目录也没有创建,但你最终可能会得到一个文件

对于踢,我也检查了freebsd,它最终从未以O_DIRECTORY创建任何东西

如果你正在寻找的是一个让你回到fd的mkdir,我恐怕没有那种东西。另一方面,你应该能够安全地打开O_DIRECTORY你所做的任何事情。

另一答案

我认为你误解了O_DIRECTORY的意思。这不是创建目录,而是确保open(2)打开的“文件”是一个目录。

O_DIRECTORY 如果path解析为非目录文件,则失败并将errno设置为[ENOTDIR]。

这正是POSIX如何记录它(如上所述)。

但是它没有指定系统的行为(O_CREAT | O_DIRECTORY | O_WRONLY)和(O_CREAT | O_DIRECTORY | O_RDWR)

O_CREAT|O_DIRECTORY|O_WRONLYO_CREAT|O_DIRECTORY|O_RDWR的行为分别等同于O_CREAT|O_WRONLYO_CREAT|O_RDWR提供的路径名(open(2)的第一个参数)是一个目录。 O_DIRECTORY的存在是为了确保打开的文件是一个目录 - 它不会影响任何其他内容。

说两个标志的使用是否未指定是否正确?如果是这样,最常见的行为是什么?

这意味着没有指定特定组合O_CREAT | O_DIRECTORY的行为;并不意味着使用单个标志(有或没有其他标志)是未指定的。

在任何符合POSIX标准的操作系统上,是否打开(名称,O_CREAT | O_DIRECTORY,模式)等同于mkdir?

一点也不。这就是为什么它没有具体说明。在Linux上,it's definitely not - 创建一个常规文件:

当在flags中指定O_CREAT和O_DIRECTORY并且pathname指定的文件不存在时,open()将创建一个常规文件(即忽略O_DIRECTORY)。

要创建目录,您可以使用mkdir(2)

另一答案

到目前为止的答案都不正确。实现可以通过O_CREAT|O_DIRECTORY|O_WRONLYO_CREAT|O_DIRECTORY|O_RDWR自由支持目录创建,但它们不是必需的。这在2014年得到澄清,正如你在bug tracker of the Austin group中看到的那样:

open("/path/to/existing/directory", O_CREAT)应该与EISDIR失败,但应该允许实现支持通过open("/path/to/directory", O_CREAT|O_DIRECTORY)创建和打开目录作为扩展

具有以下基本原理:

当在现有目录上使用open()(或O_CREAT|O_RDONLY)调用O_CREAT|O_SEARCH时,该标准未指定行为。此外,某些系统希望允许使用open()函数创建目录。这应该是允许的,但不是必需的扩展。

你从标准的current version引用的措辞

如果设置了O_CREAT和O_DIRECTORY且请求的访问模式既不是O_WRONLY也不是O_RDWR,则结果未指定。

正是允许它做出的改变之一。

正如Rich Felkner所描述的那样,允许这样做的原因之一是,它将提供一个用于原子地创建和打开目录的接口。

但是,我不知道,如果任何POSIX实现确实提供了通过open创建目录。

以上是关于open(name,O_CREAT | O_DIRECTORY,mode)的预期行为是什么?的主要内容,如果未能解决你的问题,请参考以下文章

对 ios7 的 shm_open 调用现在导致在 O_CREAT (EPERM) 期间不允许操作

POSIX 中的消息队列

文件IO详解---open函数详解

Posix 共享内存导致总线错误

什么是文件创建时的“open()”默认权限? [复制]

python中用open保存文本到桌面