First version
This commit is contained in:
commit
243e92a9dd
84 files changed
+4012
No files matched your search
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
# Writes the contest image to USB sticks, all at the same time.
|
||||
# ERASES the listed sticks. Only USB disks are accepted.
|
||||
#
|
||||
# sudo ./write_sticks.sh build/acpc2026.qcow2 /dev/sdb /dev/sdc ...
|
||||
#
|
||||
# The image can be the qcow2 file of build.sh (the ICPC image it is based on
|
||||
# must stay where it was during the build) or a raw .img file.
|
||||
set -uo pipefail
|
||||
|
||||
usage() {
|
||||
echo "Usage: sudo $0 IMAGE DEVICE [DEVICE...]" >&2
|
||||
echo >&2
|
||||
echo "USB disks currently attached:" >&2
|
||||
lsblk -d -o NAME,SIZE,MODEL,TRAN | awk 'NR == 1 || $NF == "usb"' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
[ $# -ge 2 ] || usage
|
||||
IMG=$1
|
||||
shift
|
||||
[ -f "$IMG" ] || { echo "Image not found: $IMG" >&2; exit 1; }
|
||||
[ "$(id -u)" -eq 0 ] || { echo "Run this script as root (sudo)." >&2; exit 1; }
|
||||
command -v qemu-img >/dev/null || { echo "qemu-img is missing." >&2; exit 1; }
|
||||
|
||||
FORMAT=$(qemu-img info --output=json "$IMG" | python3 -I -c 'import json, sys; print(json.load(sys.stdin)["format"])')
|
||||
SIZE=$(qemu-img info --output=json "$IMG" | python3 -I -c 'import json, sys; print(json.load(sys.stdin)["virtual-size"])')
|
||||
|
||||
echo "Image: $IMG ($FORMAT, $((SIZE / 1000000000)) GB)"
|
||||
echo
|
||||
for dev in "$@"; do
|
||||
[ -b "$dev" ] || { echo "Not a disk: $dev" >&2; exit 1; }
|
||||
[ "$(lsblk -dn -o TYPE "$dev")" = disk ] || { echo "Not a whole disk: $dev" >&2; exit 1; }
|
||||
[ "$(lsblk -dn -o TRAN "$dev")" = usb ] || { echo "Not a USB disk, refused: $dev" >&2; exit 1; }
|
||||
if lsblk -n -o MOUNTPOINTS "$dev" | grep -q '[^[:space:]]'; then
|
||||
echo "A partition of $dev is mounted, unmount it first." >&2
|
||||
exit 1
|
||||
fi
|
||||
devsize=$(blockdev --getsize64 "$dev")
|
||||
[ "$devsize" -ge "$SIZE" ] || { echo "$dev is too small ($((devsize / 1000000000)) GB)" >&2; exit 1; }
|
||||
echo " $dev $(lsblk -dn -o SIZE,MODEL "$dev")"
|
||||
done
|
||||
echo
|
||||
echo "ALL DATA ON THESE STICKS WILL BE ERASED."
|
||||
read -rp "Type ERASE to continue: " answer
|
||||
[ "$answer" = ERASE ] || { echo "Cancelled."; exit 1; }
|
||||
|
||||
logdir=$(mktemp -d)
|
||||
write_one() {
|
||||
local dev=$1 start=$(date +%s)
|
||||
if qemu-img convert -n -f "$FORMAT" -O raw -t none "$IMG" "$dev" > "$logdir/$(basename "$dev").log" 2>&1; then
|
||||
sync
|
||||
echo " done $dev ($(( $(date +%s) - start )) s)"
|
||||
else
|
||||
echo " FAILED $dev (see $logdir/$(basename "$dev").log)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Writing..."
|
||||
fail=0
|
||||
pids=()
|
||||
for dev in "$@"; do
|
||||
write_one "$dev" &
|
||||
pids+=($!)
|
||||
done
|
||||
for pid in "${pids[@]}"; do wait "$pid" || fail=1; done
|
||||
|
||||
if [ $fail -eq 0 ]; then
|
||||
echo "All sticks are written."
|
||||
rm -rf "$logdir"
|
||||
else
|
||||
echo "At least one stick failed. Logs: $logdir"
|
||||
fi
|
||||
exit $fail
|
||||
Reference in new issue
Block a user