fix: platform reads a manifest whose last line lacks a newline

`while IFS='=' read -r k v` drops an unterminated final line: read returns
1 at EOF even having filled k and v. A manifest ending `bootstrapped=...Z`
with no trailing \n rendered `RIG 1.2.3` with the timestamp silently gone
— the version read fine, so nothing looked wrong.

Guarded with `|| [ -n "$k" ]`, the same shape parse_users_file already
uses (lib/users-config.sh:47). #61's writer should not have to know
whether this reader tolerates a missing newline.

Also make human_b fall back like human_kb. With numfmt absent, memory
degraded to a raw number while disk printed 'unknown' beside it, from data
already in hand.

Both found in review of #74.

Refs #64
This commit is contained in:
dan-claude-bot 2026-07-20 00:00:57 +00:00
parent 75ef386601
commit 3cfbb8921c
2 changed files with 16 additions and 2 deletions

View file

@ -97,7 +97,10 @@ if DF="$(df -PB1 / 2>/dev/null)"; then
DISK_TOTAL="$(printf '%s\n' "$DF" | awk 'NR==2 {print $2}')" DISK_TOTAL="$(printf '%s\n' "$DF" | awk 'NR==2 {print $2}')"
DISK_FREE="$(printf '%s\n' "$DF" | awk 'NR==2 {print $4}')" DISK_FREE="$(printf '%s\n' "$DF" | awk 'NR==2 {print $4}')"
fi fi
human_b() { [ -n "${1:-}" ] && numfmt --to=iec-i "$1" 2>/dev/null || printf 'unknown'; } human_b() { # bytes -> IEC; falls back like human_kb rather than to 'unknown'
[ -n "${1:-}" ] || { printf 'unknown'; return 0; }
numfmt --to=iec-i "$1" 2>/dev/null || printf '%s B' "$1"
}
# --- virtualization --------------------------------------------------------- # --- virtualization ---------------------------------------------------------
# THE set -e TRAP: systemd-detect-virt exits NON-ZERO on bare metal while # THE set -e TRAP: systemd-detect-virt exits NON-ZERO on bare metal while
@ -139,7 +142,11 @@ MARKER="${RIG_ROLE_MARKER:-/etc/rig/role}"
manifest_field() { # $1 = key — empty when absent, unreadable or unset manifest_field() { # $1 = key — empty when absent, unreadable or unset
local k v local k v
[ -r "$MANIFEST" ] || return 0 [ -r "$MANIFEST" ] || return 0
while IFS='=' read -r k v; do # `|| [ -n "$k" ]` so a manifest whose last line lacks a trailing newline
# still yields that line: read returns 1 at EOF even having filled k/v.
# Same guard parse_users_file uses (lib/users-config.sh:47) — #61's writer
# should not have to know whether this reader tolerates a missing \n.
while IFS='=' read -r k v || [ -n "$k" ]; do
[ "$k" = "$1" ] || continue [ "$k" = "$1" ] || continue
printf '%s\n' "$v" printf '%s\n' "$v"
return 0 return 0

View file

@ -1017,6 +1017,13 @@ check "platform: reads the manifest version" 0 "9.9.9" \
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
check "platform: reads the manifest timestamp" 0 "bootstrapped 2026-07-19T14:24:51Z" \ check "platform: reads the manifest timestamp" 0 "bootstrapped 2026-07-19T14:24:51Z" \
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# ...including one whose last line has no trailing newline: `read` returns 1 at
# EOF even having filled the variables, so an unguarded loop drops that line
# silently — the timestamp would vanish while the version still rendered. #61's
# writer must not have to know this reader's tolerances (found in #74 review).
printf 'version=9.9.9\nbootstrapped=2026-07-19T14:24:51Z' > "$PLATWORK/manifest-nonl"
check "platform: reads a manifest with no trailing newline" 0 "bootstrapped 2026-07-19T14:24:51Z" \
env RIG_MANIFEST="$PLATWORK/manifest-nonl" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
printf 'role=dev class=human host=yes join=authkey\n' > "$PLATWORK/role" printf 'role=dev class=human host=yes join=authkey\n' > "$PLATWORK/role"
check "platform: renders the role marker's traits" 0 "dev (class=human host=yes join=authkey)" \ check "platform: renders the role marker's traits" 0 "dev (class=human host=yes join=authkey)" \
env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/role" "$ROOT/bin/rig" platform env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/role" "$ROOT/bin/rig" platform