#!/usr/bin/env bash # Prepare the nested targets required beneath the server profile's writable Pi-state parent bind. set -euo pipefail fail() { printf 'prepare-server-pi-state: %s\n' "$*" >&2 exit 2 } [[ $# -ge 1 && $# -le 3 ]] \ || fail "usage: $0 ABSOLUTE_PI_STATE_ROOT [NUMERIC_UID [NUMERIC_GID]]" pi_state_root="$1" owner="${2:-$(id -u)}" group="${3:-$(id -g)}" [[ "$pi_state_root" == /* && "$pi_state_root" != / && "$pi_state_root" != */ \ && "$pi_state_root" != *//* && "$pi_state_root/" != */../* \ && "$pi_state_root/" != */./* ]] \ || fail "Pi-state root must be an absolute canonical non-root path" [[ "$owner" =~ ^[0-9]+$ && "$group" =~ ^[0-9]+$ ]] \ || fail "owner and group must be numeric" [[ ! -L "$pi_state_root" ]] || fail "Pi-state root must not be a symlink" if [[ "$(id -u)" -ne 0 && ( "$owner" != "$(id -u)" || "$group" != "$(id -g)" ) ]]; then fail "non-root execution may prepare only its own UID/GID" fi ensure_directory() { local path="$1" mode="$2" if [[ -e "$path" && ( ! -d "$path" || -L "$path" ) ]]; then fail "expected a real directory: $path" fi mkdir -p "$path" chmod "$mode" "$path" if [[ "$(id -u)" -eq 0 ]]; then chown "$owner:$group" "$path" fi } ensure_target() { local target="$1" temporary="" if [[ -e "$target" || -L "$target" ]]; then [[ -f "$target" && ! -L "$target" ]] || fail "expected a regular target file: $target" else temporary="$(mktemp "${target%/*}/.${target##*/}.XXXXXX")" trap '[[ -z "${temporary:-}" ]] || rm -f "$temporary"' RETURN chmod 0600 "$temporary" if [[ "$(id -u)" -eq 0 ]]; then chown "$owner:$group" "$temporary" fi if ! ln "$temporary" "$target" 2>/dev/null; then [[ -f "$target" && ! -L "$target" ]] \ || fail "could not atomically create target: $target" fi rm -f "$temporary" temporary="" trap - RETURN fi chmod 0600 "$target" if [[ "$(id -u)" -eq 0 ]]; then chown "$owner:$group" "$target" fi } ensure_directory "$pi_state_root" 0750 ensure_directory "$pi_state_root/agent" 0700 for name in auth.json models.json settings.json; do ensure_target "$pi_state_root/agent/$name" done printf 'Prepared server Pi-state targets under %s for %s:%s.\n' \ "$pi_state_root" "$owner" "$group"