b9874d0941
Add redbear-usb-storage-check in-guest binary that validates USB mass storage read and write I/O: discovers /scheme/disk/ devices, writes a test pattern to sector 2048, reads it back, verifies match, restores original content. Updates test-usb-storage-qemu.sh with write-proof verification step. Includes all accumulated Red Bear OS work: kernel patches, relibc patches, driver infrastructure, DRM/GPU, KDE recipes, firmware, validation tooling, build system hardening, and documentation.
167 lines
5.0 KiB
Bash
Executable File
167 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# repair-archive-format.sh — Normalize unversioned/old-format archives to standard format.
|
|
#
|
|
# Standard format: {cat}-{pkg}-v{version}-patched.tar.gz containing:
|
|
# source/ — recipe source tree
|
|
# recipe.toml — recipe metadata
|
|
#
|
|
# Repairs archives that:
|
|
# 1. Have raw repo content at root (not inside source/ dir)
|
|
# 2. Missing recipe.toml
|
|
# 3. Include build artifacts (source/target/)
|
|
#
|
|
# Usage:
|
|
# ./local/scripts/repair-archive-format.sh [--dry-run]
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
POOL="$PROJECT_ROOT/sources/x86_64-unknown-redox"
|
|
WORK="/tmp/redbear-archive-repair-$$"
|
|
DRY_RUN=0
|
|
|
|
[ "${1:-}" = "--dry-run" ] && DRY_RUN=1
|
|
|
|
GREEN='\033[1;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
mkdir -p "$WORK"
|
|
|
|
repaired=0
|
|
skipped=0
|
|
for archive in "$POOL"/*.tar.gz; do
|
|
name=$(basename "$archive")
|
|
|
|
# Skip already properly versioned (has -v HEX or -v DIGITS)
|
|
if echo "$name" | grep -qE '\-v[a-f0-9]{7,}|\-v\d+\.'; then
|
|
skipped=$((skipped + 1))
|
|
continue
|
|
fi
|
|
|
|
# Extract category and package from filename: {cat}-{pkg}-*.tar.gz
|
|
# For unversioned: core-base.tar.gz -> cat=core, pkg=base
|
|
# For vunknown: core-base-vunknown-patched.tar.gz -> cat=core, pkg=base
|
|
base="${name%.tar.gz}"
|
|
base="${base%-patched}"
|
|
base="${base%-vunknown}"
|
|
cat_name=$(echo "$base" | cut -d- -f1)
|
|
pkg_name=$(echo "$base" | cut -d- -f2-)
|
|
|
|
# Find the recipe.toml
|
|
recipe=""
|
|
for candidate in \
|
|
"$PROJECT_ROOT/recipes/$cat_name/$pkg_name/recipe.toml" \
|
|
"$PROJECT_ROOT/local/recipes/$cat_name/$pkg_name/recipe.toml"; do
|
|
[ -f "$candidate" ] && recipe="$candidate" && break
|
|
done
|
|
|
|
if [ -z "$recipe" ]; then
|
|
echo -e "${YELLOW}SKIP${NC} $name (no recipe.toml found in recipes/)"
|
|
continue
|
|
fi
|
|
|
|
# Determine version
|
|
version=$(python3 -c "
|
|
import tomllib, subprocess
|
|
from pathlib import Path
|
|
with open('$recipe', 'rb') as f:
|
|
data = tomllib.load(f)
|
|
src = data.get('source', {})
|
|
if not isinstance(src, dict):
|
|
print('unknown')
|
|
elif 'tar' in src:
|
|
import re
|
|
m = re.search(r'/?v?(\d+\.\d+(?:\.\d+)?)(?:\.tar|/$)', src['tar'])
|
|
print(m.group(1) if m else 'unknown')
|
|
elif 'git' in src:
|
|
rev = src.get('rev', '')
|
|
if rev:
|
|
print(rev[:7])
|
|
else:
|
|
pkg_dir = Path('$recipe').parent / 'source'
|
|
if (pkg_dir / '.git').exists():
|
|
r = subprocess.run(['git','-C',str(pkg_dir),'rev-parse','--short','HEAD'],
|
|
capture_output=True, text=True)
|
|
print(r.stdout.strip() if r.returncode == 0 else 'unknown')
|
|
else:
|
|
print('unknown')
|
|
else:
|
|
print('unknown')
|
|
" 2>/dev/null || echo "unknown")
|
|
|
|
new_name="${cat_name}-${pkg_name}-v${version}-patched.tar.gz"
|
|
new_path="$POOL/$new_name"
|
|
|
|
if [ -f "$new_path" ] && [ "$new_name" != "$name" ]; then
|
|
echo -e "${YELLOW}SKIP${NC} $name (target $new_name already exists)"
|
|
continue
|
|
fi
|
|
|
|
# Check current format
|
|
has_source=$(tar tf "$archive" 2>/dev/null | grep -c '^source/' || true)
|
|
has_recipe=$(tar tf "$archive" 2>/dev/null | grep -c '^recipe.toml$' || true)
|
|
has_target=$(tar tf "$archive" 2>/dev/null | grep -c 'source/target/' || true)
|
|
|
|
if [ "$has_source" -gt 0 ] && [ "$has_recipe" -gt 0 ] && [ "$has_target" -eq 0 ] && [ "$new_name" = "$name" ]; then
|
|
skipped=$((skipped + 1))
|
|
continue
|
|
fi
|
|
|
|
echo -e "${GREEN}REPAIR${NC} $name -> $new_name (v$version)"
|
|
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
echo " [dry-run] would repackage: source/=$has_source recipe=$has_recipe target=$has_target"
|
|
repaired=$((repaired + 1))
|
|
continue
|
|
fi
|
|
|
|
# Create temp dir for repackaging
|
|
tmpdir="$WORK/$base"
|
|
rm -rf "$tmpdir"
|
|
mkdir -p "$tmpdir/source"
|
|
|
|
# Extract archive
|
|
tar xzf "$archive" -C "$tmpdir" 2>/dev/null
|
|
|
|
# If content is at root (not in source/), move it into source/
|
|
if [ "$has_source" -eq 0 ]; then
|
|
for item in "$tmpdir"/*; do
|
|
[ "$item" = "$tmpdir/source" ] && continue
|
|
mv "$item" "$tmpdir/source/" 2>/dev/null || true
|
|
done
|
|
fi
|
|
|
|
# Add recipe.toml if missing
|
|
if [ "$has_recipe" -eq 0 ]; then
|
|
cp "$recipe" "$tmpdir/recipe.toml"
|
|
fi
|
|
|
|
# Strip build artifacts
|
|
rm -rf "$tmpdir/source/target" 2>/dev/null || true
|
|
|
|
# Create new archive
|
|
tar czf "$new_path" -C "$tmpdir" source recipe.toml 2>/dev/null
|
|
|
|
if [ "$new_name" != "$name" ]; then
|
|
rm -f "$archive"
|
|
fi
|
|
|
|
repaired=$((repaired + 1))
|
|
done
|
|
|
|
# Update BLAKE3SUMS for repaired archives
|
|
if [ "$DRY_RUN" -eq 0 ] && [ "$repaired" -gt 0 ]; then
|
|
(cd "$POOL" && b3sum *.tar.gz 2>/dev/null) > "$POOL/../redbear-0.1.0/BLAKE3SUMS"
|
|
fi
|
|
|
|
rm -rf "$WORK"
|
|
|
|
echo ""
|
|
echo "========================================="
|
|
echo " Repair complete"
|
|
echo " Repaired: $repaired"
|
|
echo " Skipped: $skipped"
|
|
echo "========================================="
|