diff options
Diffstat (limited to '')
-rw-r--r-- | man2/readlink.2 | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/man2/readlink.2 b/man2/readlink.2 new file mode 100644 index 0000000..fe2369d --- /dev/null +++ b/man2/readlink.2 @@ -0,0 +1,331 @@ +.\" Copyright (c) 1983, 1991 The Regents of the University of California. +.\" And Copyright (C) 2011 Guillem Jover <guillem@hadrons.org> +.\" And Copyright (C) 2006, 2014 Michael Kerrisk +.\" All rights reserved. +.\" +.\" SPDX-License-Identifier: BSD-4-Clause-UC +.\" +.\" @(#)readlink.2 6.8 (Berkeley) 3/10/91 +.\" +.\" Modified Sat Jul 24 00:10:21 1993 by Rik Faith (faith@cs.unc.edu) +.\" Modified Tue Jul 9 23:55:17 1996 by aeb +.\" Modified Fri Jan 24 00:26:00 1997 by aeb +.\" 2011-09-20, Guillem Jover <guillem@hadrons.org>: +.\" Added text on dynamically allocating buffer + example program +.\" +.TH readlink 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +readlink, readlinkat \- read value of a symbolic link +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <unistd.h> +.PP +.BI "ssize_t readlink(const char *restrict " pathname ", char *restrict " buf , +.BI " size_t " bufsiz ); +.PP +.BR "#include <fcntl.h> " "/* Definition of " AT_* " constants */" +.B #include <unistd.h> +.PP +.BI "ssize_t readlinkat(int " dirfd ", const char *restrict " pathname , +.BI " char *restrict " buf ", size_t " bufsiz ); +.PP +.fi +.RS -4 +Feature Test Macro Requirements for glibc (see +.BR feature_test_macros (7)): +.RE +.PP +.BR readlink (): +.nf + _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L +.\" || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED + || /* glibc <= 2.19: */ _BSD_SOURCE +.fi +.PP +.BR readlinkat (): +.nf + Since glibc 2.10: + _POSIX_C_SOURCE >= 200809L + Before glibc 2.10: + _ATFILE_SOURCE +.fi +.SH DESCRIPTION +.BR readlink () +places the contents of the symbolic link +.I pathname +in the buffer +.IR buf , +which has size +.IR bufsiz . +.BR readlink () +does not append a terminating null byte to +.IR buf . +It will (silently) truncate the contents (to a length of +.I bufsiz +characters), in case the buffer is too small to hold all of the contents. +.SS readlinkat() +The +.BR readlinkat () +system call operates in exactly the same way as +.BR readlink (), +except for the differences described here. +.PP +If the pathname given in +.I pathname +is relative, then it is interpreted relative to the directory +referred to by the file descriptor +.I dirfd +(rather than relative to the current working directory of +the calling process, as is done by +.BR readlink () +for a relative pathname). +.PP +If +.I pathname +is relative and +.I dirfd +is the special value +.BR AT_FDCWD , +then +.I pathname +is interpreted relative to the current working +directory of the calling process (like +.BR readlink ()). +.PP +If +.I pathname +is absolute, then +.I dirfd +is ignored. +.PP +Since Linux 2.6.39, +.\" commit 65cfc6722361570bfe255698d9cd4dccaf47570d +.I pathname +can be an empty string, +in which case the call operates on the symbolic link referred to by +.I dirfd +(which should have been obtained using +.BR open (2) +with the +.B O_PATH +and +.B O_NOFOLLOW +flags). +.PP +See +.BR openat (2) +for an explanation of the need for +.BR readlinkat (). +.SH RETURN VALUE +On success, these calls return the number of bytes placed in +.IR buf . +(If the returned value equals +.IR bufsiz , +then truncation may have occurred.) +On error, \-1 is returned and +.I errno +is set to indicate the error. +.SH ERRORS +.TP +.B EACCES +Search permission is denied for a component of the path prefix. +(See also +.BR path_resolution (7).) +.TP +.B EBADF +.RB ( readlinkat ()) +.I pathname +is relative but +.I dirfd +is neither +.B AT_FDCWD +nor a valid file descriptor. +.TP +.B EFAULT +.I buf +extends outside the process's allocated address space. +.TP +.B EINVAL +.I bufsiz +is not positive. +.\" At the glibc level, bufsiz is unsigned, so this error can only occur +.\" if bufsiz==0. However, the in the kernel syscall, bufsiz is signed, +.\" and this error can also occur if bufsiz < 0. +.\" See: http://thread.gmane.org/gmane.linux.man/380 +.\" Subject: [patch 0/3] [RFC] kernel/glibc mismatch of "readlink" syscall? +.TP +.B EINVAL +The named file (i.e., the final filename component of +.IR pathname ) +is not a symbolic link. +.TP +.B EIO +An I/O error occurred while reading from the filesystem. +.TP +.B ELOOP +Too many symbolic links were encountered in translating the pathname. +.TP +.B ENAMETOOLONG +A pathname, or a component of a pathname, was too long. +.TP +.B ENOENT +The named file does not exist. +.TP +.B ENOMEM +Insufficient kernel memory was available. +.TP +.B ENOTDIR +A component of the path prefix is not a directory. +.TP +.B ENOTDIR +.RB ( readlinkat ()) +.I pathname +is relative and +.I dirfd +is a file descriptor referring to a file other than a directory. +.SH STANDARDS +POSIX.1-2008. +.SH HISTORY +.TP +.BR readlink () +4.4BSD +(first appeared in 4.2BSD), +POSIX.1-2001, POSIX.1-2008. +.TP +.BR readlinkat () +POSIX.1-2008. +Linux 2.6.16, +glibc 2.4. +.PP +Up to and including glibc 2.4, the return type of +.BR readlink () +was declared as +.IR int . +Nowadays, the return type is declared as +.IR ssize_t , +as (newly) required in POSIX.1-2001. +.SS glibc +On older kernels where +.BR readlinkat () +is unavailable, the glibc wrapper function falls back to the use of +.BR readlink (). +When +.I pathname +is a relative pathname, +glibc constructs a pathname based on the symbolic link in +.I /proc/self/fd +that corresponds to the +.I dirfd +argument. +.SH NOTES +Using a statically sized buffer might not provide enough room for the +symbolic link contents. +The required size for the buffer can be obtained from the +.I stat.st_size +value returned by a call to +.BR lstat (2) +on the link. +However, the number of bytes written by +.BR readlink () +and +.BR readlinkat () +should be checked to make sure that the size of the +symbolic link did not increase between the calls. +Dynamically allocating the buffer for +.BR readlink () +and +.BR readlinkat () +also addresses a common portability problem when using +.B PATH_MAX +for the buffer size, +as this constant is not guaranteed to be defined per POSIX +if the system does not have such limit. +.SH EXAMPLES +The following program allocates the buffer needed by +.BR readlink () +dynamically from the information provided by +.BR lstat (2), +falling back to a buffer of size +.B PATH_MAX +in cases where +.BR lstat (2) +reports a size of zero. +.PP +.\" SRC BEGIN (readlink.c) +.EX +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +\& +int +main(int argc, char *argv[]) +{ + char *buf; + ssize_t nbytes, bufsiz; + struct stat sb; +\& + if (argc != 2) { + fprintf(stderr, "Usage: %s <pathname>\en", argv[0]); + exit(EXIT_FAILURE); + } +\& + if (lstat(argv[1], &sb) == \-1) { + perror("lstat"); + exit(EXIT_FAILURE); + } +\& + /* Add one to the link size, so that we can determine whether + the buffer returned by readlink() was truncated. */ +\& + bufsiz = sb.st_size + 1; +\& + /* Some magic symlinks under (for example) /proc and /sys + report \[aq]st_size\[aq] as zero. In that case, take PATH_MAX as + a "good enough" estimate. */ +\& + if (sb.st_size == 0) + bufsiz = PATH_MAX; +\& + buf = malloc(bufsiz); + if (buf == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } +\& + nbytes = readlink(argv[1], buf, bufsiz); + if (nbytes == \-1) { + perror("readlink"); + exit(EXIT_FAILURE); + } +\& + /* Print only \[aq]nbytes\[aq] of \[aq]buf\[aq], as it doesn't contain a terminating + null byte (\[aq]\e0\[aq]). */ + printf("\[aq]%s\[aq] points to \[aq]%.*s\[aq]\en", argv[1], (int) nbytes, buf); +\& + /* If the return value was equal to the buffer size, then the + the link target was larger than expected (perhaps because the + target was changed between the call to lstat() and the call to + readlink()). Warn the user that the returned target may have + been truncated. */ +\& + if (nbytes == bufsiz) + printf("(Returned buffer may have been truncated)\en"); +\& + free(buf); + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR readlink (1), +.BR lstat (2), +.BR stat (2), +.BR symlink (2), +.BR realpath (3), +.BR path_resolution (7), +.BR symlink (7) |