Skip to contentSkip to conversation

system: add support for merged-bin (branch yem/merged-bin)

PATCH In review Yann E. MORIN 2 participants 29 messages May 14, 2025 – May 17, 2025 Kbuild

lore
Share & tools
lore
#0 lore raw

cover system: add support for merged-bin (branch yem/merged-bin)

Hello All!

This series introduces support for so-called merged-bin, where /usr/sbin is merged with /sur/bin, as an extra step after merged-usr, now requested, and later required in a relatively close future, by systemd.

The series is organised in 4 main steps::

1. patches 1-3 are cleanups in the Kconfig menu, related to the merged-usr prompt, to the defaults for PATH, and to the rationale for selecting merged-usr with systemd; those can be applied without considering the rest of the series;

2. then patches 4-6 prepare support/scripts/check-merged-usr.sh to check for more than merged-usr: a good cleanup, and better check the merged state; those patch can also be applied without considering the rest of the series;

3. with patches 7-9, support for merged-bin is added, and made mandatory

    for systemd;

4. finally, patches 10-13 introduce workarounds for a few packages to properly support merged-bin. For ease of review, those are separate patches, but that means the series _may_ break if the merged-bin support is applied but not the per-package workarounds.

Although the series was tested with a large set of packages and a large set of toolchains, and although it is a critical change, it is still pretty well confined to just a few spots.

Regards,
Yann E. MORIN.

----------------------------------------------------------------
Yann E. MORIN (13):
system: reword merged-usr prompt
system: drop superfluous negative condition for default PATH package/systemd: select merged-usr from package, not init support/scripts: comonalise checking merged status support/scripts: fix and restrict conditions to accept merged dirs support/scripts: rename check-merged-usr.sh support/scripts; teach check-merged what to check
system: add support for merged /usr/sbin (aka merged-bin) package/systemd: require merged-bin
package/coreutils: no need for chroot workaround with merged-bin package/kmod: adjust paths for merged-bin package/util-linux: adjust paths for merged-bin toolchain/external: support merged-bin

 Makefile                                   | 11 ++---
 package/coreutils/coreutils.mk             |  2 +
 package/kmod/kmod.mk                       | 12 +++++-
 package/skeleton-custom/skeleton-custom.mk | 10 +++--
 package/systemd/Config.in                  |  2 +
 package/util-linux/util-linux.mk           |  8 +++-
 support/scripts/check-merged               | 65 ++++++++++++++++++++++++++++++
 support/scripts/check-merged-usr.sh        | 39 ------------------
 system/Config.in                           | 20 +++++----
 system/skeleton/usr/sbin/.empty            |  0
 system/system.mk                           | 11 +++++
 toolchain/helpers.mk                       |  8 +++-
 12 files changed, 128 insertions(+), 60 deletions(-)
 create mode 100755 support/scripts/check-merged
 delete mode 100755 support/scripts/check-merged-usr.sh
 delete mode 100644 system/skeleton/usr/sbin/.empty

--
.-----------------.--------------------.------------------.--------------------.

|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |

'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#1 lore raw

PATCH 1/13 system: reword merged-usr prompt

The current pro;pt is overly verbose, and departs from the usual terminology used to refer to merged /usr, which, 10 years later [0], makes it a little bit difficult to find or understand.

Furthermore, we're going to add another similar prompt for merged /usr/sbin, and there's no way we want to introduce as similarly convoluted prompt then.

Reword the prompt for the merged /usr option to the explicit "merged /usr" everyone expects and understands.

[0] see commit c5bd8af65e50 (system: add options for /bin /sbin and /lib to be symlinks into /usr)

---
 system/Config.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
system/Config.in +1 -1
index 8ff6c7213e..f747fdbc56 100644
@@ -336,7 +336,7 @@ config BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES
 	  Support extended attributes handling in device tables
 
 config BR2_ROOTFS_MERGED_USR
-	bool "Use symlinks to /usr for /bin, /sbin and /lib"
+	bool "Merged /usr"
 	help
 	  If you say 'n' here, then /bin, /sbin and /lib and their
 	  counterparts in /usr will be separate directories. This
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 1/13
#2 lore raw

Re: [Buildroot] [PATCH 01/13] system: reword merged-usr prompt

Quoted 8 lines · Yann E. MORIN

The current pro;pt is overly verbose, and departs from the usual terminology used to refer to merged /usr, which, 10 years later [0], makes it a little bit difficult to find or understand.

Furthermore, we're going to add another similar prompt for merged /usr/sbin, and there's no way we want to introduce as similarly convoluted prompt then.

Quoted 7 lines

Reword the prompt for the merged /usr option to the explicit "merged /usr" everyone expects and understands.

[0] see commit c5bd8af65e50 (system: add options for /bin /sbin and /lib to be symlinks into /usr)

Quoted 9 lines
---
  system/Config.in | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
system/Config.in +0 -0
index 8ff6c7213e..f747fdbc56 100644

system/Config.in config BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES · line 342

Quoted 8 lines
system/Config.in +1 -1
@@ -336,7 +336,7 @@ config BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES
  	  Support extended attributes handling in device tables
 
  config BR2_ROOTFS_MERGED_USR
-	bool "Use symlinks to /usr for /bin, /sbin and /lib"
+	bool "Merged /usr"
  	help
  	  If you say 'n' here, then /bin, /sbin and /lib and their
  	  counterparts in /usr will be separate directories. This

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#3 lore raw

PATCH 2/13 system: drop superfluous negative condition for default PATH

In reply to Yann E. MORIN

Kconfig applies the default values in the order they are defined, and stops at the first which condition is met. In this case, the two conditions are mutually exclusive, so we can drop the second one. This also makes it obvious there actually is a default value.

---
 system/Config.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
system/Config.in +1 -1
index f747fdbc56..2499dc8208 100644
@@ -534,7 +534,7 @@ endif # BR2_ROOTFS_SKELETON_DEFAULT
 config BR2_SYSTEM_DEFAULT_PATH
 	string "Set the system's default PATH"
 	default "/usr/bin:/usr/sbin" if BR2_ROOTFS_MERGED_USR
-	default "/bin:/sbin:/usr/bin:/usr/sbin" if !BR2_ROOTFS_MERGED_USR
+	default "/bin:/sbin:/usr/bin:/usr/sbin"
 	help
 	  Sets the system's default PATH. It is being used in
 	  /etc/profile in the skeleton-init-common package and by some
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 2/13
#4 lore raw

Re: [Buildroot] [PATCH 02/13] system: drop superfluous negative condition for default PATH

Quoted 6 lines · Yann E. MORIN

Kconfig applies the default values in the order they are defined, and stops at the first which condition is met. In this case, the two conditions are mutually exclusive, so we can drop the second one. This also makes it obvious there actually is a default value.

Quoted 9 lines
---
  system/Config.in | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
system/Config.in +0 -0
index f747fdbc56..2499dc8208 100644

system/Config.in endif # BR2_ROOTFS_SKELETON_DEFAULT · line 540

Quoted 8 lines
system/Config.in +1 -1
@@ -534,7 +534,7 @@ endif # BR2_ROOTFS_SKELETON_DEFAULT
  config BR2_SYSTEM_DEFAULT_PATH
  	string "Set the system's default PATH"
  	default "/usr/bin:/usr/sbin" if BR2_ROOTFS_MERGED_USR
-	default "/bin:/sbin:/usr/bin:/usr/sbin" if !BR2_ROOTFS_MERGED_USR
+	default "/bin:/sbin:/usr/bin:/usr/sbin"
  	help
  	  Sets the system's default PATH. It is being used in
  	  /etc/profile in the skeleton-init-common package and by some

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#5 lore raw

PATCH 3/13 package/systemd: select merged-usr from package, not init

In reply to Yann E. MORIN

Since version 255, systemd no longer supports split-usr [0].

Move the select from the init system to the package, to explicitly expose tha fact.

Drop our comment about our design decision, as it no longer applies.

[0] https://github.com/systemd/systemd/blob/v255/NEWS#L7

Cc Norbert Lange <[email protected]>
Cc Sen Hastings <[email protected]>
---
 package/systemd/Config.in | 1 +
 system/Config.in          | 5 -----
 2 files changed, 1 insertion(+), 5 deletions(-)
package/systemd/Config.in +1 -0
index 851b91aeba..fd7671480c 100644
@@ -24,6 +24,7 @@ menuconfig BR2_PACKAGE_SYSTEMD
 	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_15
 	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
 	depends on BR2_HOST_GCC_AT_LEAST_8 # host-systemd
+	select BR2_ROOTFS_MERGED_USR
 	select BR2_PACKAGE_HAS_UDEV
 	select BR2_PACKAGE_DBUS if !BR2_PACKAGE_DBUS_BROKER # runtime
 	select BR2_PACKAGE_LIBCAP
system/Config.in +0 -5
index 2499dc8208..2f42e5ddf9 100644
@@ -115,10 +115,6 @@ comment "openrc needs a glibc or musl toolchain w/ dynamic library"
 	depends on BR2_USE_MMU
 	depends on BR2_STATIC_LIBS && BR2_TOOLCHAIN_USES_UCLIBC
 
-# In Buildroot, we decided not to support a split-usr when systemd is
-# used as an init system. This is a design decision, not a systemd
-# issue. Thus the select is with BR2_INIT_SYSTEMD (below) rather than
-# with BR2_PACKAGE_SYSTEMD.
 config BR2_INIT_SYSTEMD
 	bool "systemd"
 	depends on BR2_PACKAGE_SYSTEMD_ARCH_SUPPORTS
@@ -130,7 +126,6 @@ config BR2_INIT_SYSTEMD
 	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_15
 	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
 	depends on BR2_HOST_GCC_AT_LEAST_8
-	select BR2_ROOTFS_MERGED_USR
 	select BR2_PACKAGE_SYSTEMD
 	select BR2_PACKAGE_SKELETON_INIT_SYSTEMD if BR2_ROOTFS_SKELETON_DEFAULT
 
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 3/13
#6 lore raw

Re: [Buildroot] [PATCH 03/13] package/systemd: select merged-usr from package, not init

Quoted 5 lines · Yann E. MORIN

Since version 255, systemd no longer supports split-usr [0].

Move the select from the init system to the package, to explicitly expose tha fact.

Quoted 7 lines

Drop our comment about our design decision, as it no longer applies.

[0] https://github.com/systemd/systemd/blob/v255/NEWS#L7

Cc Norbert Lange <[email protected]>
Cc Sen Hastings <[email protected]>
Quoted 33 lines
---
  package/systemd/Config.in | 1 +
  system/Config.in          | 5 -----
  2 files changed, 1 insertion(+), 5 deletions(-)
package/systemd/Config.in +1 -0
index 851b91aeba..fd7671480c 100644
@@ -24,6 +24,7 @@ menuconfig BR2_PACKAGE_SYSTEMD
  	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_15
  	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
  	depends on BR2_HOST_GCC_AT_LEAST_8 # host-systemd
+	select BR2_ROOTFS_MERGED_USR
  	select BR2_PACKAGE_HAS_UDEV
  	select BR2_PACKAGE_DBUS if !BR2_PACKAGE_DBUS_BROKER # runtime
  	select BR2_PACKAGE_LIBCAP
system/Config.in +0 -4
index 2499dc8208..2f42e5ddf9 100644
@@ -115,10 +115,6 @@ comment "openrc needs a glibc or musl toolchain w/ dynamic library"
  	depends on BR2_USE_MMU
  	depends on BR2_STATIC_LIBS && BR2_TOOLCHAIN_USES_UCLIBC
 
-# In Buildroot, we decided not to support a split-usr when systemd is
-# used as an init system. This is a design decision, not a systemd
-# issue. Thus the select is with BR2_INIT_SYSTEMD (below) rather than
-# with BR2_PACKAGE_SYSTEMD.
  config BR2_INIT_SYSTEMD
  	bool "systemd"
  	depends on BR2_PACKAGE_SYSTEMD_ARCH_SUPPORTS

system/Config.in config BR2_INIT_SYSTEMD · line 131

Quoted 7 lines
system/Config.in +0 -1
@@ -130,7 +126,6 @@ config BR2_INIT_SYSTEMD
  	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_15
  	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
  	depends on BR2_HOST_GCC_AT_LEAST_8
-	select BR2_ROOTFS_MERGED_USR
  	select BR2_PACKAGE_SYSTEMD
  	select BR2_PACKAGE_SKELETON_INIT_SYSTEMD if BR2_ROOTFS_SKELETON_DEFAULT
 

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#7 lore raw

PATCH 4/13 support/scripts: comonalise checking merged status

In reply to Yann E. MORIN

Rather than repeat the same canned sequence over and over again, move it to a function that we can reuse as many times as needed. This will come handy when we later need to check merged sbin.

Switch to using bash as it allows for nicer functions (local variables), but we anyway require it globally already so that's not an additional dependency.

---
 support/scripts/check-merged-usr.sh | 46 ++++++++++++++++-------------
 1 file changed, 26 insertions(+), 20 deletions(-)
support/scripts/check-merged-usr.sh +26 -20
index 433857cd8c..ed0c58e9b7 100755
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #
 # Check if a given custom skeleton or overlay complies to the merged /usr
 # requirements:
@@ -10,30 +10,36 @@
 # /usr/lib/
 # /usr/sbin/
 #
-# Output: the list of non-compliant paths (empty if compliant).
+# Input:
+#   $1:     the root directory (skeleton, overlay) to check
+# Output:
+#   stdout: the list of non-compliant paths (empty if compliant).
 #
 
+# The directory to check for merged-usr
+root="${1}"
+
 # 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
-# all of them.
+# each of them.
 #
-lib_inode=$(stat -c '%i' "${1}/lib/." 2>/dev/null)
-bin_inode=$(stat -c '%i' "${1}/bin/." 2>/dev/null)
-sbin_inode=$(stat -c '%i' "${1}/sbin/." 2>/dev/null)
-usr_lib_inode=$(stat -c '%i' "${1}/usr/lib/." 2>/dev/null)
-usr_bin_inode=$(stat -c '%i' "${1}/usr/bin/." 2>/dev/null)
-usr_sbin_inode=$(stat -c '%i' "${1}/usr/sbin/." 2>/dev/null)
 
-not_merged_dirs=""
-test -z "$lib_inode" || \
-	test "$lib_inode" = "$usr_lib_inode" || \
-		not_merged_dirs="/lib"
-test -z "$bin_inode" || \
-	test "$bin_inode" = "$usr_bin_inode" || \
-		not_merged_dirs="$not_merged_dirs /bin"
-test -z "$sbin_inode" || \
-	test "$sbin_inode" = "$usr_sbin_inode" || \
-		not_merged_dirs="$not_merged_dirs /sbin"
-echo "${not_merged_dirs# }"
+test_merged() {
+	local root="${1}"
+	local dir1="${2}"
+	local dir2="${3}"
+	local inode1 inode2
+
+	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
+	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
+
+	test -z "${inode1}" || \
+		test "${inode1}" = "${inode2}" || \
+			printf '%s\n' "${dir1}"
+}
+
+test_merged "${root}" "/lib" "/usr/lib"
+test_merged "${root}" "/bin" "/usr/bin"
+test_merged "${root}" "/sbin" "/usr/sbin"
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 4/13
#8 lore raw

Re: [Buildroot] [PATCH 04/13] support/scripts: comonalise checking merged status

Quoted 9 lines · Yann E. MORIN

Rather than repeat the same canned sequence over and over again, move it to a function that we can reuse as many times as needed. This will come handy when we later need to check merged sbin.

Switch to using bash as it allows for nicer functions (local variables), but we anyway require it globally already so that's not an additional dependency.

Quoted 60 lines
---
  support/scripts/check-merged-usr.sh | 46 ++++++++++++++++-------------
  1 file changed, 26 insertions(+), 20 deletions(-)
support/scripts/check-merged-usr.sh +16 -20
index 433857cd8c..ed0c58e9b7 100755
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
  #
  # Check if a given custom skeleton or overlay complies to the merged /usr
  # requirements:
@@ -10,30 +10,36 @@
  # /usr/lib/
  # /usr/sbin/
  #
-# Output: the list of non-compliant paths (empty if compliant).
+# Input:
+#   $1:     the root directory (skeleton, overlay) to check
+# Output:
+#   stdout: the list of non-compliant paths (empty if compliant).
  #
 
+# The directory to check for merged-usr
+root="${1}"
+
  # 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
-# all of them.
+# each of them.
  #
-lib_inode=$(stat -c '%i' "${1}/lib/." 2>/dev/null)
-bin_inode=$(stat -c '%i' "${1}/bin/." 2>/dev/null)
-sbin_inode=$(stat -c '%i' "${1}/sbin/." 2>/dev/null)
-usr_lib_inode=$(stat -c '%i' "${1}/usr/lib/." 2>/dev/null)
-usr_bin_inode=$(stat -c '%i' "${1}/usr/bin/." 2>/dev/null)
-usr_sbin_inode=$(stat -c '%i' "${1}/usr/sbin/." 2>/dev/null)
 
-not_merged_dirs=""
-test -z "$lib_inode" || \
-	test "$lib_inode" = "$usr_lib_inode" || \
-		not_merged_dirs="/lib"
-test -z "$bin_inode" || \
-	test "$bin_inode" = "$usr_bin_inode" || \
-		not_merged_dirs="$not_merged_dirs /bin"
-test -z "$sbin_inode" || \
-	test "$sbin_inode" = "$usr_sbin_inode" || \
-		not_merged_dirs="$not_merged_dirs /sbin"
-echo "${not_merged_dirs# }"
+test_merged() {
+	local root="${1}"
+	local dir1="${2}"
+	local dir2="${3}"
+	local inode1 inode2
+
+	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"

support/scripts/check-merged-usr.sh line 45

Quoted 10 lines
support/scripts/check-merged-usr.sh +10 -0
+	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
+
+	test -z "${inode1}" || \
+		test "${inode1}" = "${inode2}" || \
+			printf '%s\n' "${dir1}"
+}
+
+test_merged "${root}" "/lib" "/usr/lib"
+test_merged "${root}" "/bin" "/usr/bin"
+test_merged "${root}" "/sbin" "/usr/sbin"

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#9 lore raw

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

In reply to Yann E. MORIN

Currently, we accept that the merged usr is bqckward, 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, and the latters are actual directories.

Fix the check-merged-usr script accordingly; extend the hedaing-comment to be more explicit (and drop '/' as there is nothing to say about it).

---
 support/scripts/check-merged-usr.sh | 34 +++++++++++++++++------------
 1 file changed, 20 insertions(+), 14 deletions(-)
support/scripts/check-merged-usr.sh +20 -14
index ed0c58e9b7..9459d975fe 100755
@@ -2,13 +2,12 @@
 #
 # 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 symlink to usr/bin
+#   /lib            missing or symlink to usr/lib
+#   /sbin           missing or symlink to usr/sbin
+#   /usr/bin/       directory
+#   /usr/lib/       directory
+#   /usr/sbin/      directory
 #
 # Input:
 #   $1:     the root directory (skeleton, overlay) to check
@@ -21,10 +20,8 @@ root="${1}"
 
 # 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.
-#
+# append '/.' to be sure we get the target directory. To check whether
+# the symlink is backward, we need to append '/.' to each tested entry.
 
 test_merged() {
 	local root="${1}"
@@ -32,12 +29,21 @@ test_merged() {
 	local dir2="${3}"
 	local inode1 inode2
 
+	# OK if missing first entry and second entry is an actual directory
+	test -e "${root}${dir1}" || { test -d "${root}${dir2}" && return; }
+
 	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
 	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
 
-	test -z "${inode1}" || \
-		test "${inode1}" = "${inode2}" || \
-			printf '%s\n' "${dir1}"
+	# OK if first entry is a symlink, second entry is a directoy, and
+	# both have the same inode (once dereferenced)
+	test -L "${root}${dir1}" \
+	&& test -d "${root}${dir2}" \
+	&& test "${inode1}" = "${inode2}" \
+	&& return
+
+	# Otherwise, this directory is not merged
+	printf '%s\n' "${dir1}"
 }
 
 test_merged "${root}" "/lib" "/usr/lib"
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#10 lore raw

Re: [Buildroot] [PATCH 05/13] support/scripts: fix and restrict conditions to accept merged dirs

All,

On 2025-05-14 18:58 +0200, Yann E. MORIN spake thusly:

Quoted 9 lines

Currently, we accept that the merged usr is bqckward, 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, and the latters are actual directories.

[--SNIP--]

Quoted 12 lines
support/scripts/check-merged-usr.sh +3 -2
@@ -32,12 +29,21 @@ test_merged() {
 	local dir2="${3}"
 	local inode1 inode2
 
+	# OK if missing first entry and second entry is an actual directory
+	test -e "${root}${dir1}" || { test -d "${root}${dir2}" && return; }
+
 	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
 	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
 
-	test -z "${inode1}" || \
-		test "${inode1}" = "${inode2}" || \

support/scripts/check-merged-usr.sh test_merged() { · line 46

Quoted 10 lines
support/scripts/check-merged-usr.sh +9 -1
-			printf '%s\n' "${dir1}"
+	# OK if first entry is a symlink, second entry is a directoy, and
+	# both have the same inode (once dereferenced)
+	test -L "${root}${dir1}" \
+	&& test -d "${root}${dir2}" \
+	&& test "${inode1}" = "${inode2}" \
+	&& return
+
+	# Otherwise, this directory is not merged
+	printf '%s\n' "${dir1}"

This new test is still quite complex, and is in fact still wrong in weird cases. For example, with BASE a custom skeleton or rootfs overlay, if BASE/sbin and BASE/usr/sbin ar absolute symlinks to /usr/sbin, the test above will accept BASE as being properly merged, while it is in fact broken.

I'm preparing a v2 which greatly simplifies the test, and makes it cover more (all, hopefully) cases.

Regards,
Yann E. MORIN.

Quoted 6 lines
support/scripts/check-merged-usr.sh +0 -0
 }
 
 test_merged "${root}" "/lib" "/usr/lib"
Signature · 1 line
2.47.0
Signature · 10 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#11 lore raw

Re: [Buildroot] [PATCH 05/13] support/scripts: fix and restrict conditions to accept merged dirs

Quoted 42 lines · Yann E. MORIN

All,

On 2025-05-14 18:58 +0200, Yann E. MORIN spake thusly:

Quoted 9 lines

Currently, we accept that the merged usr is bqckward, 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, and the latters are actual directories.

[--SNIP--]

Quoted 12 lines
support/scripts/check-merged-usr.sh +3 -2
@@ -32,12 +29,21 @@ test_merged() {
  	local dir2="${3}"
  	local inode1 inode2
 
+	# OK if missing first entry and second entry is an actual directory
+	test -e "${root}${dir1}" || { test -d "${root}${dir2}" && return; }
+
  	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
  	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
 
-	test -z "${inode1}" || \
-		test "${inode1}" = "${inode2}" || \

support/scripts/check-merged-usr.sh test_merged() { · line 46

Quoted 10 lines
support/scripts/check-merged-usr.sh +9 -1
-			printf '%s\n' "${dir1}"
+	# OK if first entry is a symlink, second entry is a directoy, and
+	# both have the same inode (once dereferenced)
+	test -L "${root}${dir1}" \
+	&& test -d "${root}${dir2}" \
+	&& test "${inode1}" = "${inode2}" \
+	&& return
+
+	# Otherwise, this directory is not merged
+	printf '%s\n' "${dir1}"

This new test is still quite complex, and is in fact still wrong in weird cases. For example, with BASE a custom skeleton or rootfs overlay, if BASE/sbin and BASE/usr/sbin ar absolute symlinks to /usr/sbin, the test above will accept BASE as being properly merged, while it is in fact broken.

Quoted 2 lines

I'm preparing a v2 which greatly simplifies the test, and makes it cover more (all, hopefully) cases.

With that in mind, I'll quickly review the series now and mark it as Changes
Requested in patchwork, OK?

Thanks,
Arnout

Quoted 11 lines

Regards,
Yann E. MORIN.

Quoted 6 lines
support/scripts/check-merged-usr.sh +0 -0
  }
 
  test_merged "${root}" "/lib" "/usr/lib"
Signature · 1 line
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#12 lore raw

Re: [Buildroot] [PATCH 05/13] support/scripts: fix and restrict conditions to accept merged dirs

In reply to Yann E. MORIN
Quoted 42 lines · Yann E. MORIN

All,

On 2025-05-14 18:58 +0200, Yann E. MORIN spake thusly:

Quoted 9 lines

Currently, we accept that the merged usr is bqckward, 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, and the latters are actual directories.

[--SNIP--]

Quoted 12 lines
support/scripts/check-merged-usr.sh +3 -2
@@ -32,12 +29,21 @@ test_merged() {
  	local dir2="${3}"
  	local inode1 inode2
 
+	# OK if missing first entry and second entry is an actual directory
+	test -e "${root}${dir1}" || { test -d "${root}${dir2}" && return; }
+
  	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
  	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
 
-	test -z "${inode1}" || \
-		test "${inode1}" = "${inode2}" || \

support/scripts/check-merged-usr.sh test_merged() { · line 46

Quoted 10 lines
support/scripts/check-merged-usr.sh +9 -1
-			printf '%s\n' "${dir1}"
+	# OK if first entry is a symlink, second entry is a directoy, and
+	# both have the same inode (once dereferenced)
+	test -L "${root}${dir1}" \
+	&& test -d "${root}${dir2}" \
+	&& test "${inode1}" = "${inode2}" \
+	&& return
+
+	# Otherwise, this directory is not merged
+	printf '%s\n' "${dir1}"

This new test is still quite complex, and is in fact still wrong in weird cases. For example, with BASE a custom skeleton or rootfs overlay, if BASE/sbin and BASE/usr/sbin ar absolute symlinks to /usr/sbin, the test above will accept BASE as being properly merged, while it is in fact broken.

Quoted 2 lines

I'm preparing a v2 which greatly simplifies the test, and makes it cover more (all, hopefully) cases.

I guess the test should simply be:

test -L "${root}${dir1}" \
&& test -d "${root}${dir2}" \
&& test "$(readlink "${root}${dir1}")" = "${dir2}" \
&& return

(which is not actually simpler... except that you can remove all the stat stuff)

Regards,
Arnout

Quoted 11 lines

Regards,
Yann E. MORIN.

Quoted 6 lines
support/scripts/check-merged-usr.sh +0 -0
  }
 
  test_merged "${root}" "/lib" "/usr/lib"
Signature · 1 line
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#13 lore raw

Re: [Buildroot] [PATCH 05/13] support/scripts: fix and restrict conditions to accept merged dirs

Arnout, All,

On 2025-05-17 12:13 +0200, Arnout Vandecappelle spake thusly:

Quoted 39 lines · Yann E. MORIN
Quoted 38 lines

On 2025-05-14 18:58 +0200, Yann E. MORIN spake thusly:

Quoted 9 lines

Currently, we accept that the merged usr is bqckward, 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, and the latters are actual directories.

[--SNIP--]

Quoted 10 lines
support/scripts/check-merged-usr.sh +3 -2
@@ -32,12 +29,21 @@ test_merged() {
  	local dir2="${3}"
  	local inode1 inode2
+	# OK if missing first entry and second entry is an actual directory
+	test -e "${root}${dir1}" || { test -d "${root}${dir2}" && return; }
+
  	inode1="$(stat -c '%i' "${root}${dir1}/." 2>/dev/null)"
  	inode2="$(stat -c '%i' "${root}${dir2}/." 2>/dev/null)"
-	test -z "${inode1}" || \
-		test "${inode1}" = "${inode2}" || \

support/scripts/check-merged-usr.sh test_merged() { · line 44

Quoted 10 lines
support/scripts/check-merged-usr.sh +9 -1
-			printf '%s\n' "${dir1}"
+	# OK if first entry is a symlink, second entry is a directoy, and
+	# both have the same inode (once dereferenced)
+	test -L "${root}${dir1}" \
+	&& test -d "${root}${dir2}" \
+	&& test "${inode1}" = "${inode2}" \
+	&& return
+
+	# Otherwise, this directory is not merged
+	printf '%s\n' "${dir1}"

This new test is still quite complex, and is in fact still wrong in weird cases. For example, with BASE a custom skeleton or rootfs overlay, if BASE/sbin and BASE/usr/sbin ar absolute symlinks to /usr/sbin, the test above will accept BASE as being properly merged, while it is in fact broken.

Quoted 8 lines
Quoted 2 lines

I'm preparing a v2 which greatly simplifies the test, and makes it cover more (all, hopefully) cases.

I guess the test should simply be:

test -L "${root}${dir1}" \
&& test -d "${root}${dir2}" \
&& test "$(readlink "${root}${dir1}")" = "${dir2}" \

This test for the target of the symlink is wrong: if dir1 is bin, and points to /usr/bin, then this is wrong: we really want relative symlinks.

Quoted 3 lines

&& return

(which is not actually simpler... except that you can remove all the stat stuff)

I'm going with an even simpler, more strict solution, that simply implements word-for-word our requirements. Indeed, I just drop all the stat stuff that could get things wrong.

Regards,
Yann E. MORIN.

Signature · 10 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#14 lore raw

PATCH 6/13 support/scripts: rename check-merged-usr.sh

In reply to Yann E. MORIN

We're going to need it to check merged-bin, so the naming would be misleading as it would no longer be just about merged-usr.

Also drop the extension, it's useless.

---
 Makefile                                              | 2 +-
 package/skeleton-custom/skeleton-custom.mk            | 2 +-
 support/scripts/{check-merged-usr.sh => check-merged} | 0
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename support/scripts/{check-merged-usr.sh => check-merged} (100%)
Makefile +1 -1
index 411e1de515..a5aa1c6553 100644
@@ -784,7 +784,7 @@ ifeq ($(BR2_ROOTFS_MERGED_USR),y)
 
 	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
 		@$(call MESSAGE,"Sanity check in overlay $(d)")$(sep) \
-		$(Q)not_merged_dirs="$$(support/scripts/check-merged-usr.sh $(d))"; \
+		$(Q)not_merged_dirs="$$(support/scripts/check-merged $(d))"; \
 		test -n "$$not_merged_dirs" && { \
 			echo "ERROR: The overlay in $(d) is not" \
 				"using a merged /usr for the following directories:" \
package/skeleton-custom/skeleton-custom.mk +1 -1
index b05c834b94..7d64959711 100644
@@ -27,7 +27,7 @@ endif
 # counterparts are appropriately setup as symlinks ones to the others.
 ifeq ($(BR2_ROOTFS_MERGED_USR),y)
 SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
-	$(shell support/scripts/check-merged-usr.sh $(SKELETON_CUSTOM_PATH))
+	$(shell support/scripts/check-merged $(SKELETON_CUSTOM_PATH))
 endif # merged /usr
 
 ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
support/scripts/check-merged renamed from support/scripts/check-merged-usr.sh +0 -0
similarity index 100%
rename from support/scripts/check-merged-usr.sh
rename to support/scripts/check-merged
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 6/13
#15 lore raw

Re: [Buildroot] [PATCH 06/13] support/scripts: rename check-merged-usr.sh

Quoted 6 lines · Yann E. MORIN

We're going to need it to check merged-bin, so the naming would be misleading as it would no longer be just about merged-usr.

Also drop the extension, it's useless.

support/scripts/check-merged

Quoted 37 lines
---
  Makefile                                              | 2 +-
  package/skeleton-custom/skeleton-custom.mk            | 2 +-
  support/scripts/{check-merged-usr.sh => check-merged} | 0
  3 files changed, 2 insertions(+), 2 deletions(-)

rename support/scripts/{check-merged-usr.sh => check-merged} (100%)

Makefile +1 -1
index 411e1de515..a5aa1c6553 100644
@@ -784,7 +784,7 @@ ifeq ($(BR2_ROOTFS_MERGED_USR),y)
 
  	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
  		@$(call MESSAGE,"Sanity check in overlay $(d)")$(sep) \
-		$(Q)not_merged_dirs="$$(support/scripts/check-merged-usr.sh $(d))"; \
+		$(Q)not_merged_dirs="$$(support/scripts/check-merged $(d))"; \
  		test -n "$$not_merged_dirs" && { \
  			echo "ERROR: The overlay in $(d) is not" \
  				"using a merged /usr for the following directories:" \
package/skeleton-custom/skeleton-custom.mk +1 -1
index b05c834b94..7d64959711 100644
@@ -27,7 +27,7 @@ endif
  # counterparts are appropriately setup as symlinks ones to the others.
  ifeq ($(BR2_ROOTFS_MERGED_USR),y)
  SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
-	$(shell support/scripts/check-merged-usr.sh $(SKELETON_CUSTOM_PATH))
+	$(shell support/scripts/check-merged $(SKELETON_CUSTOM_PATH))
  endif # merged /usr
 
  ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
support/scripts/check-merged renamed from support/scripts/check-merged-usr.sh +0 -0
similarity index 100%
rename from support/scripts/check-merged-usr.sh
rename to support/scripts/check-merged

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#16 lore raw

PATCH 7/13 support/scripts; teach check-merged what to check

In reply to Yann E. MORIN
---
 Makefile                                   | 10 +++++-----
 package/skeleton-custom/skeleton-custom.mk |  7 ++++---
 support/scripts/check-merged               | 19 +++++++++++++++----
 3 files changed, 24 insertions(+), 12 deletions(-)
Makefile +5 -5
index a5aa1c6553..1248dfb9e0 100644
@@ -780,11 +780,13 @@ endif
 
 # For a merged /usr, ensure that /lib, /bin and /sbin and their /usr
 # counterparts are appropriately setup as symlinks ones to the others.
-ifeq ($(BR2_ROOTFS_MERGED_USR),y)
-
 	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
 		@$(call MESSAGE,"Sanity check in overlay $(d)")$(sep) \
-		$(Q)not_merged_dirs="$$(support/scripts/check-merged $(d))"; \
+		$(Q)not_merged_dirs="$$(\
+			support/scripts/check-merged \
+			$(d) \
+			$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+		)"; \
 		test -n "$$not_merged_dirs" && { \
 			echo "ERROR: The overlay in $(d) is not" \
 				"using a merged /usr for the following directories:" \
@@ -792,8 +794,6 @@ ifeq ($(BR2_ROOTFS_MERGED_USR),y)
 			exit 1; \
 		} || true$(sep))
 
-endif # merged /usr
-
 	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
 		@$(call MESSAGE,"Copying overlay $(d)")$(sep) \
 		$(Q)$(call SYSTEM_RSYNC,$(d),$(TARGET_DIR))$(sep))
package/skeleton-custom/skeleton-custom.mk +4 -3
index 7d64959711..e583d2d731 100644
@@ -25,10 +25,11 @@ endif
 
 # For a merged /usr, ensure that /lib, /bin and /sbin and their /usr
 # counterparts are appropriately setup as symlinks ones to the others.
-ifeq ($(BR2_ROOTFS_MERGED_USR),y)
 SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
-	$(shell support/scripts/check-merged $(SKELETON_CUSTOM_PATH))
-endif # merged /usr
+	$(shell support/scripts/check-merged \
+		$(SKELETON_CUSTOM_PATH) \
+		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+	)
 
 ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
 ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
support/scripts/check-merged +15 -4
index 9459d975fe..7fea4e1dea 100755
@@ -11,12 +11,14 @@
 #
 # Input:
 #   $1:     the root directory (skeleton, overlay) to check
+#   $*:     the list of merged checks to perform: merged-usr
 # Output:
 #   stdout: the list of non-compliant paths (empty if compliant).
 #
 
-# The directory to check for merged-usr
+# The directory to check for $what
 root="${1}"
+shift
 
 # 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
@@ -46,6 +48,15 @@ test_merged() {
 	printf '%s\n' "${dir1}"
 }
 
-test_merged "${root}" "/lib" "/usr/lib"
-test_merged "${root}" "/bin" "/usr/bin"
-test_merged "${root}" "/sbin" "/usr/sbin"
+for what; do
+	case "${what}" in
+		(merged-usr)
+			test_merged "${root}" "/lib" "/usr/lib"
+			test_merged "${root}" "/bin" "/usr/bin"
+			test_merged "${root}" "/sbin" "/usr/sbin"
+		;;
+		(*)
+			printf 'Error: unknown type of test %s\n' "${what}"
+		;;
+	esac
+done
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#17 lore raw

Re: [Buildroot] [PATCH 07/13] support/scripts; teach check-merged what to check

Quoted 43 lines · Yann E. MORIN
---
  Makefile                                   | 10 +++++-----
  package/skeleton-custom/skeleton-custom.mk |  7 ++++---
  support/scripts/check-merged               | 19 +++++++++++++++----
  3 files changed, 24 insertions(+), 12 deletions(-)
Makefile +5 -5
index a5aa1c6553..1248dfb9e0 100644
@@ -780,11 +780,13 @@ endif
 
  # For a merged /usr, ensure that /lib, /bin and /sbin and their /usr
  # counterparts are appropriately setup as symlinks ones to the others.
-ifeq ($(BR2_ROOTFS_MERGED_USR),y)
-
  	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
  		@$(call MESSAGE,"Sanity check in overlay $(d)")$(sep) \
-		$(Q)not_merged_dirs="$$(support/scripts/check-merged $(d))"; \
+		$(Q)not_merged_dirs="$$(\
+			support/scripts/check-merged \
+			$(d) \
+			$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+		)"; \
  		test -n "$$not_merged_dirs" && { \
  			echo "ERROR: The overlay in $(d) is not" \
  				"using a merged /usr for the following directories:" \
@@ -792,8 +794,6 @@ ifeq ($(BR2_ROOTFS_MERGED_USR),y)
  			exit 1; \
  		} || true$(sep))
 
-endif # merged /usr
-
  	$(foreach d, $(call qstrip,$(BR2_ROOTFS_OVERLAY)), \
  		@$(call MESSAGE,"Copying overlay $(d)")$(sep) \
  		$(Q)$(call SYSTEM_RSYNC,$(d),$(TARGET_DIR))$(sep))
package/skeleton-custom/skeleton-custom.mk +0 -0
index 7d64959711..e583d2d731 100644
@@ -25,10 +25,11 @@ endif
 

package/skeleton-custom/skeleton-custom.mk endif · line 32

Quoted 10 lines
package/skeleton-custom/skeleton-custom.mk +4 -3
  # For a merged /usr, ensure that /lib, /bin and /sbin and their /usr
  # counterparts are appropriately setup as symlinks ones to the others.
-ifeq ($(BR2_ROOTFS_MERGED_USR),y)
  SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
-	$(shell support/scripts/check-merged $(SKELETON_CUSTOM_PATH))
-endif # merged /usr
+	$(shell support/scripts/check-merged \
+		$(SKELETON_CUSTOM_PATH) \
+		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+	)

While you're anyway working on this: I think there's little point of doing
this as a "preliminary" check, I think it's fine to do this check while "building" the custom skeleton (i.e. in SKELETON_CUSTOM_INSTALL_TARGET_CMDS).

That would allow us to move the error message to the check-merged script
itself, and let it return 1 in case it's not properly merged. And with that, both instances can simply call the script without capturing its output. It's going to save +-10 lines of code and make things easier to understand IMHO.

support/scripts/check-merged line 14

Quoted 12 lines
package/skeleton-custom/skeleton-custom.mk +0 -0
  ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
  ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
support/scripts/check-merged +1 -0
index 9459d975fe..7fea4e1dea 100755
@@ -11,12 +11,14 @@
  #
  # Input:
  #   $1:     the root directory (skeleton, overlay) to check
+#   $*:     the list of merged checks to perform: merged-usr

If you make this an option (i.e. --merged-usr), then we can replace $1 with a
$* that covers all directories, and we can get rid of the foreach in Makefile's check of the overlays, and that code could simplify to:

	@$(call MESSAGE,"Sanity check in overlays)
	support/scripts/check-merged \
		$(if $(BR2_ROOTFS_MERGED_USR),--merged-usr) \
		$(call qstrip,$(BR2_ROOTFS_OVERLAY))

Of course, there's a risk that I'm overengineering things, so feel free to
ignore my suggestions.

Regards,
Arnout

Quoted 20 lines
support/scripts/check-merged +4 -4
  # Output:
  #   stdout: the list of non-compliant paths (empty if compliant).
  #
 
-# The directory to check for merged-usr
+# The directory to check for $what
  root="${1}"
+shift
 
  # 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
@@ -46,6 +48,15 @@ test_merged() {
  	printf '%s\n' "${dir1}"
  }
 
-test_merged "${root}" "/lib" "/usr/lib"
-test_merged "${root}" "/bin" "/usr/bin"
-test_merged "${root}" "/sbin" "/usr/sbin"
+for what; do
+	case "${what}" in

support/scripts/check-merged test_merged() { · line 62

Quoted 10 lines
support/scripts/check-merged +10 -0
+		(merged-usr)
+			test_merged "${root}" "/lib" "/usr/lib"
+			test_merged "${root}" "/bin" "/usr/bin"
+			test_merged "${root}" "/sbin" "/usr/sbin"
+		;;
+		(*)
+			printf 'Error: unknown type of test %s\n' "${what}"
+		;;
+	esac
+done

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#18 lore raw

Re: [Buildroot] [PATCH 07/13] support/scripts; teach check-merged what to check

Arnout, All,

On 2025-05-17 12:24 +0200, Arnout Vandecappelle spake thusly:

Quoted 2 lines · Yann E. MORIN
Quoted 1 line

[--SNIP--]

Quoted 21 lines
Quoted 5 lines
package/skeleton-custom/skeleton-custom.mk +0 -0
index 7d64959711..e583d2d731 100644

package/skeleton-custom/skeleton-custom.mk endif · line 31

Quoted 10 lines
package/skeleton-custom/skeleton-custom.mk +4 -3
@@ -25,10 +25,11 @@ endif
  # For a merged /usr, ensure that /lib, /bin and /sbin and their /usr
  # counterparts are appropriately setup as symlinks ones to the others.
-ifeq ($(BR2_ROOTFS_MERGED_USR),y)
  SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
-	$(shell support/scripts/check-merged $(SKELETON_CUSTOM_PATH))
-endif # merged /usr
+	$(shell support/scripts/check-merged \
+		$(SKELETON_CUSTOM_PATH) \
+		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+	)

While you're anyway working on this: I think there's little point of doing
this as a "preliminary" check, I think it's fine to do this check while "building" the custom skeleton (i.e. in SKELETON_CUSTOM_INSTALL_TARGET_CMDS).

Quoted 4 lines

That would allow us to move the error message to the check-merged script
itself, and let it return 1 in case it's not properly merged. And with that, both instances can simply call the script without capturing its output. It's going to save +-10 lines of code and make things easier to understand IMHO.

I was considering something in that spirit, so your suggesting it just confirms that it is a good idea, and I'll look into doing that.

Quoted 16 lines

support/scripts/check-merged line 14

Quoted 11 lines
package/skeleton-custom/skeleton-custom.mk +0 -0
  ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
  ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
support/scripts/check-merged +1 -0
index 9459d975fe..7fea4e1dea 100755
@@ -11,12 +11,14 @@
  #
  # Input:
  #   $1:     the root directory (skeleton, overlay) to check
+#   $*:     the list of merged checks to perform: merged-usr

If you make this an option (i.e. --merged-usr), then we can replace $1 with
a $* that covers all directories, and we can get rid of the foreach in Makefile's check of the overlays, and that code could simplify to:

Quoted 7 lines
	@$(call MESSAGE,"Sanity check in overlays)
	support/scripts/check-merged \
		$(if $(BR2_ROOTFS_MERGED_USR),--merged-usr) \
		$(call qstrip,$(BR2_ROOTFS_OVERLAY))

Of course, there's a risk that I'm overengineering things, so feel free to
ignore my suggestions.

I also like it a bit better, indeed. Let's see what I can come up with...

Thanks.

Regards,
Yann E. MORIN.

Signature · 10 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#19 lore raw

PATCH 8/13 system: add support for merged /usr/sbin (aka merged-bin)

In reply to Yann E. MORIN

Starting with version 256 [0], systemd warns when /usr/bin and /usr/sbin are different directories; in the future, it may even refuse to boot in such a situation.

Add support for merged-bin, not unlike we have support for merged-usr; we also make merged-bin a sub-case of merged-usr (i.e. it is not possible to do merged-bin without merged-usr).

[0] https://github.com/systemd/systemd/blob/v256/NEWS#L265

---
 Makefile                                   |  1 +
 package/skeleton-custom/skeleton-custom.mk |  3 ++-
 support/scripts/check-merged               |  5 ++++-
 system/Config.in                           | 11 +++++++++++
 system/skeleton/usr/sbin/.empty            |  0
 system/system.mk                           | 11 +++++++++++
 6 files changed, 29 insertions(+), 2 deletions(-)
 delete mode 100644 system/skeleton/usr/sbin/.empty
Makefile +1 -0
index 1248dfb9e0..477179dd64 100644
@@ -786,6 +786,7 @@ endif
 			support/scripts/check-merged \
 			$(d) \
 			$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+			$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
 		)"; \
 		test -n "$$not_merged_dirs" && { \
 			echo "ERROR: The overlay in $(d) is not" \
package/skeleton-custom/skeleton-custom.mk +2 -1
index e583d2d731..7f9f10b81d 100644
@@ -29,12 +29,13 @@ SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
 	$(shell support/scripts/check-merged \
 		$(SKELETON_CUSTOM_PATH) \
 		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+		$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
 	)
 
 ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
 ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
 $(error The custom skeleton in $(SKELETON_CUSTOM_PATH) is not \
-	using a merged /usr for the following directories: \
+	using a merged structuren for the following directories: \
 	$(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS))
 endif
 endif
support/scripts/check-merged +4 -1
index 7fea4e1dea..0e51c032c5 100755
@@ -11,7 +11,7 @@
 #
 # Input:
 #   $1:     the root directory (skeleton, overlay) to check
-#   $*:     the list of merged checks to perform: merged-usr
+#   $*:     the list of merged checks to perform: merged-usr, merged-bin
 # Output:
 #   stdout: the list of non-compliant paths (empty if compliant).
 #
@@ -55,6 +55,9 @@ for what; do
 			test_merged "${root}" "/bin" "/usr/bin"
 			test_merged "${root}" "/sbin" "/usr/sbin"
 		;;
+		(merged-bin)
+			test_merged "${root}" "/usr/sbin" "/usr/bin"
+		;;
 		(*)
 			printf 'Error: unknown type of test %s\n' "${what}"
 		;;
system/Config.in +11 -0
index 2f42e5ddf9..5007f101e2 100644
@@ -342,6 +342,16 @@ config BR2_ROOTFS_MERGED_USR
 	  symlinks to their counterparts in /usr. In this case, /usr can
 	  not be a separate filesystem.
 
+config BR2_ROOTFS_MERGED_SBIN
+	bool "Merged /usr/sbin"
+	depends on BR2_ROOTFS_MERGED_USR
+	help
+	  If you say 'n' here, then /usr/bin and /usr/sbin will be
+	  separate directories; this is the historical UNIX way.
+
+	  If you say 'y' here, then /usr/sbin will be a relative
+	  symlink to /usr/bin.
+
 if BR2_ROOTFS_SKELETON_DEFAULT
 
 config BR2_TARGET_ENABLE_ROOT_LOGIN
@@ -528,6 +538,7 @@ endif # BR2_ROOTFS_SKELETON_DEFAULT
 
 config BR2_SYSTEM_DEFAULT_PATH
 	string "Set the system's default PATH"
+	default "/usr/bin" if BR2_ROOTFS_MERGED_SBIN
 	default "/usr/bin:/usr/sbin" if BR2_ROOTFS_MERGED_USR
 	default "/bin:/sbin:/usr/bin:/usr/sbin"
 	help
system/skeleton/usr/sbin/.empty deleted +0 -0
deleted file mode 100644
index e69de29bb2..0000000000
system/system.mk +11 -0
index 8fe2c138b0..530b26c162 100644
@@ -34,16 +34,27 @@
 
 # This function handles the merged or non-merged /usr cases
 ifeq ($(BR2_ROOTFS_MERGED_USR),y)
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),y)
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	ln -snf bin $(1)/usr/sbin
+endef
+else
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
+endef
+endif
 define SYSTEM_USR_SYMLINKS_OR_DIRS
 	ln -snf usr/bin $(1)/bin
 	ln -snf usr/sbin $(1)/sbin
 	ln -snf usr/lib $(1)/lib
+	$(SYSTEM_SBIN_SYMLINKS_OR_DIRS)
 endef
 else
 define SYSTEM_USR_SYMLINKS_OR_DIRS
 	$(INSTALL) -d -m 0755 $(1)/bin
 	$(INSTALL) -d -m 0755 $(1)/sbin
 	$(INSTALL) -d -m 0755 $(1)/lib
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
 endef
 endif
 
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 8/13
#20 lore raw

Re: [Buildroot] [PATCH 08/13] system: add support for merged /usr/sbin (aka merged-bin)

Quoted 11 lines · Yann E. MORIN

Starting with version 256 [0], systemd warns when /usr/bin and /usr/sbin are different directories; in the future, it may even refuse to boot in such a situation.

Add support for merged-bin, not unlike we have support for merged-usr; we also make merged-bin a sub-case of merged-usr (i.e. it is not possible to do merged-bin without merged-usr).

[0] https://github.com/systemd/systemd/blob/v256/NEWS#L265

I don't really like how complicated the logic in system.mk is becoming, but I
don't have better ideas either.

Regards,
Arnout

Quoted 118 lines
---
  Makefile                                   |  1 +
  package/skeleton-custom/skeleton-custom.mk |  3 ++-
  support/scripts/check-merged               |  5 ++++-
  system/Config.in                           | 11 +++++++++++
  system/skeleton/usr/sbin/.empty            |  0
  system/system.mk                           | 11 +++++++++++
  6 files changed, 29 insertions(+), 2 deletions(-)

delete mode 100644 system/skeleton/usr/sbin/.empty

Makefile +1 -0
index 1248dfb9e0..477179dd64 100644
@@ -786,6 +786,7 @@ endif
  			support/scripts/check-merged \
  			$(d) \
  			$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+			$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
  		)"; \
  		test -n "$$not_merged_dirs" && { \
  			echo "ERROR: The overlay in $(d) is not" \
package/skeleton-custom/skeleton-custom.mk +2 -1
index e583d2d731..7f9f10b81d 100644
@@ -29,12 +29,13 @@ SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
  	$(shell support/scripts/check-merged \
  		$(SKELETON_CUSTOM_PATH) \
  		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+		$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
  	)
 
  ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
  ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
  $(error The custom skeleton in $(SKELETON_CUSTOM_PATH) is not \
-	using a merged /usr for the following directories: \
+	using a merged structuren for the following directories: \
  	$(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS))
  endif
  endif
support/scripts/check-merged +4 -1
index 7fea4e1dea..0e51c032c5 100755
@@ -11,7 +11,7 @@
  #
  # Input:
  #   $1:     the root directory (skeleton, overlay) to check
-#   $*:     the list of merged checks to perform: merged-usr
+#   $*:     the list of merged checks to perform: merged-usr, merged-bin
  # Output:
  #   stdout: the list of non-compliant paths (empty if compliant).
  #
@@ -55,6 +55,9 @@ for what; do
  			test_merged "${root}" "/bin" "/usr/bin"
  			test_merged "${root}" "/sbin" "/usr/sbin"
  		;;
+		(merged-bin)
+			test_merged "${root}" "/usr/sbin" "/usr/bin"
+		;;
  		(*)
  			printf 'Error: unknown type of test %s\n' "${what}"
  		;;
system/Config.in +11 -0
index 2f42e5ddf9..5007f101e2 100644
@@ -342,6 +342,16 @@ config BR2_ROOTFS_MERGED_USR
  	  symlinks to their counterparts in /usr. In this case, /usr can
  	  not be a separate filesystem.
 
+config BR2_ROOTFS_MERGED_SBIN
+	bool "Merged /usr/sbin"
+	depends on BR2_ROOTFS_MERGED_USR
+	help
+	  If you say 'n' here, then /usr/bin and /usr/sbin will be
+	  separate directories; this is the historical UNIX way.
+
+	  If you say 'y' here, then /usr/sbin will be a relative
+	  symlink to /usr/bin.
+
  if BR2_ROOTFS_SKELETON_DEFAULT
 
  config BR2_TARGET_ENABLE_ROOT_LOGIN
@@ -528,6 +538,7 @@ endif # BR2_ROOTFS_SKELETON_DEFAULT
 
  config BR2_SYSTEM_DEFAULT_PATH
  	string "Set the system's default PATH"
+	default "/usr/bin" if BR2_ROOTFS_MERGED_SBIN
  	default "/usr/bin:/usr/sbin" if BR2_ROOTFS_MERGED_USR
  	default "/bin:/sbin:/usr/bin:/usr/sbin"
  	help
system/skeleton/usr/sbin/.empty deleted +0 -0
deleted file mode 100644
index e69de29bb2..0000000000
system/system.mk +10 -0
index 8fe2c138b0..530b26c162 100644
@@ -34,16 +34,27 @@
 
  # This function handles the merged or non-merged /usr cases
  ifeq ($(BR2_ROOTFS_MERGED_USR),y)
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),y)
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	ln -snf bin $(1)/usr/sbin
+endef
+else
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
+endef
+endif
  define SYSTEM_USR_SYMLINKS_OR_DIRS
  	ln -snf usr/bin $(1)/bin
  	ln -snf usr/sbin $(1)/sbin
  	ln -snf usr/lib $(1)/lib
+	$(SYSTEM_SBIN_SYMLINKS_OR_DIRS)

system/system.mk line 60

Quoted 10 lines
system/system.mk +1 -0
  endef
  else
  define SYSTEM_USR_SYMLINKS_OR_DIRS
  	$(INSTALL) -d -m 0755 $(1)/bin
  	$(INSTALL) -d -m 0755 $(1)/sbin
  	$(INSTALL) -d -m 0755 $(1)/lib
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
  endef
  endif
 

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#21 lore raw

Re: [Buildroot] [PATCH 08/13] system: add support for merged /usr/sbin (aka merged-bin)

In reply to Yann E. MORIN

Hello!

Quoted 39 lines · Yann E. MORIN

Starting with version 256 [0], systemd warns when /usr/bin and /usr/sbin are different directories; in the future, it may even refuse to boot in such a situation.

Add support for merged-bin, not unlike we have support for merged-usr; we also make merged-bin a sub-case of merged-usr (i.e. it is not possible to do merged-bin without merged-usr).

[0] https://github.com/systemd/systemd/blob/v256/NEWS#L265

---
 Makefile                                   |  1 +
 package/skeleton-custom/skeleton-custom.mk |  3 ++-
 support/scripts/check-merged               |  5 ++++-
 system/Config.in                           | 11 +++++++++++
 system/skeleton/usr/sbin/.empty            |  0
 system/system.mk                           | 11 +++++++++++
 6 files changed, 29 insertions(+), 2 deletions(-)
 delete mode 100644 system/skeleton/usr/sbin/.empty
Makefile +1 -0
index 1248dfb9e0..477179dd64 100644
@@ -786,6 +786,7 @@ endif
 			support/scripts/check-merged \
 			$(d) \
 			$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+			$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
 		)"; \
 		test -n "$$not_merged_dirs" && { \
 			echo "ERROR: The overlay in $(d) is not" \
package/skeleton-custom/skeleton-custom.mk +0 -0
index e583d2d731..7f9f10b81d 100644
@@ -29,12 +29,13 @@ SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \
 	$(shell support/scripts/check-merged \

package/skeleton-custom/skeleton-custom.mk SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \ · line 38

Quoted 10 lines
package/skeleton-custom/skeleton-custom.mk +2 -1
 		$(SKELETON_CUSTOM_PATH) \
 		$(if $(BR2_ROOTFS_MERGED_USR),merged-usr) \
+		$(if $(BR2_ROOTFS_MERGED_SBIN),merged-bin) \
 	)
 
 ifeq ($(BR2_PACKAGE_SKELETON_CUSTOM)$(BR_BUILDING),yy)
 ifneq ($(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS),)
 $(error The custom skeleton in $(SKELETON_CUSTOM_PATH) is not \
-	using a merged /usr for the following directories: \
+	using a merged structuren for the following directories: \

Small typo: s/structuren/structure/

Regards,

Edgar Bonet.

Quoted 80 lines
package/skeleton-custom/skeleton-custom.mk +0 -0
 	$(SKELETON_CUSTOM_NOT_MERGED_USR_DIRS))
 endif
 endif
support/scripts/check-merged +4 -1
index 7fea4e1dea..0e51c032c5 100755
@@ -11,7 +11,7 @@
 #
 # Input:
 #   $1:     the root directory (skeleton, overlay) to check
-#   $*:     the list of merged checks to perform: merged-usr
+#   $*:     the list of merged checks to perform: merged-usr, merged-bin
 # Output:
 #   stdout: the list of non-compliant paths (empty if compliant).
 #
@@ -55,6 +55,9 @@ for what; do
 			test_merged "${root}" "/bin" "/usr/bin"
 			test_merged "${root}" "/sbin" "/usr/sbin"
 		;;
+		(merged-bin)
+			test_merged "${root}" "/usr/sbin" "/usr/bin"
+		;;
 		(*)
 			printf 'Error: unknown type of test %s\n' "${what}"
 		;;
system/Config.in +11 -0
index 2f42e5ddf9..5007f101e2 100644
@@ -342,6 +342,16 @@ config BR2_ROOTFS_MERGED_USR
 	  symlinks to their counterparts in /usr. In this case, /usr can
 	  not be a separate filesystem.
 
+config BR2_ROOTFS_MERGED_SBIN
+	bool "Merged /usr/sbin"
+	depends on BR2_ROOTFS_MERGED_USR
+	help
+	  If you say 'n' here, then /usr/bin and /usr/sbin will be
+	  separate directories; this is the historical UNIX way.
+
+	  If you say 'y' here, then /usr/sbin will be a relative
+	  symlink to /usr/bin.
+
 if BR2_ROOTFS_SKELETON_DEFAULT
 
 config BR2_TARGET_ENABLE_ROOT_LOGIN
@@ -528,6 +538,7 @@ endif # BR2_ROOTFS_SKELETON_DEFAULT
 
 config BR2_SYSTEM_DEFAULT_PATH
 	string "Set the system's default PATH"
+	default "/usr/bin" if BR2_ROOTFS_MERGED_SBIN
 	default "/usr/bin:/usr/sbin" if BR2_ROOTFS_MERGED_USR
 	default "/bin:/sbin:/usr/bin:/usr/sbin"
 	help
system/skeleton/usr/sbin/.empty deleted +0 -0
deleted file mode 100644
index e69de29bb2..0000000000
system/system.mk +10 -0
index 8fe2c138b0..530b26c162 100644
@@ -34,16 +34,27 @@
 
 # This function handles the merged or non-merged /usr cases
 ifeq ($(BR2_ROOTFS_MERGED_USR),y)
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),y)
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	ln -snf bin $(1)/usr/sbin
+endef
+else
+define SYSTEM_SBIN_SYMLINKS_OR_DIRS
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
+endef
+endif
 define SYSTEM_USR_SYMLINKS_OR_DIRS
 	ln -snf usr/bin $(1)/bin
 	ln -snf usr/sbin $(1)/sbin
 	ln -snf usr/lib $(1)/lib
+	$(SYSTEM_SBIN_SYMLINKS_OR_DIRS)

system/system.mk line 60

Quoted 10 lines
system/system.mk +1 -0
 endef
 else
 define SYSTEM_USR_SYMLINKS_OR_DIRS
 	$(INSTALL) -d -m 0755 $(1)/bin
 	$(INSTALL) -d -m 0755 $(1)/sbin
 	$(INSTALL) -d -m 0755 $(1)/lib
+	$(INSTALL) -d -m 0755 $(1)/usr/sbin
 endef
 endif
 

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#22 lore raw

Re: [Buildroot] [PATCH 08/13] system: add support for merged /usr/sbin (aka merged-bin)

Edgar, All,

On 2025-05-17 18:52 +0200, Edgar Bonet spake thusly:

Quoted 1 line · Yann E. MORIN

[--SNIP--]

Quoted 2 lines

package/skeleton-custom/skeleton-custom.mk SKELETON_CUSTOM_NOT_MERGED_USR_DIRS = \ · line 38

Quoted 1 line
package/skeleton-custom/skeleton-custom.mk +1 -0
+	using a merged structuren for the following directories: \

Small typo: s/structuren/structure/

Good catch, thanks!

Regards,
Yann E. MORIN.

Signature · 10 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 561 099 427 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#23 lore raw

PATCH 9/13 package/systemd: require merged-bin

In reply to Yann E. MORIN

Since version 256, systemd will taint the system if /usr/bin and /usr/sbin are not merged, known as merged-bin. Although this is not yet an error, it will be in the future.

To be as ready as we can be when that happens, forcibly enable merged-bin, like we did when we initially added merged-usr.

Cc Norbert Lange <[email protected]>
Cc Sen Hastings <[email protected]>
---
 package/systemd/Config.in | 1 +
 1 file changed, 1 insertion(+)
package/systemd/Config.in +1 -0
index fd7671480c..5eaa092444 100644
@@ -25,6 +25,7 @@ menuconfig BR2_PACKAGE_SYSTEMD
 	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
 	depends on BR2_HOST_GCC_AT_LEAST_8 # host-systemd
 	select BR2_ROOTFS_MERGED_USR
+	select BR2_ROOTFS_MERGED_SBIN
 	select BR2_PACKAGE_HAS_UDEV
 	select BR2_PACKAGE_DBUS if !BR2_PACKAGE_DBUS_BROKER # runtime
 	select BR2_PACKAGE_LIBCAP
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
Acked-by Arnout Vandecappelle on v1 9/13
#24 lore raw

Re: [Buildroot] [PATCH 09/13] package/systemd: require merged-bin

Quoted 6 lines · Yann E. MORIN

Since version 256, systemd will taint the system if /usr/bin and /usr/sbin are not merged, known as merged-bin. Although this is not yet an error, it will be in the future.

To be as ready as we can be when that happens, forcibly enable merged-bin, like we did when we initially added merged-usr.

Except that this time we don't add a comment about it :-)

Regards,
Arnout

Quoted 13 lines
Cc Norbert Lange <[email protected]>
Cc Sen Hastings <[email protected]>
---
  package/systemd/Config.in | 1 +
  1 file changed, 1 insertion(+)
package/systemd/Config.in +0 -0
index fd7671480c..5eaa092444 100644

package/systemd/Config.in menuconfig BR2_PACKAGE_SYSTEMD · line 31

Quoted 7 lines
package/systemd/Config.in +1 -0
@@ -25,6 +25,7 @@ menuconfig BR2_PACKAGE_SYSTEMD
  	depends on BR2_TOOLCHAIN_GCC_AT_LEAST_8
  	depends on BR2_HOST_GCC_AT_LEAST_8 # host-systemd
  	select BR2_ROOTFS_MERGED_USR
+	select BR2_ROOTFS_MERGED_SBIN
  	select BR2_PACKAGE_HAS_UDEV
  	select BR2_PACKAGE_DBUS if !BR2_PACKAGE_DBUS_BROKER # runtime
  	select BR2_PACKAGE_LIBCAP

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot

#25 lore raw

PATCH 10/13 package/coreutils: no need for chroot workaround with merged-bin

In reply to Yann E. MORIN
---
 package/coreutils/coreutils.mk | 2 ++
 1 file changed, 2 insertions(+)
package/coreutils/coreutils.mk +2 -0
index a6d193b49e..cbfc2cd88c 100644
@@ -125,6 +125,7 @@ define COREUTILS_CREATE_TEST_SYMLINK
 endef
 COREUTILS_POST_INSTALL_TARGET_HOOKS += COREUTILS_CREATE_TEST_SYMLINK
 
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),)
 # gnu thinks chroot is in bin, debian thinks it's in sbin
 ifeq ($(BR2_PACKAGE_COREUTILS_INDIVIDUAL_BINARIES),y)
 define COREUTILS_FIX_CHROOT_LOCATION
@@ -137,6 +138,7 @@ define COREUTILS_FIX_CHROOT_LOCATION
 endef
 endif
 COREUTILS_POST_INSTALL_TARGET_HOOKS += COREUTILS_FIX_CHROOT_LOCATION
+endif
 
 # Explicitly install ln and realpath, which we *are* insterested in.
 # A lot of other programs still get installed, however, but disabling
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#26 lore raw

PATCH 11/13 package/kmod: adjust paths for merged-bin

In reply to Yann E. MORIN
---
 package/kmod/kmod.mk | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
package/kmod/kmod.mk +10 -2
index dfdd17b955..4635b8702d 100644
@@ -68,16 +68,24 @@ ifeq ($(BR2_PACKAGE_KMOD_TOOLS),y)
 KMOD_LICENSE += , GPL-2.0+ (tools)
 KMOD_LICENSE_FILES += COPYING
 
-# /sbin is really /usr/sbin with merged /usr, so adjust relative symlink
+# /sbin is really /usr/sbin with merged /usr, and /usr/sbin is
+# really /usr/bin with merged sbin, so adjust relative symlink
 ifeq ($(BR2_ROOTFS_MERGED_USR),y)
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),y)
+KMOD_BIN_PATH = kmod
+KMOD_SBIN_DIR = bin
+else
 KMOD_BIN_PATH = ../bin/kmod
+KMOD_SBIN_DIR = sbin
+endif
 else
 KMOD_BIN_PATH = ../usr/bin/kmod
+KMOD_SBIN_DIR = sbin
 endif
 
 define KMOD_INSTALL_TOOLS
 	for i in depmod insmod lsmod modinfo modprobe rmmod; do \
-		ln -sf $(KMOD_BIN_PATH) $(TARGET_DIR)/sbin/$$i; \
+		ln -sf $(KMOD_BIN_PATH) $(TARGET_DIR)/$(KMOD_SBIN_DIR)/$$i; \
 	done
 endef
 
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#27 lore raw

PATCH 12/13 package/util-linux: adjust paths for merged-bin

In reply to Yann E. MORIN
---
 package/util-linux/util-linux.mk | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
package/util-linux/util-linux.mk +7 -1
index ed30c0b107..ba3474b99f 100644
@@ -74,7 +74,13 @@ endif
 # ${usrlib_execdir} (/usr/lib) to ${libdir} (/lib), since both paths are
 # the same when merged usr is in use.
 ifeq ($(BR2_ROOTFS_MERGED_USR),y)
-UTIL_LINUX_CONF_OPTS += --bindir=/usr/bin --sbindir=/usr/sbin --libdir=/usr/lib
+UTIL_LINUX_CONF_OPTS += --bindir=/usr/bin --libdir=/usr/lib
+# Ditto for /usr/sbin and /usr/bin when merge sbin is in use
+ifeq ($(BR2_ROOTFS_MERGED_SBIN),y)
+UTIL_LINUX_CONF_OPTS += --sbindir=/usr/bin
+else
+UTIL_LINUX_CONF_OPTS += --sbindir=/usr/sbin
+endif
 endif
 
 ifeq ($(BR2_PACKAGE_SYSTEMD),y)
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#28 lore raw

PATCH 13/13 toolchain/external: support merged-bin

In reply to Yann E. MORIN

When an external toolchain does not have a merged-bin, we can end up with a situation where the toolchain installs an staging/usr/sbin/ directory, overriding the sbin symlink with an actual directory. When not using PPD, this does not cause any harm.

However, with PPD, the build fails when preparing the staging (the host/) for packages when the skeleton is eventually rsynced, e.g.:

    $ cat defconfig
    BR2_aarch64=y
    BR2_TOOLCHAIN_EXTERNAL=y
    BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y
    BR2_PER_PACKAGE_DIRECTORIES=y
    BR2_INIT_NONE=y
    BR2_ROOTFS_MERGED_USR=y
    BR2_ROOTFS_MERGED_SBIN=y
    # BR2_PACKAGE_BUSYBOX is not set
    BR2_PACKAGE_ZLIB=y
    # BR2_TARGET_ROOTFS_TAR is not set
    $ make zlib
    [...]
Quoted 1 line
Quoted 1 line
Quoted 1 line

zlib Configuring

    mkdir -p [...]/per-package/zlib/host
    rsync -a --hard-links --link-dest=[...]/per-package/host-skeleton/host/ [...]/per-package/host-skeleton/host/ [...]/per-package/zlib/host
    rsync -a --hard-links --link-dest=[...]/per-package/libzlib/host/ [...]/per-package/libzlib/host/ [...]/per-package/zlib/host
    rsync -a --hard-links --link-dest=[...]/per-package/skeleton/host/ [...]/per-package/skeleton/host/ [...]/per-package/zlib/host
    could not make way for new symlink: aarch64-buildroot-linux-gnu/sysroot/usr/sbin
    cannot delete non-empty directory: aarch64-buildroot-linux-gnu/sysroot/usr/sbin
    rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.3.0]
    make[1]: *** [package/pkg-generic.mk:256: [...]/build/zlib/.stamp_configured] Error 23
    make: *** [Makefile:23: _all] Error 2

The root cause is that, in the skeleton, we end up with [staging]/usr/sbin as a synlink to bin, but when the external toolchain gets installed, the symlinbk is replaced by a directory. Later, when we aggregate the PPD before configuring a package, it often happens that a dependant package be rsynced before the toolchain and the skeleton, as seen above, in which case the sbin directory from the toolchain, by way of the dependency to a package, is already present when rsync wants to create a symlink as rsynced from the skeleton.

In the example above, this plays in this order:

1. skeleton gets installed, provides a symlink
2. toolchain-external-bootlin rsyncs from skeleton, gets a symlink
3. toolchain-external-bootlin gets installed, replaces symlink with a directory
4. libzlib rsyncs from skeleton, gets a ymlink, then rsyncs from toolchain-e-b, gets a directory
5. zlib rsyncs from libzlib first (because alphabetical ordering), gets a directory, then rsyncs from skeleton, which rsyncs from a symlink, but the dstination is a non-empty directory, so rsync fails.

It is perfectly legit that an external toolchain does not use a merged-bin setup, so we must accept that as input. We do so by treating the /usr/sbin entry specially, like we already do for a few others, of which /sbin itself for example.

Note that the merged-usr setup has no issue, because we already handle the lib dirctories speically too.

Cc Giulio Benetti <[email protected]>
Cc Romain Naour <[email protected]>
Cc Thomas Petazzoni <[email protected]>
---
 toolchain/helpers.mk | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
toolchain/helpers.mk +6 -2
index f3fdaaec07..21c710d0fb 100644
@@ -96,6 +96,10 @@ copy_toolchain_lib_root = \
 # Note that the 'locale' directories are not copied. They are huge
 # (400+MB) in CodeSourcery toolchains, and they are not really useful.
 #
+# usr/sbin may be a directory in the source toolchain, but a symlink
+# in the destination sysroot, when we are using a merged-bin. Account
+# for that.
+#
 # $1: main sysroot directory of the toolchain
 # $2: arch specific sysroot directory of the toolchain
 # $3: arch specific subdirectory in the sysroot
@@ -109,13 +113,13 @@ copy_toolchain_sysroot = \
 	ARCH_SUBDIR="$(strip $3)"; \
 	ARCH_LIB_DIR="$(strip $4)" ; \
 	SUPPORT_LIB_DIR="$(strip $5)" ; \
-	for i in etc $${ARCH_LIB_DIR} sbin usr usr/$${ARCH_LIB_DIR}; do \
+	for i in etc $${ARCH_LIB_DIR} sbin usr usr/$${ARCH_LIB_DIR} usr/sbin; do \
 		if [ ! -d $${ARCH_SYSROOT_DIR}/$$i ] ; then \
 			continue ; \
 		fi ; \
 		if [ "$$i" = "usr" ]; then \
 			rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
-				--include '/libexec*/' --exclude '/lib*/' \
+				--include '/libexec*/' --exclude '/lib*/' --exclude '/sbin' \
 				$${ARCH_SYSROOT_DIR}/$$i/ $(STAGING_DIR)/$$i/ ; \
 		else \
 			rsync -au --chmod=u=rwX,go=rX --exclude 'locale/' \
Signature · 6 lines
2.47.0

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot