linkat()

Updated: April 19, 2023

Create a link to an existing file located at a given path

Synopsis:

#include <fcntl.h>

int linkat( int olddirfd, 
            const char *const oldpath,
            int newdirfd, 
            const char *const newpath,
            int flags );

Arguments:

olddirfd
A file descriptor that indicates the base directory for relative file paths. The pathname given in oldpath is resolved by appending it to the directory associated with olddirfd. You can set this argument to AT_FDCWD to use the current working directory as the base directory.
Note: You must use a file descriptor obtained from an open() call with the O_DIRECTORY flag set. Otherwise, the function fails and sets errno to ENOTDIR.

If oldpath specifies an absolute path, olddirfd has no effect.

oldpath
The path of an existing file that you're creating a hard link to. This can be absolute or relative; for details of how relative pathname resolution is done, see above.
newdirfd
A file descriptor that indicates the base directory for relative file paths. The pathname given in newpath is resolved by appending it to the directory associated with newdirfd. You can set this argument to AT_FDCWD to use the current working directory as the base directory.
Note: You must use a file descriptor obtained from an open() call with the O_DIRECTORY flag set. Otherwise, the function fails and sets errno to ENOTDIR.

If newpath specifies an absolute path, newdirfd has no effect.

newpath
The path of the new link. This can be absolute or relative; for details of how relative pathname resolution is done, see above.
flags
A bitfield of the following flags:
  • AT_SYMLINK_FOLLOW — if oldpath names a symbolic link, create a new link for the target of the symbolic link.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The linkat() function creates a new directory entry named by newpath to refer to (that is, to be a hard link to) an existing file named by oldpath. Each of the oldpath and newpath arguments can contain an absolute or a relative path. In the latter case, the corresponding file descriptor argument (olddirfd for oldpath and newdirfd for newpath) is used to resolve the pathname, as explained in the descriptions of these arguments (above).

If the access mode of the open file description associated with the olddirfd or newdirfd file descriptor is not O_SEARCH, the function checks if directory searches are permitted using the current permissions of the directory underlying the file descriptor. If the access mode is O_SEARCH, the function doesn't perform the check.

When the flags field is 0, this function is equivalent to link() when both oldpath and newpath are absolute and not relative paths. For details about other possible flags settings, see this argument's description (above).

QNX Neutrino has no concept of a path operation (open(), readlink(), etc.) that references a path relative to an already open file descriptor (for a directory), as far as the filesystem resource manager is concerned. Therefore, it's not possible to eliminate the race inherent in looking up a pathname with multiple intervening directories or symbolic links. However, linkat() can still be used for maintaining a per-thread current working directory, using file descriptors maintained by the application.

Note: This implementation doesn't support using linkat() on directories or the linking of files across filesystems (different logical disks).

If it succeeds, the linkat() function atomically creates a new link for the existing file and increments the link count of the file by one. For information about which fields of the file and the directory are updated, see the link() reference. If the function fails, no link is created, and the link count of the file remains unchanged.

Returns:

0
Success.
-1
An error occurred (errno is set).

Errors:

EACCES
One of the following is true:
  • A component of the path prefix in oldpath or newpath denies search permission.
  • The access mode of the olddirfd or newdirfd file descriptor is not O_SEARCH and the underlying directory doesn't permit directory searches.
  • The link named by newpath is in a directory with a mode that denies write permission.
  • The calling process does not have permission to access the existing file and this is required by the implementation.
EBADF
One of the paths (oldpath or newpath) does not specify an absolute path and the corresponding file descriptor (olddirfd or newdirfd) is neither AT_FDCWD nor a valid file descriptor open for reading or searching.
EEXIST
The link named by newpath already exists.
EINVAL
An invalid value was specified for flags.
ELOOP
During resolution of the oldpath or newpath argument, too many levels of symbolic links were encountered.
EMLINK
The number of links to the file named by oldpath would exceed LINK_MAX.
ENAMETOOLONG
The length of the oldpath or newpath string exceeds PATH_MAX, the resolution of a symbolic link within one of these strings produced a result longer than PATH_MAX, or a pathname component is longer than NAME_MAX.
ENOENT
One of the following conditions is true:
  • A component of the path prefix in oldpath or newpath doesn't exist.
  • The file named by oldpath doesn't exist.
  • Either oldpath or newpath points to an empty string.
ENOSPC
The directory that would contain the link can't be extended.
ENOSYS
The linkat() function isn't implemented for the filesystem underlying the path specified in oldpath or newpath.
ENOTDIR
One of the following is true:
  • A component of the path prefix in oldpath or newpath names an existing file that is neither a directory nor a symbolic link to one.
  • The pathname in oldpath contains at least one non-slash character, ends with at least one slash character (/), and the last component names an existing file that is neither a directory nor a symbolic link to one.
  • The path in oldpath names an existing non-directory and the path in newpath names a non-existent file, contains at least one non-slash character, and ends with at least one slash character (/).
  • The oldpath or newpath argument isn't an absolute path and the associated olddirfd or newdirfd file descriptor is associated with a non-directory file.
  • One of the file descriptors (olddirfd or newdirfd) was created without O_DIRECTORY set.
EPERM
The file named by oldpath is a directory and the calling process doesn't have the appropriate permissions.
EROFS
The requested link requires writing in a directory on a read-only filesystem.
EXDEV
The link named by newpath and the file named by oldpath are on different filesystems and the implementation doesn't support links between filesystems. Or, oldpath refers to a named stream.

Classification:

POSIX 2008

Safety:  
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes