tls: prepare for ECDH_anon ciphers
[oweals/busybox.git] / libbb / xreadlink.c
index bb63da08c86c1c2dad6d90d8da6e974db8fde663..ead30e499cdb6d36464a3fd8bda53d0bb640135e 100644 (file)
@@ -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;
+}