[Buildroot] [PATCH 1/2] core: make symlinks relative when preparing the SDK

Yann E. MORIN yann.morin.1998 at free.fr
Fri Dec 7 18:10:09 UTC 2018


The SDK is supposed to be relocatable, so symlinks must not be
absolute.

Add a new helper script, that replaces all absolute symlinks with
relative ones.

The ideal solution would use the shortest relative path for the
destination, but it is non-trivial to come up with. We just ensure
the relative path does not cross a common base directory, and compute
all the paths relative to that anchor.

This can give non-optimum relative symlinks, like:
    /base-dir/bin/foo -> ../bin/bar

when the optimum would have been:
    /base-dir/bin/foo -> bar

Finally, as a sanity check, ensure there is not relative symlinl
pointing out of the base directory, because their targets would be
missing from the SDK.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998 at free.fr>
Cc: Joel Carlson <JoelsonCarl at gmail.com>
---
 Makefile                     |  1 +
 support/scripts/fix-symlinks | 53 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100755 support/scripts/fix-symlinks

diff --git a/Makefile b/Makefile
index 37df98520e..e8a1c7b366 100644
--- a/Makefile
+++ b/Makefile
@@ -586,6 +586,7 @@ prepare-sdk: world
 	@$(call MESSAGE,"Rendering the SDK relocatable")
 	$(TOPDIR)/support/scripts/fix-rpath host
 	$(TOPDIR)/support/scripts/fix-rpath staging
+	$(TOPDIR)/support/scripts/fix-symlinks "$(HOST_DIR)"
 	$(INSTALL) -m 755 $(TOPDIR)/support/misc/relocate-sdk.sh $(HOST_DIR)/relocate-sdk.sh
 	mkdir -p $(HOST_DIR)/share/buildroot
 	echo $(HOST_DIR) > $(HOST_DIR)/share/buildroot/sdk-location
diff --git a/support/scripts/fix-symlinks b/support/scripts/fix-symlinks
new file mode 100755
index 0000000000..b1190300e2
--- /dev/null
+++ b/support/scripts/fix-symlinks
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Transform all symlinks in ${1} from absolute to relative,
+# with the base of relativity anchored in ${1}
+#
+# Additionally, ensure that all existing symlinks point inside the
+# base directory.
+#
+# Note that the relativity of the symlink is not the shortest, e.g.
+# ${base}/bin/foo can end up as a symlink to ../bin/bar when it would
+# be shorter to have a symlink to ./bar, or even simply to bar. This
+# is not the nicest, but works and is easy to do.
+
+main() {
+    local base="${1}"
+    local link dest reldir
+    local -a links
+
+    links=( $(find "${base}" -type l -printf '%P\n') )
+    for link in "${links[@]}"; do
+        dest="$(readlink "${base}/${link}")"
+        case "${dest}" in
+          ("${base}"/*) ;; # We need to handle that one
+          (/*)
+            printf 'Absolute symlink outside of base "%s": "%s" -> "%s"\n' \
+                   "${base}" "${link}" "${dest}"
+            exit 1
+            ;;
+          (../*|*/../*|*/..)
+            # Not absolute, but does it cross the boundary?
+            dest="$(readlink -m "${base}/${link}")"
+            case "${dest}" in
+              ("${base}"/*) ;; # Anchored, OK
+              (*)
+                printf 'Relative symlink outside of base "%s": "%s" -> "%s"\n' \
+                       "${base}" "${link}" "${dest}"
+                exit 1
+                ;;
+            esac
+            continue # Not absolute, does not cross, OK
+            ;;
+          (*)
+            continue # Not absolute, does not cross, OK
+            ;;
+        esac
+        reldir="$(sed -r -e 's,([^/]+/),../,g; s,/[^/]+$,,' <<<"${link#${base}}")"
+        rm -f "${base}/${link}"
+        ln -sf "${reldir}${dest#${base}}" "${base}/${link}"
+    done
+}
+
+main "${@}"
-- 
2.14.1



More information about the buildroot mailing list