X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=libbb%2Fxreadlink.c;h=ead30e499cdb6d36464a3fd8bda53d0bb640135e;hb=3a4d5a73a876b0922afed095bc9f83dbdf07148e;hp=bb63da08c86c1c2dad6d90d8da6e974db8fde663;hpb=9f4f60183b2de12ff618a4966378c6b49184b1de;p=oweals%2Fbusybox.git diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index bb63da08c..ead30e499 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -1,14 +1,13 @@ /* vi: set sw=4 ts=4: */ /* * xreadlink.c - safe implementation of readlink. - * Returns a NULL on failure... + * Returns a NULL on failure. * * Licensed under GPLv2, see file LICENSE in this source tree. */ - #include "libbb.h" -/* some systems (eg Hurd) does not have MAXSYMLINKS definition, +/* Some systems (eg Hurd) do not have MAXSYMLINKS definition, * set it to some reasonable value if it isn't defined */ #ifndef MAXSYMLINKS # define MAXSYMLINKS 20 @@ -108,8 +107,11 @@ char* FAST_FUNC xmalloc_readlink_or_warn(const char *path) char* FAST_FUNC xmalloc_realpath(const char *path) { -#if defined(__GLIBC__) || \ - (defined(__UCLIBC__) && UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31)) +/* NB: uclibc also defines __GLIBC__ + * Therefore the test "if glibc, or uclibc >= 0.9.31" looks a bit weird: + */ +#if defined(__GLIBC__) && \ + (!defined(__UCLIBC__) || UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31)) /* glibc provides a non-standard extension */ /* new: POSIX.1-2008 specifies this behavior as well */ return realpath(path, NULL); @@ -120,3 +122,33 @@ char* FAST_FUNC xmalloc_realpath(const char *path) return xstrdup(realpath(path, buf)); #endif } + +char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) +{ + char *buf; + + errno = 0; + buf = xmalloc_realpath(path); + /* + * There is one case when "readlink -f" and + * "realpath" from coreutils succeed, + * even though file does not exist, such as: + * /tmp/file_does_not_exist + * (the directory must exist). + */ + if (!buf && errno == ENOENT) { + char *last_slash = strrchr(path, '/'); + if (last_slash) { + *last_slash++ = '\0'; + buf = xmalloc_realpath(path); + if (buf) { + unsigned len = strlen(buf); + buf = xrealloc(buf, len + strlen(last_slash) + 2); + buf[len++] = '/'; + strcpy(buf + len, last_slash); + } + } + } + + return buf; +}