osi-tools/mkosi.sh

115 lines
2.9 KiB
Bash
Raw Normal View History

2018-07-25 19:23:05 +00:00
#!/usr/bin/env bash
# 2018 Luke Shumaker
declare -r NAME=mkosi
declare -r VERSION=20180725
# Why is this different than mkosi[1]?
#
# - mkosi claims to be "legacy-free"--but they call everything that's
# not systemd "legacy"; that clearly won't do for creating OpenRC or
# GNU Shepherd images.
#
# - mkosi claims to be "legacy-free", only supporting GPT
# disk-labels--but btrfs can be booted directly, without a separate
# disk-label, or a separate ESP partition. To a btrfs disk, GPT/ESP
# is legacy.
#
# - Using a raw btrfs disk means that it can easily be mounted without
# first disecting the disk-label.
#
# [1]: https://github.com/systemd/mkosi
print() {
# shellcheck disable=SC2059
printf "$(gettext -- "$1")\\n" "${@:2}"
}
error() {
local msg
msg="$(print "${@:2}")"
printf '%s: %s\n' "${0##*/}" "$msg"
if (( $1 != 0 )); then
exit "$1"
fi
}
main() {
set -euE
local arg_mode=outside
local arg_mountpoint=
local arg_size=1G
local arg_file
local args
if ! args="$(getopt -n "${0##*/}" -o "Vhs" -l "inside:,version,help,size" -- "$@")"; then
arg_mode=error
else
eval "args=($args)"
set -- "${args[@]}"
while true; do
case "$1" in
--inside) shift; arg_mode=inside; arg_mountpoint=$1; shift;;
-V|--version) shift; arg_mode=version;;
-h|--help) shift; arg_mode=usage;;
-s|--size) shift; arg_size=$1;;
--) shift; break;;
esac
done
if (( $# != 1 )); then
if (( $# == 0 )); then
error 0 "Expected 1 positional argument, got none"
else
error 0 "Expected 1 positional argument, got %d: %s" "$#" "${@@Q}"
fi
arg_mode=error
else
arg_file=$1
fi
fi
case "$arg_mode" in
error) print "Try '%q --help' for more information" "${0##*/}" >&2; return 2;;
version)
print "%s (notsystemd) %s" "$NAME" "$VERSION"
return 0
;;
usage)
print 'Usage: %s [OPTIONS]' "${0##*/} FILENAME.IMG"
print 'Make Operating System Image'
echo
print 'Create a mountable, bootable OS image.'
echo
print 'OPTIONS:'
# --inside is internal-only; undocumented
print ' -s SIZE, --size=SIZE set the size of the image (default: 1G)'
echo
print ' -h, --help display this help'
print ' -V, --version output version information'
return 0
;;
# main code starts here
outside)
if (( UID != 0 )); then
error 2 "Must be invoked as root."
fi
arg_mountpoint=$(mktemp -dt -- "${0##*/}.XXXXXXXXXX")
# shellcheck disable=SC2064
trap "rmdir -- ${arg_mountpoint@Q}" EXIT
unshare --mount -- "${BASH_SOURCE[0]}" --inside="$arg_mountpoint" "${args[@]}"
;;
inside) # just keep reading...
mount --make-rslave /
truncate --size="$arg_size" -- "$arg_file"
mkfs.btrfs -- "$arg_file"
mount "$arg_file" "$arg_mountpoint"
pacstrap -M -C /usr/share/pacman/defaults/pacman.conf.x86_64 -- "$arg_mountpoint" base grub
arch-chroot -- "$arg_mountpoint" bash -i
;;
*) error 'Internal error. The programmer writing this tool screwed up.'; exit 1;;
esac
}
main "$@"