[RFC,v2,12/19] add helper script to clean artifacts in build dir

Message ID 20260220171601.3845113-13-felix.moessbauer@siemens.com
State New
Headers show
Series add support to build isar unprivileged | expand

Commit Message

Felix Moessbauer Feb. 20, 2026, 5:15 p.m. UTC
When running in rootless mode, cleaning the build directory from outside
the build environment is a non trivial task due to mixed file
ownerships. To simplify this, we introduce the isar-clean-builddir
script that can perform the cleanup without requiring root privileges.

Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
 RECIPE-API-CHANGELOG.md     |  5 +++
 scripts/isar-clean-builddir | 73 +++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100755 scripts/isar-clean-builddir

Comments

Jan Kiszka Feb. 20, 2026, 6:24 p.m. UTC | #1
On 20.02.26 18:15, Felix Moessbauer wrote:
> When running in rootless mode, cleaning the build directory from outside
> the build environment is a non trivial task due to mixed file
> ownerships. To simplify this, we introduce the isar-clean-builddir
> script that can perform the cleanup without requiring root privileges.
> 
> Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
> ---
>  RECIPE-API-CHANGELOG.md     |  5 +++
>  scripts/isar-clean-builddir | 73 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 78 insertions(+)
>  create mode 100755 scripts/isar-clean-builddir
> 
> diff --git a/RECIPE-API-CHANGELOG.md b/RECIPE-API-CHANGELOG.md
> index 59ea3110..8cbafbba 100644
> --- a/RECIPE-API-CHANGELOG.md
> +++ b/RECIPE-API-CHANGELOG.md
> @@ -1015,3 +1015,8 @@ check the kas mailing list).
>  Note, that the following features are not supported yet in rootless mode:
>  
>  - devshell
> +
> +Note, that the build dir may contain files that were generated within the rootless
> +environment and cannot be deleted from the outside by the calling user. To simplify
> +the cleanup, we provide the `isar-clean-builddir` script that helps purging
> +directories with mixed ownerships (without requiring root privileges).
> diff --git a/scripts/isar-clean-builddir b/scripts/isar-clean-builddir
> new file mode 100755
> index 00000000..81b52561
> --- /dev/null
> +++ b/scripts/isar-clean-builddir
> @@ -0,0 +1,73 @@
> +#!/bin/sh
> +# isar-clean-builddir - Clean the build/tmp directory
> +#
> +# This script removes all files from the specified directory, including those
> +# owned by other users (which requires elevated privileges).
> +#
> +# Rootless Mode:
> +#   When --rootless is specified, no privileged commands are executed. This
> +#   requires that the UID namespace where files were generated matches the
> +#   cleanup environment. When running from a container, this script must be
> +#   called from within the same container.
> +#
> +# Part of the Isar API. External tools may call this script for cleanup.
> +#
> +# Copyright (c) Siemens AG, 2026
> +# SPDX-License-Identifier: MIT
> +
> +DRY_RUN=0
> +ROOTLESS=0
> +
> +usage()
> +{
> +    EXIT_CODE="$1"
> +    SELF="isar-clean-builddir"
> +    printf "%b" "Usage: ${SELF} [--rootless] [--dry-run] [dir]\n"
> +
> +    exit "${EXIT_CODE:-1}"
> +}
> +
> +while [ $# -gt 0 ]; do
> +    case "$1" in
> +    --dry-run)
> +        DRY_RUN=1
> +        shift 1
> +        ;;
> +    -h | --help)
> +        usage 0
> +        ;;
> +    --rootless)
> +        ROOTLESS=1
> +        shift 1
> +        ;;
> +    --*)
> +        usage 1
> +        ;;
> +    *)
> +        break
> +        ;;
> +    esac
> +done
> +
> +[ $# -eq 1 ] || usage 1
> +if ! [ -d "$1" ]; then
> +    echo "error: \"$1\" is not a directory"
> +    exit 1
> +fi
> +
> +if [ $ROOTLESS -eq 1 ]; then
> +    PRIVILEGED_CMD="mmdebstrap --unshare-helper"
> +else
> +    PRIVILEGED_CMD="sudo"
> +fi
> +
> +if [ $DRY_RUN -eq 1 ]; then
> +    echo "dry-run, not executing"
> +    DRY_RUN_PREFIX="/bin/echo"
> +fi
> +
> +# clean all files that do not belong to us
> +# shellcheck disable=2086
> +find "$1" \( ! -user "$(whoami)" -type d -prune \) -exec $DRY_RUN_PREFIX $PRIVILEGED_CMD rm -rf {} \;
> +# clean remaining files
> +$DRY_RUN_PREFIX rm -rf "$1"

Works in rootless, folder is gone, but it suggests something different:

$ isar/scripts/isar-clean-builddir --rootless build/tmp
rm: cannot remove 'build/tmp/ccache/xenomai-demo-riscv64-amd64/a':
Permission denied
E: system failed: 256
E: unshared command failed
rm: cannot remove 'build/tmp/ccache/xenomai-demo-riscv64-amd64/8':
Permission denied
E: system failed: 256
E: unshared command failed
rm: cannot remove 'build/tmp/ccache/xenomai-demo-riscv64-amd64/c':
Permission denied
E: system failed: 256
E: unshared command failed
...
$ ls build/tmp
ls: cannot access 'build/tmp': No such file or directory

Jan

Patch

diff --git a/RECIPE-API-CHANGELOG.md b/RECIPE-API-CHANGELOG.md
index 59ea3110..8cbafbba 100644
--- a/RECIPE-API-CHANGELOG.md
+++ b/RECIPE-API-CHANGELOG.md
@@ -1015,3 +1015,8 @@  check the kas mailing list).
 Note, that the following features are not supported yet in rootless mode:
 
 - devshell
+
+Note, that the build dir may contain files that were generated within the rootless
+environment and cannot be deleted from the outside by the calling user. To simplify
+the cleanup, we provide the `isar-clean-builddir` script that helps purging
+directories with mixed ownerships (without requiring root privileges).
diff --git a/scripts/isar-clean-builddir b/scripts/isar-clean-builddir
new file mode 100755
index 00000000..81b52561
--- /dev/null
+++ b/scripts/isar-clean-builddir
@@ -0,0 +1,73 @@ 
+#!/bin/sh
+# isar-clean-builddir - Clean the build/tmp directory
+#
+# This script removes all files from the specified directory, including those
+# owned by other users (which requires elevated privileges).
+#
+# Rootless Mode:
+#   When --rootless is specified, no privileged commands are executed. This
+#   requires that the UID namespace where files were generated matches the
+#   cleanup environment. When running from a container, this script must be
+#   called from within the same container.
+#
+# Part of the Isar API. External tools may call this script for cleanup.
+#
+# Copyright (c) Siemens AG, 2026
+# SPDX-License-Identifier: MIT
+
+DRY_RUN=0
+ROOTLESS=0
+
+usage()
+{
+    EXIT_CODE="$1"
+    SELF="isar-clean-builddir"
+    printf "%b" "Usage: ${SELF} [--rootless] [--dry-run] [dir]\n"
+
+    exit "${EXIT_CODE:-1}"
+}
+
+while [ $# -gt 0 ]; do
+    case "$1" in
+    --dry-run)
+        DRY_RUN=1
+        shift 1
+        ;;
+    -h | --help)
+        usage 0
+        ;;
+    --rootless)
+        ROOTLESS=1
+        shift 1
+        ;;
+    --*)
+        usage 1
+        ;;
+    *)
+        break
+        ;;
+    esac
+done
+
+[ $# -eq 1 ] || usage 1
+if ! [ -d "$1" ]; then
+    echo "error: \"$1\" is not a directory"
+    exit 1
+fi
+
+if [ $ROOTLESS -eq 1 ]; then
+    PRIVILEGED_CMD="mmdebstrap --unshare-helper"
+else
+    PRIVILEGED_CMD="sudo"
+fi
+
+if [ $DRY_RUN -eq 1 ]; then
+    echo "dry-run, not executing"
+    DRY_RUN_PREFIX="/bin/echo"
+fi
+
+# clean all files that do not belong to us
+# shellcheck disable=2086
+find "$1" \( ! -user "$(whoami)" -type d -prune \) -exec $DRY_RUN_PREFIX $PRIVILEGED_CMD rm -rf {} \;
+# clean remaining files
+$DRY_RUN_PREFIX rm -rf "$1"