Magellan Linux

Annotation of /tags/mkinitrd-6_2_0/libbb/xreadlink.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 2 months ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/libbb/xreadlink.c
File MIME type: text/plain
File size: 2441 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * xreadlink.c - safe implementation of readlink.
4     * Returns a NULL on failure...
5     */
6    
7     #include "libbb.h"
8    
9     /*
10     * NOTE: This function returns a malloced char* that you will have to free
11 niro 816 * yourself.
12 niro 532 */
13 niro 816 char* FAST_FUNC xmalloc_readlink(const char *path)
14 niro 532 {
15     enum { GROWBY = 80 }; /* how large we will grow strings by */
16    
17     char *buf = NULL;
18     int bufsize = 0, readsize = 0;
19    
20     do {
21 niro 816 bufsize += GROWBY;
22     buf = xrealloc(buf, bufsize);
23     readsize = readlink(path, buf, bufsize);
24 niro 532 if (readsize == -1) {
25     free(buf);
26     return NULL;
27     }
28 niro 816 } while (bufsize < readsize + 1);
29 niro 532
30     buf[readsize] = '\0';
31    
32     return buf;
33     }
34    
35 niro 816 /*
36     * This routine is not the same as realpath(), which
37     * canonicalizes the given path completely. This routine only
38     * follows trailing symlinks until a real file is reached and
39     * returns its name. If the path ends in a dangling link or if
40     * the target doesn't exist, the path is returned in any case.
41     * Intermediate symlinks in the path are not expanded -- only
42     * those at the tail.
43     * A malloced char* is returned, which must be freed by the caller.
44     */
45     char* FAST_FUNC xmalloc_follow_symlinks(const char *path)
46 niro 532 {
47 niro 816 char *buf;
48     char *lpc;
49     char *linkpath;
50     int bufsize;
51     int looping = MAXSYMLINKS + 1;
52    
53     buf = xstrdup(path);
54     goto jump_in;
55    
56     while (1) {
57     linkpath = xmalloc_readlink(buf);
58     if (!linkpath) {
59     /* not a symlink, or doesn't exist */
60     if (errno == EINVAL || errno == ENOENT)
61     return buf;
62     goto free_buf_ret_null;
63     }
64    
65     if (!--looping) {
66     free(linkpath);
67     free_buf_ret_null:
68     free(buf);
69     return NULL;
70     }
71    
72     if (*linkpath != '/') {
73     bufsize += strlen(linkpath);
74     buf = xrealloc(buf, bufsize);
75     lpc = bb_get_last_path_component_strip(buf);
76     strcpy(lpc, linkpath);
77     free(linkpath);
78     } else {
79     free(buf);
80     buf = linkpath;
81     jump_in:
82     bufsize = strlen(buf) + 1;
83     }
84     }
85     }
86    
87     char* FAST_FUNC xmalloc_readlink_or_warn(const char *path)
88     {
89     char *buf = xmalloc_readlink(path);
90     if (!buf) {
91     /* EINVAL => "file: Invalid argument" => puzzled user */
92     bb_error_msg("%s: cannot read link (not a symlink?)", path);
93     }
94     return buf;
95     }
96    
97     /* UNUSED */
98     #if 0
99     char* FAST_FUNC xmalloc_realpath(const char *path)
100     {
101 niro 532 #if defined(__GLIBC__) && !defined(__UCLIBC__)
102     /* glibc provides a non-standard extension */
103     return realpath(path, NULL);
104     #else
105     char buf[PATH_MAX+1];
106    
107     /* on error returns NULL (xstrdup(NULL) ==NULL) */
108     return xstrdup(realpath(path, buf));
109     #endif
110     }
111 niro 816 #endif