Merged-usr Buildroot Images: Audit Install Paths That Assume /bin Is a Directory

In a merged-usr image, /bin can be a symlink while /bin/tool remains a valid installed pathname. The compatibility question is whether package installers, overlays and inspection scripts preserve that structure. Test the path’s resolution and filesystem object type separately before changing an install prefix.

This guide pins Buildroot 2025.02. An owned host fixture created relative bin, sbin and lib links into usr, installed a harmless marker through bin and checked an overlay’s top-level shape. No root filesystem was mounted, booted or modified outside the disposable tree.

Read the selected layout contract

The 2025.02 system configuration defines BR2_ROOTFS_MERGED_USR for bin, sbin and lib symlinks to their usr counterparts. Its help explicitly excludes a separate usr filesystem for this configuration. Do not generalize a custom early-mount design into support promised by this Buildroot option.

The tagged system helper creates relative targets usr/bin, usr/sbin and usr/lib. With the option disabled, it creates separate directories instead. Preserve that choice with the image identity rather than detecting it from a developer workstation’s own root layout.

The common skeleton package applies the layout to both target and staging setup. A package can therefore encounter symlinked paths during installation before a final image exists. Correctness must cover the build tree as well as runtime lookup.

Relative top-level symlinks lead an installation through bin/tool to the canonical usr/bin/tool file while preserving link identity, followed by overlay and final-image checks.
Original merged-usr path fixture with observed link preservation and file mode.

Distinguish directory tests from link tests

A test that follows a symlink can report “directory” for bin because its destination is a directory. A non-following lstat or explicit symlink test reports the actual link object. Record both facts when diagnosing an installer that insists on creating or replacing a real directory.

Use readlink to preserve the link text and an image-aware resolver to establish the intended destination. A filename existing at both bin/tool and usr/bin/tool does not imply two independent copies. In the merged case they can name the same object.

Do not apply the host’s ordinary absolute-path resolution blindly to an extracted image. An absolute symlink inside an image is interpreted from the image root at runtime, while a naive host operation can escape into the host root. Keep fixture writes within verified owned paths.

Review installation operations by effect

An installer that creates a child file through an existing directory symlink can work correctly. An installer that replaces the parent path, recursively copies a directory tree over it or removes it before installation may not. The command’s effect matters more than whether its destination string starts with /bin.

Capture the actual package install command and inspect the destination before and after it runs in a disposable tree. Check symlink identity, final file content and mode. Include a reinstall case if the package updates an existing file.

Do not “repair” every package by converting bin back into a real directory. That breaks the selected image layout and can split files between two locations. Fix the maintained install rule or overlay structure while preserving the intended merged paths.

What the host fixture established

The fixture created usr/bin, usr/sbin and usr/lib beneath a new owned directory, then added relative bin, sbin and lib symlinks. A standard install -D -m 0755 operation wrote a synthetic text marker to the tree’s bin/tool path.

After installation, bin was still a symlink. The marker was present at usr/bin/tool with mode 0755, and both pathnames identified the same file. The marker was never executed. This checks one ordinary host installation pattern, not every upstream package’s copy or removal behavior.

A separate overlay preflight detected a real top-level bin directory in a deliberately incompatible fixture. A canonical overlay using usr/bin had no such conflicting top-level object. No overlay was actually applied over the merged tree, so the result is a shape-check outcome rather than an observed Buildroot overlay failure.

Build a package and overlay matrix

Candidate input Required check
Installer writes bin/tool Parent link survives; resolved file is the intended usr object.
Overlay contains a real bin directory Hold for layout review before applying it.
Cleanup removes or recreates bin Review the structural operation, not only child filenames.
Script assumes separate bin and usr/bin copies Check aliasing, duplicate enumeration and update behavior.

Use the same matrix for sbin and lib, then inspect architecture-specific library aliases separately. The three basic links do not describe every lib32 or lib64 arrangement. Derive those from the selected toolchain and skeleton rules.

Check final-image path resolution

Inspect the assembled filesystem after post-build scripts and image-generation transformations, not only the staging tree. Record the type and target of each top-level link, the expected executable/interpreter paths and any unexpected duplicate real directories.

A shell script’s shebang can still name /bin/sh in a merged layout, provided resolution reaches the intended interpreter. Likewise, a loader pathname under lib must resolve correctly in the final image. Do not rewrite all such paths solely because their first component is a symlink.

Verify startup availability under the supported image design. If usr is unavailable when essential programs are needed, the valid-looking link cannot supply its target. For the stated Buildroot configuration, follow the documented integrated usr layout rather than inventing a separate-mount exception.

Keep structural evidence with packaging acceptance

Retain the selected configuration, link inventory, install trace, overlay shape report and final-image checks. Repeat them after changing the skeleton, init system or package install logic. A package upgrade can alter directory-copy behavior without changing the installed tool’s name.

The useful result is a verified path-resolution contract: traditional names remain usable, their parent links remain intact and every file belongs to the intended canonical location. The host fixture establishes one small installation case; full Buildroot assembly and target boot remain explicit acceptance work.

Similar Posts