libbb: better coreutils compatibility for realpath
Add some tests which coreutils realpath pass but BusyBox realpath
fails (bar one). Adjust xmalloc_realpath_coreutils() so the tests
pass:
- Expand symbolic links before testing whether the last path component
exists.
- When the link target is a relative path canonicalize it by passing
it through xmalloc_realpath_coreutils() as already happens for
absolute paths.
- Ignore trailing slashes when finding the last path component and
correctly handle the case where the only slash is at the start of
the path. This requires ignoring superfluous leading slashes.
- Undo all changes to the path so error messages from the caller show
the original filename.
function old new delta
xmalloc_realpath_coreutils 214 313 +99
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/testsuite/realpath.tests b/testsuite/realpath.tests
new file mode 100755
index 0000000..0e68e02
--- /dev/null
+++ b/testsuite/realpath.tests
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Realpath tests.
+# Copyright 2006 by Natanael Copa <n@tanael.org>
+# Copyright 2021 by Ron Yorston <rmy@pobox.com>
+# Licensed under GPLv2, see file LICENSE in this source tree.
+
+. ./testing.sh
+
+unset LC_ALL
+unset LC_MESSAGES
+unset LANG
+unset LANGUAGE
+
+TESTDIR=realpath_testdir
+TESTLINK1="link1"
+TESTLINK2="link2"
+
+# create the dir and test files
+mkdir -p "./$TESTDIR"
+ln -s "./$TESTDIR/not_file" "./$TESTLINK1"
+ln -s "./$TESTDIR/not_file/not_dir" "./$TESTLINK2"
+
+# shell's $PWD may leave symlinks unresolved.
+# "pwd" may be a built-in and have the same problem.
+# External pwd _can't_ have that problem (current dir on Unix is physical).
+pwd=`which pwd`
+pwd=`$pwd`
+testing "realpath on non-existent absolute path 1" "realpath /not_file" "/not_file\n" "" ""
+testing "realpath on non-existent absolute path 2" "realpath /not_file/" "/not_file\n" "" ""
+testing "realpath on non-existent absolute path 3" "realpath //not_file" "/not_file\n" "" ""
+testing "realpath on non-existent absolute path 4" "realpath /not_dir/not_file 2>&1" "realpath: /not_dir/not_file: No such file or directory\n" "" ""
+
+testing "realpath on non-existent local file 1" "realpath $TESTDIR/not_file" "$pwd/$TESTDIR/not_file\n" "" ""
+testing "realpath on non-existent local file 2" "realpath $TESTDIR/not_dir/not_file 2>&1" "realpath: $TESTDIR/not_dir/not_file: No such file or directory\n" "" ""
+
+testing "realpath on link to non-existent file 1" "realpath $TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" ""
+testing "realpath on link to non-existent file 2" "realpath $TESTLINK2 2>&1" "realpath: $TESTLINK2: No such file or directory\n" "" ""
+testing "realpath on link to non-existent file 3" "realpath ./$TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" ""
+testing "realpath on link to non-existent file 4" "realpath ./$TESTLINK2 2>&1" "realpath: ./$TESTLINK2: No such file or directory\n" "" ""
+
+# clean up
+rm -r "$TESTLINK1" "$TESTLINK2" "$TESTDIR"
+
+exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255))