Bring script headers onto the template and close safeguard gaps

Headers claimed protections the code never had, and several destructive paths had no
guard against a collapsed config value.
This commit is contained in:
Gmer4Lfe
2026-08-01 20:37:59 -04:00
parent cdce877601
commit e8b114094a
78 changed files with 3301 additions and 277 deletions
+70
View File
@@ -41,6 +41,64 @@
# safely after a partial run or a manually resolved conflict.
#
# ==============================================================================================
# DESIGN PRINCIPLES
# ==============================================================================================
#
# Move, Never Copy or Delete
# Files are relocated with mv and nothing is ever removed. A misjudged move is
# reversible by hand; a delete is not. The script has no cleanup pass by design.
#
# Idempotent by Collision Skip
# Re-running is safe because an existing destination is skipped rather than
# overwritten. A partial run, an interrupted run, or a manually resolved conflict
# can all be followed by a plain re-run.
#
# Deterministic Ordering
# Multiple trailers per show are sorted before numbering, so the same input always
# produces the same trailer.ext / trailer-2.ext assignment. Without the sort, the
# numbering would depend on filesystem iteration order and a re-run could rename
# files differently.
#
# Filesystem Only
# Neither Trailarr nor Emby is touched. Emby's periodic library scan picks the moved
# files up on its own — poking either service would add failure modes to what is
# otherwise a pure file move.
#
# ==============================================================================================
# OPERATIONAL SAFEGUARDS
# ==============================================================================================
#
# Root Enforcement
# Moves files owned by container users and chowns the created trailers/ directory.
#
# Lock Acquisition
# acquire_lock prevents two runs numbering the same show's trailers concurrently.
#
# Host Detection
# detect_hosts() aliases HOST*_SONARR_TV_ROOT → SONARR_TV_ROOT.
#
# TV Root Validation
# Exits if SONARR_TV_ROOT is unset or is not a directory — the scan below is rooted
# there, and an empty value would walk from the current directory.
#
# Bounded Scan Depth
# find runs with -mindepth 2 -maxdepth 2, so only files sitting directly in a series
# folder are considered. Trailers already correctly placed inside trailers/ are out
# of range and cannot be picked up and re-moved.
#
# Collision Skip
# An existing destination is never overwritten — the source is left in place and
# counted as a conflict for review.
#
# Permission Matching on Created Directories
# mkdir as root would leave trailers/ as root-owned. It is chowned to
# PERMISSIONS_OWNER and chmodded to PERMISSIONS_DIR_MODE so it matches the rest of
# the library and does not become an exception the permissions job has to correct.
#
# Dry Run Support
# --dry-run reports every move and touches nothing.
#
# ==============================================================================================
# CONFIGURATION
# ==============================================================================================
#
@@ -50,6 +108,12 @@
# Host filesystem path to the TV library. Aliased by detect_hosts() →
# SONARR_TV_ROOT.
#
# master.conf
#
# PERMISSIONS_OWNER / PERMISSIONS_DIR_MODE
# Applied to each created trailers/ directory so it matches library convention.
# Shared with media_shares_permissions.sh. (defaults: nobody:users, 755)
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
@@ -74,6 +138,12 @@ parse_args "$@"
# ==============================================================================================
# ━━━ Setup ━━━
# ==============================================================================================
# Moves container-owned media files and chowns the trailers/ dirs it creates.
if [[ "$EUID" -ne 0 ]]; then
error "Must be run as root"
exit 1
fi
acquire_lock
# detect_hosts() sets MY_ID and aliases HOST*_SONARR_TV_ROOT → SONARR_TV_ROOT