Files

62 lines
2.2 KiB
Bash
Raw Permalink Normal View History

2026-08-17 18:42:29 +00:00
#!/usr/bin/env bash
set -Eeuo pipefail
[[ $# -eq 2 ]] || { echo "Usage: $0 ROOTFS.ext4 TREE" >&2; exit 2; }
ROOTFS=$1
TREE=$2
[[ -f "$ROOTFS" && -d "$TREE" ]] || { echo "Invalid rootfs or tree" >&2; exit 2; }
COMMANDS=$(mktemp)
trap 'rm -f -- "$COMMANDS"' EXIT
escape_debugfs() {
local value=$1
value=${value//\\/\\\\}
value=${value//\"/\\\"}
printf '%s' "$value"
}
while IFS= read -r -d '' source_path; do
relative_path=${source_path#"$TREE"/}
target_path="/${relative_path}"
quoted_target=$(escape_debugfs "$target_path")
if [[ -d "$source_path" && ! -L "$source_path" ]]; then
printf 'mkdir "%s"\n' "$quoted_target" >>"$COMMANDS"
fi
done < <(find "$TREE" -mindepth 1 -type d -print0 | sort -z)
while IFS= read -r -d '' source_path; do
relative_path=${source_path#"$TREE"/}
target_path="/${relative_path}"
quoted_source=$(escape_debugfs "$source_path")
quoted_target=$(escape_debugfs "$target_path")
if [[ -L "$source_path" ]]; then
printf 'rm "%s"\n' "$quoted_target" >>"$COMMANDS"
printf 'symlink "%s" "%s"\n' "$quoted_target" "$(escape_debugfs "$(readlink "$source_path")")" >>"$COMMANDS"
elif [[ -f "$source_path" ]]; then
printf 'rm "%s"\n' "$quoted_target" >>"$COMMANDS"
printf 'write "%s" "%s"\n' "$quoted_source" "$quoted_target" >>"$COMMANDS"
fi
done < <(find "$TREE" -mindepth 1 \( -type f -o -type l \) -print0 | sort -z)
while IFS= read -r -d '' source_path; do
relative_path=${source_path#"$TREE"/}
target_path="/${relative_path}"
quoted_target=$(escape_debugfs "$target_path")
permissions=$(stat -c '%a' "$source_path")
if [[ -d "$source_path" && ! -L "$source_path" ]]; then
file_type=040000
elif [[ -L "$source_path" ]]; then
file_type=0120000
else
file_type=0100000
fi
printf 'set_inode_field "%s" uid 0\n' "$quoted_target" >>"$COMMANDS"
printf 'set_inode_field "%s" gid 0\n' "$quoted_target" >>"$COMMANDS"
printf 'set_inode_field "%s" mode 0%o\n' "$quoted_target" "$((file_type | 8#$permissions))" >>"$COMMANDS"
done < <(find "$TREE" -mindepth 1 -print0 | sort -z)
# debugfs reports benign "already exists" and "file not found" diagnostics for
# idempotent mkdir/rm operations. The caller performs explicit postconditions.
debugfs -w -f "$COMMANDS" "$ROOTFS" >/dev/null 2>&1