问题
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 withEISDIR
, but implementations should be allowed to support creating and opening a directory viaopen("/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 withO_CREAT|O_RDONLY
(orO_CREAT|O_SEARCH
) on an existing directory. Additionally, some systems want to allow creation of directories using theopen()
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