diff options
| author | Michael Kerrisk <mtk.manpages@gmail.com> | 2016-08-20 15:27:13 +1200 |
|---|---|---|
| committer | Michael Kerrisk <mtk.manpages@gmail.com> | 2016-08-20 15:27:13 +1200 |
| commit | cc6e4bf0cfd6cd3a4cc5484984f8987b7edfb43f (patch) | |
| tree | 3b4e3fd841ccd60d54f70b0667c3bfdc1fed1f1a | |
| parent | e9979dff7cd21490424b9fb20c22ccd3a9c5f5ca (diff) | |
| download | man-pages-cc6e4bf0cfd6cd3a4cc5484984f8987b7edfb43f.tar.gz | |
readlink.2: Make example program handle links that report a size of zero
Some "magic" symlinks created by the kernel (e.g., those under
/proc and /sys) report 'st_size' as zero. Modify the example
program to handle that possibility.
Reported-by: Ursache Vladimir <f35f22fan@gmail.com>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
| -rw-r--r-- | man2/readlink.2 | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/man2/readlink.2 b/man2/readlink.2 index c64c630f6a..97e79f3fe2 100644 --- a/man2/readlink.2 +++ b/man2/readlink.2 @@ -277,11 +277,16 @@ The following program allocates the buffer needed by .BR readlink () dynamically from the information provided by .BR lstat (2), -making sure there's no race condition between the calls. +falling back to a buffer of size +.BR PATH_MAX +in cases where +.BR lstat (2) +reports a size of zero. .nf #include <sys/types.h> #include <sys/stat.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -291,7 +296,7 @@ main(int argc, char *argv[]) { struct stat sb; char *linkname; - ssize_t r; + ssize_t r, bufsiz; if (argc != 2) { fprintf(stderr, "Usage: %s <pathname>\\n", argv[0]); @@ -303,31 +308,37 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } - linkname = malloc(sb.st_size + 1); + bufsiz = sb.st_size + 1; + + /* Some magic symlinks under (for example) /proc and /sys + report \(aqst_size\(aq as zero. In that case, take PATH_MAX as + a "good enough" estimate */ + + if (sb.st_size == 0) + bufsiz = PATH_MAX; + + printf("%zd\\n", bufsiz); + + linkname = malloc(bufsiz); if (linkname == NULL) { - fprintf(stderr, "insufficient memory\\n"); + perror("malloc"); exit(EXIT_FAILURE); } - r = readlink(argv[1], linkname, sb.st_size + 1); - + r = readlink(argv[1], linkname, bufsiz); 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); + if (r == bufsiz) + printf("(Returned buffer may have been truncated)\\n"); + free(linkname); exit(EXIT_SUCCESS); } .fi |
