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

半世苍凉 提交于 2019-12-09 18:24:12

问题


Despite a careful read of the related standard documentation, I can't understand what's the expected behavior in POSIX compliant systems when a open system call is invoked with flags including O_CREAT|O_DIRECTORY.

The standard specifies that

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

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). Indeed (as far as I can understand) the behavior on EISDIR only apply to existing directories.

In the section related to O_CREATE, the standard specifies that, when the named file does not exist,

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

but again it does not specify what will happen if O_DIRECTORY is set too.

I've looked the manual pages of both NetBSD (which notoriously cares a lot about POSIX compliance) and Linux (which is a widely used system, despite not actually a POSIX one) but I can't find any clarification.

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

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


回答1:


netbsd itself contains the following in vn_open:

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

so any combination with these 2 is straight up rejected.

in linux it's a little bit more hairy, but any trivial test will show you that the directory is not created either, but you can end up with a file

for kicks i also checked freebsd, which never ends up creating anything with O_DIRECTORY in the first place

if what you are looking for is a mkdir which gives you back the fd, i'm afraid there is nothing of the sort. on the other hand you should be able to safely open with O_DIRECTORY anything you mkdir'ed.




回答2:


I think you have misunderstood what O_DIRECTORY is meant for. It's not to create a directory but to ensure the "file" opened by open(2) is a directory.

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

That's precisely how POSIX documents it (quoted above).

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)

The behaviour of O_CREAT|O_DIRECTORY|O_WRONLY and O_CREAT|O_DIRECTORY|O_RDWR is equivalent to O_CREAT|O_WRONLY and O_CREAT|O_RDWR respectively provided the pathname (first argument to open(2)) is a directory. The presence of O_DIRECTORY is to ensure the file being opened is a directory - it doesn't affect anything else.

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

It means the behaviour of the specific combination O_CREAT | O_DIRECTORY isn't specified; doesn't mean using the individual flags (with or without other flags) is unspecified.

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

Not at all. That's why it's left as unspecified. On Linux, it's definitely not - a regular file is created:

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).

To create a directory, you'd use mkdir(2).




回答3:


The answers so far are not correct. Implementations are free to support directory creation via O_CREAT|O_DIRECTORY|O_WRONLY or O_CREAT|O_DIRECTORY|O_RDWR, but they are not required to. This was clarified in 2014, as you can see in the bug tracker of the Austin group:

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

with the following rationale:

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.

The wording you cited from the current version of the standard

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

was precisely one of the changes made to allow it.

One of reasons for allowing this, as described by Rich Felkner, is, that it would provide an interface for atomically creating and opening a directory.

However, I don't know, if any POSIX implementation out there does actually provide directory creation via open.



来源:https://stackoverflow.com/questions/45818628/whats-the-expected-behavior-of-openname-o-creato-directory-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!