From 10d81b7e5b3304e4a16449b6f7319d7359fc0454 Mon Sep 17 00:00:00 2001 From: Sam Hardeman Date: Sun, 15 Mar 2026 18:52:13 +0100 Subject: [PATCH] Added cdz check parameter for use in multicd (normal cd, squash cd and cdz). Consolidated all squash functionality into a binary (squasher) Updated the 'cd' alias (multicd). Added -e to ldrc (to edit the user scripts) --- README.md | 14 ++-- cdz | 98 ++++++++++++++++++++---- daisy.source | 31 ++++++-- destroy-squash-image | 50 ------------- make-squash-image | 118 ----------------------------- mount-squash-image | 46 ------------ squasher | 175 +++++++++++++++++++++++++++++++++++++++++++ umount-squash-image | 27 ------- 8 files changed, 288 insertions(+), 271 deletions(-) delete mode 100755 destroy-squash-image delete mode 100755 make-squash-image delete mode 100755 mount-squash-image create mode 100755 squasher delete mode 100755 umount-squash-image diff --git a/README.md b/README.md index ecc2e66..125c122 100755 --- a/README.md +++ b/README.md @@ -45,11 +45,13 @@ These are the included binaries and utilities: NO_ARCHIVEMOUNT=1. The standard script supports zip, tarballs, and rar archives. We recommend relying on archivemount` if you have it installed. - - SquashFS tools (mount/umount/make/destroy-squash-image): + Use "--check" to only check if a file is an archive. + It returns 0 if it is, 1 otherwise. + - SquashFS tools (squasher): These convenient set of tools allow you to easily create XZ-compressed SquashFS images from existing folders to save disk space. The resulting folder is still writable since it is - mounted using an 'overlay' system. You can use 'make-squash-image' + mounted using an 'overlay' system. You can use 'squasher make' to compresses an existing folder. These folders are automatically mounted when you use 'cd' to navigate to them (via an alias). When using 'make-squash-image' on an already mounted folder, it will @@ -57,12 +59,12 @@ These are the included binaries and utilities: SystemD service to auto-mount, however, you cam easily add auto-mount as a cron job. Here is a list of tools, they all take the same folder argument: - > make-squash-image: Converts the folder into a hidden image + > squasher make: Converts the folder into a hidden image on the same disk as the folder. - > mount-squash-image: Sets up a mount for the XZ image alongside + > squasher mount: Sets up a mount for the XZ image alongside directories for changes - > umount-squash-image: Self-explanatory. - > destroy-squash-image: Extracts the image and essentially reverts + > squasher umount: Self-explanatory. + > squasher destroy: Extracts the image and essentially reverts everything. File changes are kept, however. - editx: Uses your standard CLI editor to create/modify a diff --git a/cdz b/cdz index 94e5e4c..3b8d15a 100755 --- a/cdz +++ b/cdz @@ -1,57 +1,122 @@ #!/usr/bin/env bash -# Usage: cdz +# Usage: cdz [--check] -if [[ $LD_INTERNAL -ne 1 ]]; then +if [[ $LD_INTERNAL -ne 1 ]] +then LD_INTERNAL=1 . $(dirname $(realpath $0))/daisy.source fi +is_archive() +{ + local file="$1" + local mime_type=$(file --mime-type -b "$file") + + if [[ $mime_type == *"tar"* || $file == *.tar* || $mime_type == "application/zip" || $mime_type == "application/x-rar" ]] + then + return 0 + fi + + if command -v archivemount >/dev/null 2>&1 + then + local test_dir=$(mktemp -d /tmp/cdz_check.XXXXXXXX) + local result=1 + if archivemount -o readonly "$file" "$test_dir" >/dev/null 2>&1 + then + result=0 + umount "$test_dir" + fi + rmdir "$test_dir" + return $result + fi + + return 1 +} + +check_mode=0 +if [[ "$1" == "--check" ]] +then + check_mode=1 + shift +fi + target=$1 -if [[ -z "$target" ]]; then - echo "No target specified." +if [[ -z "$target" ]] +then + if [[ $check_mode -eq 0 ]] + then + echo "No target specified." + fi exit 1 fi -if [[ ! -f "$target" ]]; then - echo "File not found: \"$target\"" +if [[ ! -f "$target" ]] +then + if [[ $check_mode -eq 0 ]] + then + echo "File not found: \"$target\"" + fi exit 2 fi target_abs=$(realpath "$target") name=$(basename "$target") +if is_archive "$target_abs" +then + if [[ $check_mode -eq 1 ]] + then + exit 0 + fi +else + if [[ $check_mode -eq 1 ]] + then + exit 1 + fi + mime_type=$(file --mime-type -b "$target_abs") + echo "Unsupported archive type: $mime_type" + exit 1 +fi + +# Proceed with extraction has_archivemount=$(command -v archivemount >/dev/null 2>&1; echo $?) -if [[ $has_archivemount -eq 0 && $NO_ARCHIVEMOUNT -ne 1 ]]; then +if [[ $has_archivemount -eq 0 && $NO_ARCHIVEMOUNT -ne 1 ]] +then use_mounter=1 else use_mounter=0 fi -mime_type=$(file --mime-type -b "$target") - +mime_type=$(file --mime-type -b "$target_abs") comm1=(:) comm2=(echo "Unsupported archive type: $mime_type") comm3=(:) comm4=(:) comm5=(:) -if [[ $use_mounter -eq 1 ]]; then +if [[ $use_mounter -eq 1 ]] +then echo "Using archivemount..." comm2=(archivemount -o allow_root,use_ino "$target_abs") comm4=(cd ..) comm5=(umount) -elif [[ $mime_type == *"tar"* || $target == *.tar* ]]; then +elif [[ $mime_type == *"tar"* || $target_abs == *.tar* ]] +then comm2=(tar xvf "$target_abs" -C) -elif [[ $mime_type == "application/zip" ]]; then - if command -v unzip >/dev/null 2>&1; then +elif [[ $mime_type == "application/zip" ]] +then + if command -v unzip >/dev/null 2>&1 + then comm2=(unzip -q "$target_abs" -d) else comm1=(echo "unzip is missing") comm3=(exit 1) fi -elif [[ $mime_type == "application/x-rar" ]]; then - if command -v unrar >/dev/null 2>&1; then +elif [[ $mime_type == "application/x-rar" ]] +then + if command -v unrar >/dev/null 2>&1 + then # unrar needs the directory as the last argument comm2=(unrar x -idq "$target_abs") else @@ -63,7 +128,8 @@ fi dir=$(mktemp -d /tmp/extracted.XXXXXXXX) "${comm1[@]}" -if [[ ${comm2[0]} == "unrar" ]]; then +if [[ ${comm2[0]} == "unrar" ]] +then "${comm2[@]}" "$dir" else "${comm2[@]}" "$dir" diff --git a/daisy.source b/daisy.source index 97a43c6..915ab1b 100755 --- a/daisy.source +++ b/daisy.source @@ -80,10 +80,12 @@ LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src" LD_ESOURCEFILE="$LD_CONFIG_FOLDER/extra.src" touch $LD_ALIASFILE touch $LD_EDITORFILE +touch $LD_ESOURCEFILE ld_dbg echo "Sourced config contents:" ld_dbg cat $LD_ALIASFILE ld_dbg cat $LD_EDITORFILE +ld_dbg cat $LD_ESOURCEFILE # Source everything in the config folder function _daisy_source_configs @@ -132,28 +134,37 @@ function daisy_wait_for_editor done } -function mountcd +function multicd { cdpath="$@" - if [[ $cdpath == '' ]]; + if [[ $cdpath == '' ]] then \cd + return fi - if [[ -f "$cdpath/.needs_mount" ]]; + + if cdz --check "$cdpath" >/dev/null 2>&1 then - mount-squash-image "$cdpath" + cdz "$cdpath" + return + fi + + if [[ -f "$cdpath/.needs_mount" ]] + then + squasher mount "$cdpath" fi \cd "$cdpath" } -alias cd=mountcd +alias cd=multicd # Undocumented but internally used function daisy_editor { editor=${LD_EDITOR:-$EDITOR}; ld_dbg echo Opening $editor to edit file: $1 - $editor "$1" + $editor "$1" + sleep 1 daisy_wait_for_editor $editor "$1" } @@ -315,8 +326,12 @@ function daisy_reload function ldrc { - daisy_editor "$LD_SOURCE_FILE" - LD_INTERNAL=0 source "$LD_SOURCE_FILE" + ARG=$1 + SOURCE="$LD_SOURCE_FILE" + [[ "$ARG" == "-e" ]] && SOURCE="$LD_ESOURCEFILE" + + daisy_editor "$SOURCE" + LD_INTERNAL=0 source "$SOURCE" } enc_is_folder=0 diff --git a/destroy-squash-image b/destroy-squash-image deleted file mode 100755 index 6eef52a..0000000 --- a/destroy-squash-image +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Lackadaisical squashfs tools - Destroy - -DIR="$1" -if [[ -z "$DIR" ]]; then - echo "Usage: $0 " - exit 1 -fi - -DIR=$(readlink -f "$DIR") -DIR_SHORT=$(basename "$DIR") -BIN_DIR=$(dirname "$(readlink -f "$0")") - -if [[ ! -f "$DIR/.needs_mount" ]]; then - if ! mountpoint -q "$DIR"; then - echo "Error: $DIR is not a SquashFS directory." - exit 1 - fi -fi - -# Stop systemd service -ESC_PATH=$(systemd-escape -p "$DIR") -SERVICE_NAME="squash-mount@$ESC_PATH.service" - -echo "Disabling service ($SERVICE_NAME)..." -sudo systemctl stop "$SERVICE_NAME" 2>/dev/null -sudo systemctl disable "$SERVICE_NAME" 2>/dev/null - -# Ensure it is mounted to copy merged data -echo "Ensuring image is mounted to preserve data..." -"$BIN_DIR/mount-squash-image" "$DIR" 1>/dev/null 2>/dev/null - -echo "Destroying image and restoring data..." - -# Atomic copy-out -TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX) -sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; } - -# Unmount -"$BIN_DIR/umount-squash-image" "$DIR" - -# Restore original directory structure -OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT" -sudo rm -rf "$DIR" -sudo mv "$TEMP_DIR" "$DIR" - -# Final cleanup -sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img" - -echo "Success: SquashFS image destroyed and data restored to \"$DIR\"." diff --git a/make-squash-image b/make-squash-image deleted file mode 100755 index 17e0099..0000000 --- a/make-squash-image +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash -# Lackadaisical squashfs tools -# Allows you to create a modifiable squashfs-backed image for a folder - -BIN_DIR=$(dirname "$(readlink -f "$0")") -DIR="$1" - -if [[ -z "$DIR" ]]; then - echo "Usage: $0 " - exit 1 -fi - -if [[ ! -d "$DIR" ]]; then - echo "Error: Directory \"$DIR\" does not exist!" - exit 1 -fi - -echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..." -for fs in fuse squashfs overlay; do - if ! grep -q "$fs" /proc/filesystems; then - echo "Attempting to load $fs module..." - sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; } - fi -done - -DIR=$(readlink -f "$DIR") -DIR_SHORT=$(basename "$DIR") -DIRSIZE=$(du -sh "$DIR" | cut -f1) - -OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT" -OVERLAY_UPPER="$OVERLAY_ROOT/upper" -OVERLAY_LOWER="$OVERLAY_ROOT/lower" -OVERLAY_WORK="$OVERLAY_ROOT/work" -OVERLAY_TARG="$DIR" -RECREATE=false - -mkdir -p "$OVERLAY_ROOT" - -if [[ -f "${OVERLAY_ROOT}.img" ]]; then - echo "Existing image found, updating..." - "$BIN_DIR/mount-squash-image" "$DIR" - DIRSIZE=$(du -sh "$DIR" | cut -f1) - RECREATE=true -fi - -echo "Compressing \"$DIR\"..." -sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1 - -if [[ "$RECREATE" == "true" ]]; then - echo "Cleaning up old layers..." - "$BIN_DIR/umount-squash-image" "$DIR" - # Safety check before destructive RM - if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then - sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" - rm -f "${OVERLAY_ROOT}.img" - fi -fi - -mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img" - -# Prepare overlay structure -mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG" - -# Reset original directory to mountpoint -sudo rm -rf "$DIR" -mkdir -p "$DIR" -touch "$DIR/.needs_mount" - -echo "-------------------------------------------------------------------------" -echo "Storage Stats:" -echo " Original size: $DIRSIZE" -echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)" -echo "-------------------------------------------------------------------------" - -# SystemD Service Setup -SERVICE_CONTENT="[Unit] -Description=SquashFS Mount for %I -After=local-fs.target - -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=${BIN_DIR}/mount-squash-image %I -ExecStop=${BIN_DIR}/umount-squash-image %I - -[Install] -WantedBy=multi-user.target" - -echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null -sudo systemctl daemon-reload - -ESC_PATH=$(systemd-escape -p "$DIR") -SERVICE_NAME="squash-mount@$ESC_PATH.service" - -read -p "Do you want to auto-enable the mount service ($SERVICE_NAME)? [y/N] " yn -case $yn in - [Yy]* ) - echo "Enabling and starting service..." - sudo systemctl enable --now "$SERVICE_NAME" - sudo systemctl stop "$SERVICE_NAME" - sudo systemctl start "$SERVICE_NAME" - ;; - * ) - echo "To enable the service manually, run: sudo systemctl enable --now $SERVICE_NAME" - ;; -esac - -echo "" -echo "Your SquashFS-backed folder is ready for use." -echo "To mount it manually, either cd into it or use mount-squash-image." -echo "" -echo "Should you wish to update the contents of the image with your changes made" -echo "inside of the folder, simply run make-squash-image again on the same" -echo "folder to update the image." -echo -echo "To disable auto-mounting upon cd, please remove the" -echo ".needs_mount file to prevent that." -echo diff --git a/mount-squash-image b/mount-squash-image deleted file mode 100755 index 2c0fac9..0000000 --- a/mount-squash-image +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# Lackadaisical squashfs tools - Mount - -DIR="$1" -if [[ -z "$DIR" ]]; then - echo "Usage: $0 " - exit 1 -fi - -DIR=$(readlink -f "$DIR") -DIR_SHORT=$(basename "$DIR") -BIN_DIR=$(dirname "$(readlink -f "$0")") - -OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT" -OVERLAY_UPPER="$OVERLAY_ROOT/upper" -OVERLAY_LOWER="$OVERLAY_ROOT/lower" -OVERLAY_WORK="$OVERLAY_ROOT/work" -OVERLAY_TARG="$DIR" - -if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then - echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2 - exit 1 -fi - -# Unmount existing first -"$BIN_DIR/umount-squash-image" "$DIR" 2>/dev/null - -# Mount lower squashfs image via loopback -mkdir -p "$OVERLAY_LOWER" -sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop -if [[ $? -ne 0 ]]; then - echo "Error: Failed to mount squashfs image." >&2 - exit 1 -fi - -# Mount overlay -sudo mount -t overlay none "$OVERLAY_TARG" \ - -o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK" - -if [[ $? -ne 0 ]]; then - echo "Error: Failed to mount overlay." >&2 - sudo umount "$OVERLAY_LOWER" 2>/dev/null - exit 1 -fi - -echo "SquashFS filesystem is mounted and ready." diff --git a/squasher b/squasher new file mode 100755 index 0000000..3049be8 --- /dev/null +++ b/squasher @@ -0,0 +1,175 @@ +#!/bin/bash +# Lackadaisical squashfs tools - Squasher +# Combined utility for make, mount, umount, and destroy operations. + +BIN_DIR=$(dirname "$(readlink -f "$0")") +COMMAND="$1" +DIR="$2" + +usage() { + echo "Usage: $0 {make|mount|umount|destroy} " + exit 1 +} + +if [[ -z "$COMMAND" || -z "$DIR" ]]; then + usage +fi + +DIR=$(readlink -f "$DIR") +DIR_SHORT=$(basename "$DIR") +OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT" +OVERLAY_UPPER="$OVERLAY_ROOT/upper" +OVERLAY_LOWER="$OVERLAY_ROOT/lower" +OVERLAY_WORK="$OVERLAY_ROOT/work" +OVERLAY_TARG="$DIR" + +case "$COMMAND" in + make) + if [[ ! -d "$DIR" ]]; then + echo "Error: Directory \"$DIR\" does not exist!" + exit 1 + fi + + echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..." + for fs in fuse squashfs overlay; do + if ! grep -q "$fs" /proc/filesystems; then + echo "Attempting to load $fs module..." + sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; } + fi + done + + DIRSIZE=$(du -sh "$DIR" | cut -f1) + RECREATE=false + mkdir -p "$OVERLAY_ROOT" + + if [[ -f "${OVERLAY_ROOT}.img" ]]; then + echo "Existing image found, updating..." + "$0" mount "$DIR" + DIRSIZE=$(du -sh "$DIR" | cut -f1) + RECREATE=true + fi + + echo "Compressing \"$DIR\"..." + sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1 + + if [[ "$RECREATE" == "true" ]]; then + echo "Cleaning up old layers..." + "$0" umount "$DIR" + if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then + sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" + rm -f "${OVERLAY_ROOT}.img" + fi + fi + + mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img" + mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG" + + sudo rm -rf "$DIR" + mkdir -p "$DIR" + touch "$DIR/.needs_mount" + + echo "-------------------------------------------------------------------------" + echo "Storage Stats:" + echo " Original size: $DIRSIZE" + echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)" + echo "-------------------------------------------------------------------------" + + SERVICE_CONTENT="[Unit] +Description=SquashFS Mount for %I +After=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=${BIN_DIR}/squasher mount %I +ExecStop=${BIN_DIR}/squasher umount %I + +[Install] +WantedBy=multi-user.target" + + echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null + sudo systemctl daemon-reload + + ESC_PATH=$(systemd-escape -p "$DIR") + SERVICE_NAME="squash-mount@$ESC_PATH.service" + + read -p "Enable auto-mount service ($SERVICE_NAME)? [y/N] " yn + if [[ "$yn" =~ ^[Yy]$ ]]; then + sudo systemctl enable --now "$SERVICE_NAME" + sudo systemctl stop "$SERVICE_NAME" + sudo systemctl start "$SERVICE_NAME" + else + echo "Manual mount command: sudo systemctl start $SERVICE_NAME" + fi + ;; + + mount) + if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then + echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2 + exit 1 + fi + + "$0" umount "$DIR" 2>/dev/null + mkdir -p "$OVERLAY_LOWER" + sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop + if [[ $? -ne 0 ]]; then + echo "Error: Failed to mount squashfs image." >&2 + exit 1 + fi + + sudo mount -t overlay none "$OVERLAY_TARG" \ + -o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK" + + if [[ $? -ne 0 ]]; then + echo "Error: Failed to mount overlay." >&2 + sudo umount "$OVERLAY_LOWER" 2>/dev/null + exit 1 + fi + echo "SquashFS filesystem is mounted and ready." + ;; + + umount) + sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null + sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null + + if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then + echo "Warning: Filesystem is still mounted. Check for open processes." + exit 1 + fi + echo "SquashFS filesystem has been unmounted." + ;; + + destroy) + if [[ ! -f "$DIR/.needs_mount" ]]; then + if ! mountpoint -q "$DIR"; then + echo "Error: $DIR is not a SquashFS directory." + exit 1 + fi + fi + + ESC_PATH=$(systemd-escape -p "$DIR") + SERVICE_NAME="squash-mount@$ESC_PATH.service" + + echo "Disabling service ($SERVICE_NAME)..." + sudo systemctl stop "$SERVICE_NAME" 2>/dev/null + sudo systemctl disable "$SERVICE_NAME" 2>/dev/null + + echo "Ensuring image is mounted to preserve data..." + "$0" mount "$DIR" 1>/dev/null 2>/dev/null + + echo "Destroying image and restoring data..." + TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX) + sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; } + + "$0" umount "$DIR" + sudo rm -rf "$DIR" + sudo mv "$TEMP_DIR" "$DIR" + sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img" + + echo "Success: SquashFS image destroyed and data restored to \"$DIR\"." + ;; + + *) + usage + ;; +esac diff --git a/umount-squash-image b/umount-squash-image deleted file mode 100755 index 18fd764..0000000 --- a/umount-squash-image +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# Lackadaisical squashfs tools - Unmount - -DIR="$1" -if [[ -z "$DIR" ]]; then - echo "Usage: $0 " - exit 1 -fi - -DIR=$(readlink -f "$DIR") -DIR_SHORT=$(basename "$DIR") - -OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT" -OVERLAY_LOWER="$OVERLAY_ROOT/lower" -OVERLAY_TARG="$DIR" - -# Forcefully unmount both layers recursively -sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null -sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null - -if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then - echo "Warning: Filesystem is still mounted. Check for open processes." - exit 1 -fi - -echo "SquashFS filesystem has been unmounted." -exit 0