aboutsummaryrefslogtreecommitdiffstats
path: root/man2
diff options
context:
space:
mode:
authorMichael Kerrisk <mtk.manpages@gmail.com>2016-08-20 15:27:13 +1200
committerMichael Kerrisk <mtk.manpages@gmail.com>2016-08-20 15:27:13 +1200
commitcc6e4bf0cfd6cd3a4cc5484984f8987b7edfb43f (patch)
tree3b4e3fd841ccd60d54f70b0667c3bfdc1fed1f1a /man2
parente9979dff7cd21490424b9fb20c22ccd3a9c5f5ca (diff)
downloadman-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>
Diffstat (limited to 'man2')
-rw-r--r--man2/readlink.237
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