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

What's the expected behavior of open(name, O_CREAT|O_DIRECTORY, mode)?

尽管仔细阅读了 the related standard documentation,但我无法理解当使用包括 O_CREAT|O_DIRECTORY.

标准规定

If O_CREAT and O_DIRECTORY are set and the requested access mode is neither O_WRONLY nor O_RDWR, the result is unspecified.

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

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

if O_DIRECTORY is not set the file shall be created as a regular file; [...]

但它同样没有指定如果也设置了 O_DIRECTORY 会发生什么。

我查看了 NetBSD (which notoriously cares a lot about POSIX compliance) and Linux 的手册页(这是一个广泛使用的系统,尽管实际上不是 POSIX 系统)但我找不到任何说明。

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

在任何符合 POSIX 的 OS 上,open(name, O_CREAT|O_DIRECTORY, mode) 是否等同于 mkdir

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

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

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

在 linux 中有点多毛,但是任何简单的测试都会告诉你目录也没有创建,但你可以得到一个文件

为了好玩,我还检查了 freebsd,它从一开始就不会用 O_DIRECTORY 创建任何东西

如果您正在寻找的是一个 mkdir,它可以返回 fd,恐怕没有这样的东西。另一方面,您应该能够使用 O_DIRECTORY 任何您 mkdir 编辑的内容安全地打开。

我认为您误解了 O_DIRECTORY 的含义。不是创建一个目录,而是保证open(2)打开的"file"是一个目录。

O_DIRECTORY
If path resolves to a non-directory file, fail and set errno to [ENOTDIR].

这正是 POSIX 记录它的方式(上面引用)。

However it does not specify the behavior of the system with neither (O_CREAT|O_DIRECTORY|O_WRONLY) nor (O_CREAT|O_DIRECTORY|O_RDWR)

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

Is it correct to say that the use of both flags is unspecified? And if so, what's the most common behavior?

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

Is open(name, O_CREAT|O_DIRECTORY, mode) equivalent to mkdir on any POSIX compliant OS?

完全没有。这就是为什么它被保留为 未指定 的原因。在 Linux、it's definitely not - 创建了一个常规文件:

When both O_CREAT and O_DIRECTORY are specified in flags and the file specified by pathname does not exist, open() will create a regular file (i.e., O_DIRECTORY is ignored).

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

到目前为止的答案都不正确。实现可以通过 O_CREAT|O_DIRECTORY|O_WRONLYO_CREAT|O_DIRECTORY|O_RDWR 免费支持目录创建,但它们不是必需的。 正如您在 bug tracker of the Austin group:

中看到的那样,这在 2014 年得到了澄清

open("/path/to/existing/directory", O_CREAT) should fail with EISDIR, but implementations should be allowed to support creating and opening a directory via open("/path/to/directory", O_CREAT|O_DIRECTORY) as an extension

基于以下理由:

The standard does not specify the behavior when open() is called with O_CREAT|O_RDONLY (or O_CREAT|O_SEARCH) on an existing directory. Additionally, some systems want to allow creation of directories using the open() function. This should be an allowed, but not required, extension.

您从标准current version中引用的措辞

If O_CREAT and O_DIRECTORY are set and the requested access mode is neither O_WRONLY nor O_RDWR, the result is unspecified.

恰恰是允许它进行的更改之一。

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

但是,我不知道是否有任何 POSIX 实现确实通过 open.

提供目录创建