OSDN Git Service

(split) LDP: Update original to LDP v3.52.
[linuxjm/LDP_man-pages.git] / original / man2 / readlink.2
index 8014d41..f4ee2cb 100644 (file)
@@ -1,6 +1,8 @@
 .\" Copyright (c) 1983, 1991 The Regents of the University of California.
+.\" And Copyright (C) 2011 Guillem Jover <guillem@hadrons.org>
 .\" 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:
 .\" 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 2007-07-26 "Linux" "Linux Programmer's Manual"
+.TH READLINK 2 2011-09-20 "Linux" "Linux Programmer's Manual"
 .SH NAME
 readlink \- read value of a symbolic link
 .SH SYNOPSIS
@@ -50,7 +55,10 @@ Feature Test Macro Requirements for glibc (see
 .sp
 .ad l
 .BR readlink ():
-_BSD_SOURCE || _XOPEN_SOURCE\ >=\ 500 || _POSIX_C_SOURCE\ >=\ 200112L
+.RS 4
+_BSD_SOURCE || _XOPEN_SOURCE\ >=\ 500 ||
+_XOPEN_SOURCE\ &&\ _XOPEN_SOURCE_EXTENDED || _POSIX_C_SOURCE\ >=\ 200112L
+.RE
 .ad b
 .SH DESCRIPTION
 .BR readlink ()
@@ -66,7 +74,7 @@ does not append a null byte to
 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.
-.SH "RETURN VALUE"
+.SH RETURN VALUE
 On success,
 .BR readlink ()
 returns the number of bytes placed in
@@ -114,10 +122,10 @@ Insufficient kernel memory was available.
 .TP
 .B ENOTDIR
 A component of the path prefix is not a directory.
-.SH "CONFORMING TO"
-4.4BSD (the
-.BR readlink ()
-function call appeared in 4.2BSD),
+.SH CONFORMING TO
+4.4BSD
+.RB ( readlink ()
+first appeared in 4.2BSD),
 POSIX.1-2001.
 .SH NOTES
 In versions of glibc up to and including glibc 2.4, the return type of
@@ -127,7 +135,84 @@ was declared as
 Nowadays, the return type is declared as
 .IR ssize_t ,
 as (newly) required in POSIX.1-2001.
-.SH "SEE ALSO"
+
+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 ()
+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 ()
+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.
+.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 < 0) {
+        perror("lstat");
+        exit(EXIT_FAILURE);
+    }
+
+    if (r > sb.st_size) {
+        fprintf(stderr, "symlink increased in size "
+                        "between lstat() and readlink()\\n");
+        exit(EXIT_FAILURE);
+    }
+
+    linkname[sb.st_size] = \(aq\\0\(aq;
+
+    printf("\(aq%s\(aq points to \(aq%s\(aq\\n", argv[1], linkname);
+
+    exit(EXIT_SUCCESS);
+}
+.fi
+.SH SEE ALSO
+.BR readlink (1),
 .BR lstat (2),
 .BR readlinkat (2),
 .BR stat (2),