1 /* vi: set sw=4 ts=4: */
3 * xreadlink.c - safe implementation of readlink.
4 * Returns a NULL on failure...
6 * Licensed under GPLv2, see file LICENSE in this source tree.
12 * NOTE: This function returns a malloced char* that you will have to free
15 char* FAST_FUNC
xmalloc_readlink(const char *path
)
17 enum { GROWBY
= 80 }; /* how large we will grow strings by */
20 int bufsize
= 0, readsize
= 0;
24 buf
= xrealloc(buf
, bufsize
);
25 readsize
= readlink(path
, buf
, bufsize
);
30 } while (bufsize
< readsize
+ 1);
38 * This routine is not the same as realpath(), which
39 * canonicalizes the given path completely. This routine only
40 * follows trailing symlinks until a real file is reached and
41 * returns its name. If the path ends in a dangling link or if
42 * the target doesn't exist, the path is returned in any case.
43 * Intermediate symlinks in the path are not expanded -- only
45 * A malloced char* is returned, which must be freed by the caller.
47 char* FAST_FUNC
xmalloc_follow_symlinks(const char *path
)
53 int looping
= MAXSYMLINKS
+ 1;
59 linkpath
= xmalloc_readlink(buf
);
61 /* not a symlink, or doesn't exist */
62 if (errno
== EINVAL
|| errno
== ENOENT
)
64 goto free_buf_ret_null
;
74 if (*linkpath
!= '/') {
75 bufsize
+= strlen(linkpath
);
76 buf
= xrealloc(buf
, bufsize
);
77 lpc
= bb_get_last_path_component_strip(buf
);
78 strcpy(lpc
, linkpath
);
84 bufsize
= strlen(buf
) + 1;
89 char* FAST_FUNC
xmalloc_readlink_or_warn(const char *path
)
91 char *buf
= xmalloc_readlink(path
);
93 /* EINVAL => "file: Invalid argument" => puzzled user */
94 const char *errmsg
= "not a symlink";
97 errmsg
= strerror(err
);
98 bb_error_msg("%s: cannot read link: %s", path
, errmsg
);
103 char* FAST_FUNC
xmalloc_realpath(const char *path
)
105 #if defined(__GLIBC__) && !defined(__UCLIBC__)
106 /* glibc provides a non-standard extension */
107 /* new: POSIX.1-2008 specifies this behavior as well */
108 return realpath(path
, NULL
);
110 char buf
[PATH_MAX
+1];
112 /* on error returns NULL (xstrdup(NULL) == NULL) */
113 return xstrdup(realpath(path
, buf
));