floppy-utils/check-deps.sh
Greg Gauthier 34aeb7bc0d feat(floppy-utils): add bash toolkit for retro floppy disk operations
Introduce floppy-utils: a CLI for creating, editing, archiving, and
restoring floppy disk images on Linux with USB floppy drive support.
Includes main floppy command, legacy wrappers, dependency checker,
install script, and comprehensive documentation.
2026-06-01 20:54:30 +01:00

226 lines
5.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Verify dependencies for floppy-utils on Debian-based systems; optionally install via apt.
set -euo pipefail
INSTALL=0
QUIET=0
usage() {
cat <<'EOF'
Usage: check-deps.sh [OPTIONS]
Check that base tools required by floppy-utils are available.
On Debian, Ubuntu, Raspberry Pi OS, and derivatives, missing packages can be
installed with apt when --install is passed.
Options:
--install, -i Install missing packages (requires apt and root/sudo)
--quiet, -q Only print errors and the install command
-h, --help Show this help
Examples:
./check-deps.sh
./check-deps.sh --install
sudo ./check-deps.sh -i
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--install|-i) INSTALL=1; shift ;;
--quiet|-q) QUIET=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "check-deps.sh: unknown option: $1" >&2; usage >&2; exit 2 ;;
esac
done
log() {
[[ "$QUIET" -eq 0 ]] && echo "$@"
}
warn() {
echo "check-deps.sh: $*" >&2
}
die() {
warn "$*"
exit 1
}
is_debian_like() {
if [[ -f /etc/debian_version ]]; then
return 0
fi
if [[ -f /etc/os-release ]]; then
# shellcheck source=/dev/null
source /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
debian:*|*debian*|ubuntu:*|*ubuntu*|raspbian:*|linuxmint:*|pop:*|elementary:*|kali:*|devuan:*)
return 0
;;
esac
fi
return 1
}
os_description() {
if [[ -f /etc/os-release ]]; then
# shellcheck source=/dev/null
source /etc/os-release
printf '%s %s\n' "${NAME:-Linux}" "${VERSION_ID:-}"
elif [[ -f /etc/debian_version ]]; then
printf 'Debian %s\n' "$(cat /etc/debian_version)"
else
echo "Unknown"
fi
}
# command -> Debian package providing it
declare -A CMD_PKG=(
[lsblk]=util-linux
[blockdev]=util-linux
[losetup]=util-linux
[findmnt]=util-linux
[fdisk]=util-linux
[blkid]=util-linux
[mount]=mount
[umount]=mount
[dd]=coreutils
[readlink]=coreutils
[mkfs.vfat]=dosfstools
[sudo]=sudo
[udisksctl]=udisks2
[udevadm]=udev
[eject]=eject
)
REQUIRED_CMDS=(
lsblk blockdev losetup findmnt blkid mount umount dd readlink mkfs.vfat
)
RECOMMENDED_CMDS=(
sudo udisksctl udevadm eject fdisk
)
have_cmd() {
command -v "$1" >/dev/null 2>&1
}
packages_for_cmds() {
local -A seen=()
local cmd pkg
for cmd in "$@"; do
pkg="${CMD_PKG[$cmd]:-}"
[[ -n "$pkg" && -z "${seen[$pkg]:-}" ]] || continue
seen[$pkg]=1
printf '%s\n' "$pkg"
done
}
check_cmds() {
local label="$1"
local required="$2"
shift 2
local cmd
local -a missing=()
log "$label"
for cmd in "$@"; do
if have_cmd "$cmd"; then
log " OK $cmd"
else
if [[ "$required" -eq 1 ]]; then
log " MISS $cmd (required)"
else
log " MISS $cmd (recommended)"
fi
missing+=("$cmd")
fi
done
log ""
MISSING_RESULT=("${missing[@]}")
}
run_apt_install() {
local -a packages=("$@")
[[ ${#packages[@]} -gt 0 ]] || return 0
if ! command -v apt-get >/dev/null 2>&1; then
die "apt-get not found; install manually: ${packages[*]}"
fi
local -a apt_cmd=(apt-get)
if [[ "$(id -u)" -ne 0 ]]; then
command -v sudo >/dev/null 2>&1 || die "root or sudo required to install: ${packages[*]}"
apt_cmd=(sudo apt-get)
fi
log "Installing: ${packages[*]}"
"${apt_cmd[@]}" update -qq
DEBIAN_FRONTEND=noninteractive "${apt_cmd[@]}" install -y --no-install-recommends "${packages[@]}"
}
main() {
local -a missing_required=() missing_recommended=() packages=()
local debian=0
log "floppy-utils dependency check"
log "OS: $(os_description)"
if is_debian_like; then
debian=1
log "Debian-based system detected."
else
warn "Not a Debian-based system — will check commands only (no apt install)."
fi
log ""
check_cmds "Required commands:" 1 "${REQUIRED_CMDS[@]}"
missing_required=("${MISSING_RESULT[@]}")
check_cmds "Recommended commands:" 0 "${RECOMMENDED_CMDS[@]}"
missing_recommended=("${MISSING_RESULT[@]}")
if [[ ${#missing_required[@]} -eq 0 && ${#missing_recommended[@]} -eq 0 ]]; then
log "All required and recommended commands are available."
exit 0
fi
if [[ ${#missing_required[@]} -gt 0 ]]; then
log "Missing required: ${missing_required[*]}"
fi
if [[ ${#missing_recommended[@]} -gt 0 ]]; then
log "Missing recommended: ${missing_recommended[*]}"
fi
mapfile -t packages < <(packages_for_cmds "${missing_required[@]}" "${missing_recommended[@]}")
if [[ ${#packages[@]} -gt 0 ]]; then
log "Debian packages: ${packages[*]}"
fi
if [[ "$INSTALL" -eq 1 ]]; then
[[ "$debian" -eq 1 ]] || die "refusing --install on non-Debian system"
run_apt_install "${packages[@]}"
log ""
log "Re-checking..."
INSTALL=0
main
return
fi
if [[ "$debian" -eq 1 && ${#packages[@]} -gt 0 ]]; then
log ""
log "To install:"
log " sudo ./check-deps.sh --install"
log " # or: sudo apt-get install -y ${packages[*]}"
fi
if [[ ${#missing_required[@]} -gt 0 ]]; then
die "required dependencies missing"
fi
warn "recommended tools missing — floppy-utils works with reduced functionality"
exit 0
}
main