#!/bin/bash # System Commands Handler # Handles all system subcommands by calling core functions # Safe disk reclaim: clear the whole build cache (-a; it's pure cache, always # safe to drop) and remove dangling images. Never touches volumes or in-use # images. runFileOp hits the right daemon (rootless: as the install user). reclaimDockerSpace() { isHeader "Reclaiming Space" runFileOp docker builder prune -af >/dev/null 2>&1 checkSuccess "Cleared build cache" runFileOp docker image prune -f >/dev/null 2>&1 checkSuccess "Removed dangling images" isSuccessful "Done" } # Remove specific Docker images by id/ref. Args: # $1 force flag — "-f" to force-remove (e.g. in-use images), else empty # $2 comma-separated list of image refs (the WebUI sends full sha256:… ids) # The WebUI Storage page calls this through the task system (see the # system_image_rm action) — never a direct API. Each ref is validated before it # reaches docker; removal continues past per-image failures and reports a tally. removeDockerImages() { local force_flag="$1" ids_csv="$2" isHeader "Removing Images" if [[ -z "$ids_csv" ]]; then isError "No images specified." return 1 fi local removed=0 failed=0 id local IFS=',' local -a ids=($ids_csv) unset IFS for id in "${ids[@]}"; do id="${id//[[:space:]]/}" [[ -n "$id" ]] || continue # Accept only a sha256 digest or a conservative repo[:tag] ref — no shell # metacharacters can reach docker even though this arrives via the task # command string. if [[ ! "$id" =~ ^sha256:[a-f0-9]{12,64}$ && ! "$id" =~ ^[A-Za-z0-9][A-Za-z0-9._/:@-]*$ ]]; then isError "Skipping invalid image ref: $id" failed=$((failed + 1)); continue fi # $force_flag is intentionally unquoted: it's either empty or "-f". if runFileOp docker image rm $force_flag "$id" >/dev/null 2>&1; then isSuccessful "Removed $id" removed=$((removed + 1)) else isError "Could not remove $id (in use, or has dependent child images)" failed=$((failed + 1)) fi done isNotice "Done — removed ${removed}, failed/skipped ${failed}." [[ "$failed" -eq 0 ]] } cliHandleSystemCommands() { local action="$initial_command2" case "$action" in "status") tagsValidateShowSystemStatus ;; "update") checkUpdates ;; "reset") runReinstall ;; "reclaim") reclaimDockerSpace ;; "image") # libreportal system image rm [--force] case "$initial_command3" in "rm"|"remove") local img_force="" img_ids="" if [[ "$initial_command4" == "--force" || "$initial_command4" == "-f" ]]; then img_force="-f"; img_ids="$initial_command5" else img_ids="$initial_command4" fi removeDockerImages "$img_force" "$img_ids" ;; *) isNotice "Invalid image command: $initial_command3" cliShowSystemHelp ;; esac ;; *) isNotice "Invalid system command: $action" cliShowSystemHelp ;; esac }