the-custodian/docs/changes/2026-11-01-scanner-json-digest/native-r4/restore_modes.sh

48 lines
2 KiB
Bash

#!/bin/sh
# Restore only known group-write additions on unchanged, owned hook inodes.
set +vx
set -eu
export PATH=/usr/bin:/bin
records=$1
test "$(id -u)" = 1000
fail() { printf '{"mode_check":"%s","result":"refused"}\n' "$1"; exit 61; }
tab=$(printf '\t')
validate() {
mode=$1 sum=$2 path=$3
case "$mode" in 755|775) ;; *) fail unsupported-baseline-mode;; esac
case "$path" in /data/git/gitea-repositories/*/*.git/hooks/*) ;; *) fail path-scope;; esac
parent=${path%/*}
while test "$parent" != /data; do
test -d "$parent" && test ! -L "$parent" || fail parent-shape
parent=${parent%/*}
done
test -f "$path" && test ! -L "$path" || fail file-shape
test "$(stat -c %u "$path")" = 1000 && test "$(stat -c %g "$path")" = 1000 || fail file-owner
test "$(sha256sum "$path" | cut -d ' ' -f 1)" = "$sum" || fail file-hash
current=$(stat -c %a "$path")
test "$current" = "$mode" || { test "$mode" = 755 && test "$current" = 775; } || fail unexpected-mode
}
count=0
while IFS="$tab" read -r mode sum path; do validate "$mode" "$sum" "$path"; count=$((count+1)); done < "$records"
test "$count" -gt 0 || fail empty-scope
changed=0
while IFS="$tab" read -r mode sum path; do
validate "$mode" "$sum" "$path"
if test "$current" != "$mode"; then
inode=$(stat -c '%d:%i' "$path")
exec 7< "$path"
fd=/proc/self/fd/7
test "$(stat -L -c '%d:%i' "$fd")" = "$inode" || fail opened-inode
test "$(stat -L -c %u "$fd")" = 1000 && test "$(stat -L -c %g "$fd")" = 1000 || fail opened-owner
test "$(stat -L -c %a "$fd")" = 775 || fail opened-mode
test "$(sha256sum "$fd" | cut -d ' ' -f 1)" = "$sum" || fail opened-hash
chmod "$mode" "$fd"
test "$(stat -L -c %a "$fd")" = "$mode" || fail restored-mode
test -f "$path" && test ! -L "$path" && test "$(stat -c '%d:%i' "$path")" = "$inode" || fail final-inode
exec 7<&-
changed=$((changed+1))
fi
validate "$mode" "$sum" "$path"
test "$current" = "$mode" || fail final-mode
done < "$records"
printf '{"hook_modes_verified":%s,"group_write_additions_reversed":%s}\n' "$count" "$changed"