readlink(2) System Calls Manual readlink(2) readlink, readlinkat - LIBRARY Standard C library (libc, -lc) #include ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsiz); #include /* AT_* */ #include ssize_t readlinkat(int dirfd, const char *restrict pathname, char *restrict buf, size_t bufsiz); glibc (. feature_test_macros(7)): readlink(): _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L || /* glibc <= 2.19: */ _BSD_SOURCE readlinkat(): glibc 2.10: _POSIX_C_SOURCE >= 200809L glibc 2.10: _ATFILE_SOURCE readlink() places the contents of the symbolic link pathname in the buffer buf, which has size bufsiz. readlink() does not append a terminating null byte to buf. It will (silently) truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents. readlinkat() readlinkat() readlink(), , . pathname , , dirfd ( , readlink()). pathname dirfd AT_FDCWD, pathname ( readlink()). pathname , dirfd . Linux .6.39, pathname ; , dirfd ( open(2) O_PATH O_NOFOLLOW). openat(2) readlinkat(). , buf ( bufsiz, ). -1, errno . EACCES (. path_resolution(7). EBADF (readlinkat()) pathname is relative but dirfd is neither AT_FDCWD nor a valid file descriptor. EFAULT buf , . EINVAL bufsiz . EINVAL (. ., pathname) . EIO -. ELOOP pathname . ENAMETOOLONG pathname . ENOENT . ENOMEM . ENOTDIR . ENOTDIR (readlinkat()) pathname dirfd , , . POSIX.1-2008. readlink() 4.4BSD (first appeared in 4.2BSD), POSIX.1-2001, POSIX.1-2008. readlinkat() POSIX.1-2008. Linux 2.6.16, glibc 2.4. Up to and including glibc 2.4, the return type of readlink() was declared as int. Nowadays, the return type is declared as ssize_t, as (newly) required in POSIX.1-2001. glibc , readlinkat() , glibc readlink(). pathname , glibc /proc/self/fd, dirfd. . stat.st_size, lstat(2). , , readlink() readlinkat(), , , . readlink() readlinkat() , , PATH_MAX, POSIX , , . , readlink(), , lstat(2), PATH_MAX, lstat(2) . #include #include #include #include #include int main(int argc, char *argv[]) { char *buf; ssize_t nbytes, bufsiz; struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s \n", 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 'st_size' 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 'nbytes' of 'buf', as it doesn't contain a terminating null byte ('\0'). */ printf("'%s' points to '%.*s'\n", argv[1], (int) nbytes, buf); /* If the return value was equal to the buffer size, then 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)\n"); free(buf); exit(EXIT_SUCCESS); } . readlink(1), lstat(2), stat(2), symlink(2), realpath(3), path_resolution(7), symlink(7) aereiae , Azamat Hackimov , Dmitriy S. Seregin , Katrin Kutepova , Lockal , Yuri Kozlov , ; GNU 3 , . . , , . Linux man-pages 6.06 1 2023 . readlink(2)