Starting with kernel 2.6.16, Linux provides a range of new system calls that perform similar tasks to various traditional system calls, but provide additional functionality that is useful to some applications. These system calls are summarized in Table 18-2. We describe these system calls in this chapter because they provide variations on the traditional semantics of the process’s current working directory.
Table 18-2. System calls that use a directory file descriptor to interpret relative pathnames
New interface | Traditional analog | Notes |
---|---|---|
access() | Supports | |
chmod() | ||
chown() | Supports | |
stat() | Supports | |
link() | Supports (since Linux 2.6.18) | |
mkdir() | ||
mkfifo() | Library function layered on top of | |
mknod() | ||
open() | ||
readlink() | ||
rename() | ||
symlink() | ||
unlink() | Supports | |
utimes() | Supports |
In order to describe these system calls, we’ll use a specific example: openat().
#define _XOPEN_SOURCE 700 /* Or define _POSIX_C_SOURCE >= 200809 */
#include <fcntl.h>
int openat
(int dirfd, const char *pathname, int
flags, ... /* mode_t mode */);
Returns file descriptor on success, or -1 on error
The openat() system call is similar to the traditional open() system call, but adds an argument, dirfd, that is used as follows:
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.
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)).
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()):
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 descriptor to openat(), such races can be avoided.
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 different 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
feature 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 declarations of these system calls.)
Solaris 9 and later provide versions of some of the interfaces listed in Table 18-2, with slightly different semantics.