Browse Source

support/scripts: fix and restrict conditions to accept merged dirs

Currently, we accept that the merged usr is backward, i.e. that the
/usr/bin, /usr/sbin, and /usr/lib entries be symlinks to, resp., /bin,
/sbin, and /lib. We also allow either entries to be symlinks to other
parts of the root. Both are accepted despite the comment at the top of
the script explaining what should be accepted.

However, a properly merged usr is the other way around: /bin, /sbin, and
/lib are the symlinks to resp. /usr/bin, /usr/sbin, and /usr/lib, which
are actual directories.

Fix the check-merged-usr script accordingly: implement the test as we
mean it, by testing the conditions rather than resorting to a convoluted
and incorrect use of stat(1).

Even though the split between test_dir() and test_merged() seems
superfluous, it'll come useful when we introduce support for merged-bin
in a later patch.

For skeletons, we require that the directories do exist, while we allow
them to be missing for overlays; indeed, it is perfectly legit to
provide an overlay that only contains totally unrelated directories
(e.g. /var/www to populate a webroot for example).

Extend the heading-comment to be more explicit (and drop '/' as there is
nothing to say about it).

Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
Signed-off-by: Romain Naour <romain.naour@smile.fr>
Yann E. MORIN 4 months ago
parent
commit
4da66e8130
1 changed files with 48 additions and 33 deletions
  1. 48 33
      support/scripts/check-merged-usr.sh

+ 48 - 33
support/scripts/check-merged-usr.sh

@@ -2,13 +2,14 @@
 #
 # Check if a given custom skeleton or overlay complies to the merged /usr
 # requirements:
-# /
-# /bin -> usr/bin
-# /lib -> usr/lib
-# /sbin -> usr/sbin
-# /usr/bin/
-# /usr/lib/
-# /usr/sbin/
+#   /bin            missing, or a relative symlink to usr/bin
+#   /lib            missing, or a relative symlink to usr/lib
+#   /sbin           missing, or a relative symlink to usr/sbin
+#   /usr/bin/       missing*, or an existing directory; not a symlink
+#   /usr/lib/       missing*, or an existing directory; not a symlink
+#   /usr/sbin/      missing*, or an existing directory; not a symlink
+#
+# *: must be present for skeletons, can be missing for overlays
 #
 # Input:
 #   --type TYPE     the type of root to check: 'skeleton' or 'overlay'
@@ -17,7 +18,7 @@
 #   stdout:         the list of non-compliant paths (empty if compliant).
 # Exit code:
 #   0:              in case of success (stdout will be empty)
-#   !0:             if any path is improperly merged
+#   !0:             if any directory to check is improperly merged
 #
 
 opts="type:"
@@ -38,6 +39,12 @@ while :; do
 	esac
 done
 
+if [ "${type}" = "skeleton" ]; then
+	strict=true
+else
+	strict=false
+fi
+
 report_error() {
 	local type="${1}"
 	local root="${2}"
@@ -54,44 +61,52 @@ report_error() {
 	is_success=false
 }
 
-# Extract the inode numbers for all of those directories. In case any is
-# a symlink, we want to get the inode of the pointed-to directory, so we
-# append '/.' to be sure we get the target directory. Since the symlinks
-# can be anyway (/bin -> /usr/bin or /usr/bin -> /bin), we do that for
-# each of them.
-#
-
-is_valid_merged() {
-	local root="${1}"
-	local dir1="${2}"
-	local dir2="${3}"
-	local inode1 inode2
+test_merged() {
+	local type="${1}"
+	local root="${2}"
+	local base="${3}"
+	local dir1="${4}"
+	local dir2="${5}"
 
-	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
-	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
+	if ! test -e "${root}${base}${dir1}"; then
+		return 0
+	elif [ "$(readlink "${root}${base}${dir1}")" = "${dir2}" ]; then
+		return 0
+	fi
 
-	test -z "${inode1}" || test "${inode1}" = "${inode2}"
+	# Otherwise, this directory is not merged
+	report_error "${type}" "${root}" \
+		'%s%s should be missing, or be a relative symlink to %s\n' \
+		"${base}" "${dir1}" "${dir2}"
 }
 
-test_merged() {
+test_dir() {
 	local type="${1}"
 	local root="${2}"
-	local dir1="${3}"
-	local dir2="${4}"
+	local base="${3}"
+	local dir="${4}"
 
-	if ! is_valid_merged "${root}" "${dir1}" "${dir2}"; then
-		report_error "${type}" "${root}" \
-			'%s should be missing, or be a relative symlink to %s\n' \
-			"${dir1}" "${dir2}"
+	if ! test -e "${root}${base}${dir}" && ! ${strict}; then
+		return 0
+	elif test -d "${root}${base}${dir}" && ! test -L "${root}${base}${dir}"; then
+		return 0
 	fi
+
+	# Otherwise, this entry is not a proper directory
+	report_error "${type}" "${root}" \
+		"%s%s should exist, be a directory, and not be a symlink\n" \
+		"${base}" "${dir}"
 }
 
 is_success=true
 for root; do
 	first=true
-	test_merged "${type}" "${root}" "/lib" "/usr/lib"
-	test_merged "${type}" "${root}" "/bin" "/usr/bin"
-	test_merged "${type}" "${root}" "/sbin" "/usr/sbin"
+	test_dir "${type}" "${root}" "/" "usr/bin"
+	test_dir "${type}" "${root}" "/" "usr/lib"
+	test_dir "${type}" "${root}" "/" "usr/sbin"
+	test_merged "${type}" "${root}" "/" "bin" "usr/bin"
+	test_merged "${type}" "${root}" "/" "lib" "usr/lib"
+	test_merged "${type}" "${root}" "/" "sbin" "usr/sbin"
 done
 
 ${is_success}