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

时间:2017-08-22 13:11:27

标签: c linux filesystems posix bsd

尽管仔细阅读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)的手册页,但我找不到任何澄清。

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

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

3 个答案:

答案 0 :(得分:4)

我认为你误解了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 分别提供 pathname (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)

答案 1 :(得分:2)

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

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

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

在Linux中它有点毛茸茸,但是任何微不足道的测试都会告诉你目录也没有创建,但是你最终可以得到一个文件

对于踢,我也检查了freebsd,它从来没有最终用O_DIRECTORY创建任何东西

如果您正在寻找的是mkdir,它会让您回到fd,我担心没有任何类似的东西。另一方面,你应该能够安全地使用O_DIRECTORY打开任何你想要的东西。

答案 2 :(得分: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)应该以{{1​​}}失败,但应允许实施支持通过EISDIR作为扩展名创建和打开目录

具有以下基本原理:

  

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

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

  

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

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

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

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