открыть и, возможно, создать файл (расширенный) (open and possibly create a file (extended))
Примечание (Note)
Extensibility
In order to allow for future extensibility, openat2
() requires
the user-space application to specify the size of the open_how
structure that it is passing. By providing this information, it
is possible for openat2
() to provide both forwards- and
backwards-compatibility, with size acting as an implicit version
number. (Because new extension fields will always be appended,
the structure size will always increase.) This extensibility
design is very similar to other system calls such as
sched_setattr(2), perf_event_open(2), and clone3(2).
If we let usize be the size of the structure as specified by the
user-space application, and ksize be the size of the structure
which the kernel supports, then there are three cases to
consider:
• If ksize equals usize, then there is no version mismatch and
how can be used verbatim.
• If ksize is larger than usize, then there are some extension
fields that the kernel supports which the user-space
application is unaware of. Because a zero value in any added
extension field signifies a no-op, the kernel treats all of the
extension fields not provided by the user-space application as
having zero values. This provides backwards-compatibility.
• If ksize is smaller than usize, then there are some extension
fields which the user-space application is aware of but which
the kernel does not support. Because any extension field must
have its zero values signify a no-op, the kernel can safely
ignore the unsupported extension fields if they are all-zero.
If any unsupported extension fields are nonzero, then -1 is
returned and errno is set to E2BIG
. This provides forwards-
compatibility.
Because the definition of struct open_how may change in the
future (with new fields being added when system headers are
updated), user-space applications should zero-fill struct
open_how to ensure that recompiling the program with new headers
will not result in spurious errors at runtime. The simplest way
is to use a designated initializer:
struct open_how how = { .flags = O_RDWR,
.resolve = RESOLVE_IN_ROOT };
or explicitly using memset(3) or similar:
struct open_how how;
memset(&how, 0, sizeof(how));
how.flags = O_RDWR;
how.resolve = RESOLVE_IN_ROOT;
A user-space application that wishes to determine which
extensions the running kernel supports can do so by conducting a
binary search on size with a structure which has every byte
nonzero (to find the largest value which doesn't produce an error
of E2BIG
).