readlink,realpath: fix a case with a symplink, closes 11021
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 13 Jun 2019 15:08:29 +0000 (17:08 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 13 Jun 2019 15:09:05 +0000 (17:09 +0200)
function                                             old     new   delta
xmalloc_realpath_coreutils                           125     201     +76

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/xreadlink.c

index ead30e499cdb6d36464a3fd8bda53d0bb640135e..a4e402b84c59b4818a624da2204f63e69e7f1751 100644 (file)
@@ -147,6 +147,35 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
                                buf[len++] = '/';
                                strcpy(buf + len, last_slash);
                        }
+               } else {
+                       char *link = xmalloc_readlink(path);
+                       if (link) {
+                               char *cwd;
+                               if (link[0] == '/') {
+                                       /*
+                                        * $ ln -s /bin/qwe symlink  # note: /bin is a link to /usr/bin
+                                        * $ readlink -f symlink
+                                        * /usr/bin/qwe/target_does_not_exist
+                                        * $ realpath symlink
+                                        * /usr/bin/qwe/target_does_not_exist
+                                        */
+                                       buf = xmalloc_realpath_coreutils(link);
+                                       free(link);
+                                       return buf;
+                               }
+                               /*
+                                * $ ln -s target_does_not_exist symlink
+                                * $ readlink -f symlink
+                                * /CURDIR/target_does_not_exist
+                                * $ realpath symlink
+                                * /CURDIR/target_does_not_exist
+                                */
+                               cwd = xrealloc_getcwd_or_warn(NULL);
+                               buf = concat_path_file(cwd, link);
+                               free(cwd);
+                               free(link);
+                               return buf;
+                       }
                }
        }