source: src/router/busybox/libbb/xreadlink.c @ 8864

Last change on this file since 8864 was 8864, checked in by BrainSlayer, 5 years ago

replace busybox with new version

File size: 2.3 KB
Line 
1/* 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 * yourself.
12 */
13char *xmalloc_readlink(const char *path)
14{
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                bufsize += GROWBY;
22                buf = xrealloc(buf, bufsize);
23                readsize = readlink(path, buf, bufsize);
24                if (readsize == -1) {
25                        free(buf);
26                        return NULL;
27                }
28        } while (bufsize < readsize + 1);
29
30        buf[readsize] = '\0';
31
32        return buf;
33}
34
35/*
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 */
45char *xmalloc_follow_symlinks(const char *path)
46{
47        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
58                linkpath = xmalloc_readlink(buf);
59                if (!linkpath) {
60                        /* not a symlink, or doesn't exist */
61                        if (errno == EINVAL || errno == ENOENT)
62                                return buf;
63                        goto free_buf_ret_null;
64                }
65
66                if (!--looping) {
67                        free(linkpath);
68 free_buf_ret_null:
69                        free(buf);
70                        return NULL;
71                }
72
73                if (*linkpath != '/') {
74                        bufsize += strlen(linkpath);
75                        buf = xrealloc(buf, bufsize);
76                        lpc = bb_get_last_path_component_strip(buf);
77                        strcpy(lpc, linkpath);
78                        free(linkpath);
79                } else {
80                        free(buf);
81                        buf = linkpath;
82 jump_in:
83                        bufsize = strlen(buf) + 1;
84                }
85        }
86}
87
88char *xmalloc_readlink_or_warn(const char *path)
89{
90        char *buf = xmalloc_readlink(path);
91        if (!buf) {
92                /* EINVAL => "file: Invalid argument" => puzzled user */
93                bb_error_msg("%s: cannot read link (not a symlink?)", path);
94        }
95        return buf;
96}
97
98/* UNUSED */
99#if 0
100char *xmalloc_realpath(const char *path)
101{
102#if defined(__GLIBC__) && !defined(__UCLIBC__)
103        /* glibc provides a non-standard extension */
104        return realpath(path, NULL);
105#else
106        char buf[PATH_MAX+1];
107
108        /* on error returns NULL (xstrdup(NULL) ==NULL) */
109        return xstrdup(realpath(path, buf));
110#endif
111}
112#endif
Note: See TracBrowser for help on using the repository browser.