Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   openat2    ( 2 )

открыть и, возможно, создать файл (расширенный) (open and possibly create a file (extended))

  Name  |  Synopsis  |  Description  |  Return value  |  Error  |  Versions  |  Conforming to  |    Note    |  See also  |

Примечание (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).