Descriptor-Relative Access (The GNU C Library)

### 14.2 Descriptor-Relative Access ¶

Many functions that accept file names have `…at` variants which accept a file descriptor and a file name argument instead of just a file name argument. For example, `fstatat` is the descriptor-based variant of the `fstat` function. Most such functions also accept an additional flags argument which changes the behavior of the file name lookup based on the passed `AT_…` flags.

There are several reasons to use descriptor-relative access:

- The working directory is a process-wide resource, so individual threads cannot change it without affecting other threads in the process. Explicitly specifying the directory against which relative paths are resolved can be a thread-safe alternative to changing the working directory.
- If a program wishes to access a directory tree which is being modified concurrently, perhaps even by a different user on the system, the program must avoid looking up file names with multiple components, in order to detect symbolic links, using the `O_NOFOLLOW` flag (see Open-time Flags) or the `AT_SYMLINK_FOLLOW` flag (described below). Without directory-relative access, it is necessary to use the `fchdir` function to change the working directory (see Working Directory), which is not thread-safe.
- Listing directory contents using the `readdir` or `readdir64` functions (see Reading and Closing a Directory Stream) does not provide full file name paths. Using `…at` functions, it is possible to use the file names directly, without having to construct such full paths.
- Additional flags available with some of the `…at` functions provide access to functionality which is not available otherwise.

The file descriptor used by these `…at` functions has the following uses:

- It can be a file descriptor referring to a directory. Such a descriptor can be created explicitly using the `open` function and the `O_RDONLY` file access mode, with or without the `O_DIRECTORY` flag. See Opening and Closing Files. Or it can be created implicitly by `opendir` and retrieved using the `dirfd` function. See Opening a Directory Stream.

  If a directory descriptor is used with one of the `…at` functions, a relative file name argument is resolved relative to directory referred to by the file descriptor, just as if that directory were the current working directory. Absolute file name arguments (starting with ‘`/`’) are resolved against the file system root, and the descriptor argument is effectively ignored.

  This means that file name lookup is not constrained to the directory of the descriptor. For example, it is possible to access a file `example` in the descriptor’s parent directory using a file name argument `"../example"`, or in the root directory using `"/example"`.

  If the file descriptor refers to a directory, the empty string `""` is not a valid file name argument. It is possible to use `"."` to refer to the directory itself. Also see `AT_EMPTY_PATH` below.

- The special value `AT_FDCWD`. This means that the current working directory is used for the lookup if the file name is a relative. For `…at` functions with an `AT_…` flags argument, this provides a shortcut to use those flags with regular (not descriptor-based) file name lookups.

  If `AT_FDCWD` is used, the empty string `""` is not a valid file name argument.

- An arbitrary file descriptor, along with an empty string `""` as the file name argument, and the `AT_EMPTY_PATH` flag. In this case, the operation uses the file descriptor directly, without further file name resolution. On Linux, this allows operations on descriptors opened with the `O_PATH` flag. For regular descriptors (opened without `O_PATH`), the same functionality is also available through the plain descriptor-based functions (for example, `fstat` instead of `fstatat`).

  This is a GNU extension.

The flags argument in `…at` functions can be a combination of the following flags, defined in `fcntl.h`. Not all such functions support all flags, and some (such as `openat`) do not accept a flags argument at all. Although the flags specific to each function have distinct values from each other, some flags (relevant to different functions) might share the same value and therefore are not guaranteed to have unique values.

A non-exhaustive list of common flags and their descriptions follows. Flags specific to a function are described alongside the function itself. In these flag descriptions, the effective final path component refers to the final component (basename) of the full path constructed from the descriptor and file name arguments, using file name lookup, as described above.

`AT_EMPTY_PATH` ¶

  This flag is used with an empty file name `""` and a descriptor which does not necessarily refer to a directory. It is most useful with `O_PATH` descriptors, as described above. This flag is a GNU extension.

`AT_NO_AUTOMOUNT` ¶

  If the effective final path component refers to a potential file system mount point controlled by an auto-mounting service, the operation does not trigger auto-mounting and refers to the unmounted mount point instead. See Mount, Unmount, Remount. If a file system has already been mounted at the effective final path component, the operation applies to the file or directory in the mounted file system, not the underlying file system that was mounted over. This flag is a GNU extension.

`AT_SYMLINK_FOLLOW` ¶

  If the effective final path component is a symbolic link, the operation follows the symbolic link and operates on its target. (For most functions, this is the default behavior.)

`AT_SYMLINK_NOFOLLOW` ¶

  If the effective final path component is a symbolic link, the operation operates on the symbolic link, without following it. The difference in behavior enabled by this flag is similar to the difference between the `lstat` and `stat` functions, or the behavior activated by the `O_NOFOLLOW` argument to the `open` function. Even with the `AT_SYMLINK_NOFOLLOW` flag present, symbolic links in a non-final component of the file name are still followed.

Note: There is no relationship between these flags and the type argument to the `getauxval` function (with `AT_…` constants defined in `elf.h`). See Auxiliary Vector.

The `…at` functions have some common error conditions due to the nature of descriptor-relative access. A list of common errors and their descriptions follows. Errors specific to a function are described alongside the function itself.

`EBADF`

  The file name argument is a relative path but the descriptor argument is neither `AT_FDCWD` nor a valid file descriptor.

`EINVAL`

  If the function accepts a flags argument, the flag combination passed is not valid for the function.

`ENOTDIR`

  The file name argument is a relative file name but the descriptor argument is associated with a file that is not a directory.