366 Chapter 18
The openat() system call is similar to the traditional open() system call, but adds an
argument, dirfd, that is used as follows:
z If pathname specifies a relative pathname, then it is interpreted relative to the
directory referred to by the open file descriptor dirfd, rather than relative to
the process’s current working directory.
z If pathname specifies a relative pathname, and dirfd contains the special value
AT_FDCWD, then pathname is interpreted relative to the process’s current working
directory (i.e., the same behavior as open(2)).
z If pathname specifies an absolute pathname, then dirfd is ignored.
The flags argument of openat() serves the same purpose as for open(). However,
some of the system calls listed in Table 18-2 support a flags argument that is not
provided by the corresponding traditional system call, and the purpose of this
argument is to modify the semantics of the call. The most frequently provided flag
is AT_SYMLINK_NOFOLLOW, which specifies that if pathname is a symbolic link, then the
system call should operate on the link, rather than the file to which it refers. (The
linkat() system call provides the AT_SYMLINK_FOLLOW flag, which performs the converse
action, changing the default behavior of linkat() so that it dereferences oldpath if it
is a symbolic link.) For details of the other flags, refer to the corresponding manual
pages.
The system calls listed in Table 18-2 are supported for two reasons (again, we
explain using the example of openat()):
z Using openat() allows an application to avoid certain race conditions that can
occur when open() is used to open files in locations other than the current
working directory. These races can occur because some component of the
directory prefix of pathname could be changed in parallel with the open() call.
By opening a file descriptor for the target directory, and passing that descrip-
tor to openat(), such races can be avoided.
z In Chapter 29, we’ll see that the working directory is a process attribute that is
shared by all threads of the process. For some applications, it is useful for dif-
ferent threads to have different “virtual” working directories. An application
can emulate this functionality using openat() in conjunction with directory file
descriptors maintained by the application.
These system calls are not standardized in SUSv3, but are included in SUSv4. In
order to expose the declaration of each of these system calls, the _XOPEN_SOURCE fea-
ture test macro must be defined with a value greater than or equal to 700 before
including the appropriate header file (e.g., <fcntl.h> for open()). Alternatively, the
_POSIX_C_SOURCE macro can be defined with a value greater than or equal to 200809.
(Before glibc 2.10, the _ATFILE_SOURCE macro needed to be defined to expose the dec-
larations of these system calls.)
Solaris 9 and later provide versions of some of the interfaces listed in Table 18-2,
with slightly different semantics.