| .\" 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. |
| .\" |
| .\" %%%LICENSE_START(BSD_4_CLAUSE_UCB) |
| .\" Redistribution and use in source and binary forms, with or without |
| .\" modification, are permitted provided that the following conditions |
| .\" are met: |
| .\" 1. Redistributions of source code must retain the above copyright |
| .\" notice, this list of conditions and the following disclaimer. |
| .\" 2. Redistributions in binary form must reproduce the above copyright |
| .\" notice, this list of conditions and the following disclaimer in the |
| .\" documentation and/or other materials provided with the distribution. |
| .\" 3. All advertising materials mentioning features or use of this software |
| .\" must display the following acknowledgement: |
| .\" This product includes software developed by the University of |
| .\" California, Berkeley and its contributors. |
| .\" 4. Neither the name of the University nor the names of its contributors |
| .\" may be used to endorse or promote products derived from this software |
| .\" without specific prior written permission. |
| .\" |
| .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| .\" SUCH DAMAGE. |
| .\" %%%LICENSE_END |
| .\" |
| .\" @(#)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 2014-10-15 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| readlink, readlinkat \- read value of a symbolic link |
| .SH SYNOPSIS |
| .nf |
| .B #include <unistd.h> |
| .sp |
| .BI "ssize_t readlink(const char *" pathname ", char *" buf \ |
| ", size_t " bufsiz ); |
| .sp |
| .BR "#include <fcntl.h> " "/* Definition of AT_* constants */" |
| .B #include <unistd.h> |
| .sp |
| .BI "ssize_t readlinkat(int " dirfd ", const char *" pathname , |
| .BI " char *" buf ", size_t " bufsiz ); |
| .sp |
| .fi |
| .in -4n |
| Feature Test Macro Requirements for glibc (see |
| .BR feature_test_macros (7)): |
| .in |
| .sp |
| .ad l |
| .BR readlink (): |
| .RS 4 |
| _BSD_SOURCE || _XOPEN_SOURCE\ >=\ 500 || |
| _XOPEN_SOURCE\ &&\ _XOPEN_SOURCE_EXTENDED || _POSIX_C_SOURCE\ >=\ 200112L |
| .RE |
| .sp |
| .BR readlinkat (): |
| .PD 0 |
| .ad l |
| .RS 4 |
| .TP 4 |
| Since glibc 2.10: |
| _XOPEN_SOURCE\ >=\ 700 || _POSIX_C_SOURCE\ >=\ 200809L |
| .TP |
| Before glibc 2.10: |
| _ATFILE_SOURCE |
| .RE |
| .ad b |
| .PD |
| .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 null byte to |
| .IR buf . |
| It will 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. |
| |
| 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). |
| |
| 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 ()). |
| |
| If |
| .I pathname |
| is absolute, then |
| .I dirfd |
| is ignored. |
| |
| 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 |
| .IR 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 . |
| 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 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 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. |
| .PP |
| The following additional errors can occur for |
| .BR readlinkat (): |
| .TP |
| .B EBADF |
| .I dirfd |
| is not a valid file descriptor. |
| .TP |
| .B ENOTDIR |
| .I pathname |
| is relative and |
| .I dirfd |
| is a file descriptor referring to a file other than a directory. |
| .SH VERSIONS |
| .BR readlinkat () |
| was added to Linux in kernel 2.6.16; |
| library support was added to glibc in version 2.4. |
| .SH CONFORMING TO |
| .BR readlink (): |
| 4.4BSD |
| .RB ( readlink () |
| first appeared in 4.2BSD), |
| POSIX.1-2001, POSIX.1-2008. |
| |
| .BR readlinkat (): |
| POSIX.1-2008. |
| .SH NOTES |
| In versions of glibc 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. |
| |
| 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 |
| .I 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. |
| .SS Glibc notes |
| 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 |
| .IR /proc/self/fd |
| that corresponds to the |
| .IR dirfd |
| argument. |
| .SH EXAMPLE |
| The following program allocates the buffer needed by |
| .BR readlink () |
| dynamically from the information provided by |
| .BR lstat (), |
| making sure there's no race condition between the calls. |
| .nf |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct stat sb; |
| char *linkname; |
| ssize_t r; |
| |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s <pathname>\\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| if (lstat(argv[1], &sb) == \-1) { |
| perror("lstat"); |
| exit(EXIT_FAILURE); |
| } |
| |
| linkname = malloc(sb.st_size + 1); |
| if (linkname == NULL) { |
| fprintf(stderr, "insufficient memory\\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| r = readlink(argv[1], linkname, sb.st_size + 1); |
| |
| if (r == \-1) { |
| perror("readlink"); |
| exit(EXIT_FAILURE); |
| } |
| |
| if (r > sb.st_size) { |
| fprintf(stderr, "symlink increased in size " |
| "between lstat() and readlink()\\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| linkname[r] = \(aq\\0\(aq; |
| |
| printf("\(aq%s\(aq points to \(aq%s\(aq\\n", argv[1], linkname); |
| |
| free(linkname); |
| |
| exit(EXIT_SUCCESS); |
| } |
| .fi |
| .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) |