2018-07-25 19:23:05 +00:00
|
|
|
#!/usr/bin/env bash
|
2018-08-18 18:42:42 +00:00
|
|
|
# Copyright (C) 2018 Luke Shumaker
|
2023-10-23 22:28:09 +00:00
|
|
|
# Copyright (C) 2023 Umorpha Systems
|
2018-08-18 18:42:42 +00:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
2018-08-06 01:56:44 +00:00
|
|
|
declare -r NAME=osi-mk
|
2023-10-23 22:19:22 +00:00
|
|
|
declare -r VERSION=20231023
|
2018-07-25 19:23:05 +00:00
|
|
|
|
|
|
|
# Why is this different than mkosi[1]?
|
|
|
|
#
|
|
|
|
# - mkosi claims to be "legacy-free"--but they call everything that's
|
2018-08-06 00:09:42 +00:00
|
|
|
# not systemd "legacy"; that clearly won't do for creating OpenRC
|
|
|
|
# images.
|
2018-07-25 19:23:05 +00:00
|
|
|
#
|
|
|
|
# - 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
|
2023-10-25 11:04:49 +00:00
|
|
|
# first dissecting the disk-label.
|
2018-07-25 19:23:05 +00:00
|
|
|
#
|
|
|
|
# [1]: https://github.com/systemd/mkosi
|
|
|
|
|
2018-08-12 21:53:08 +00:00
|
|
|
set -euE -o pipefail
|
2018-08-16 05:32:59 +00:00
|
|
|
source ./lib/osi.sh
|
2018-08-06 01:49:45 +00:00
|
|
|
|
|
|
|
loaded_modules=()
|
2018-08-06 04:02:37 +00:00
|
|
|
load_module() {
|
2018-08-06 01:49:45 +00:00
|
|
|
local module
|
2018-08-06 04:02:37 +00:00
|
|
|
if ! [[ -f $1 ]]; then
|
2023-10-25 10:59:35 +00:00
|
|
|
error $EXIT_INVALIDARGUMENT 'Module does not exist: %s' "$1"
|
2018-08-06 04:02:37 +00:00
|
|
|
fi
|
2018-08-06 01:49:45 +00:00
|
|
|
module="$(realpath -- "$1")"
|
|
|
|
if in_array "$module" "${loaded_modules[@]}"; then
|
2018-08-06 04:02:37 +00:00
|
|
|
return 0
|
2018-08-06 01:49:45 +00:00
|
|
|
fi
|
2018-08-06 04:02:37 +00:00
|
|
|
loaded_modules+=("$module")
|
2023-10-24 21:42:25 +00:00
|
|
|
# shellcheck source=/dev/null
|
2018-08-06 04:02:37 +00:00
|
|
|
source "$1"
|
2018-08-06 01:49:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 21:53:08 +00:00
|
|
|
osi-mk:genfstab() {
|
|
|
|
local arg_mountpoint=$1
|
|
|
|
genfstab -t uuid "$arg_mountpoint" > "${arg_mountpoint}/etc/fstab"
|
|
|
|
}
|
|
|
|
|
2018-08-06 01:56:44 +00:00
|
|
|
osi-mk:directories() {
|
2018-08-06 01:49:45 +00:00
|
|
|
local arg_mountpoint=$1
|
|
|
|
local spec outside inside
|
2018-08-06 04:02:37 +00:00
|
|
|
for spec in "${arg_directories[@]}"; do
|
2018-08-06 01:49:45 +00:00
|
|
|
outside="${spec%:*}"
|
|
|
|
inside="${spec#"${outside}:"}"
|
2018-08-13 01:03:56 +00:00
|
|
|
# TODO: maybe rsync would be better?
|
|
|
|
if [[ -d "${arg_mountpoint}/${inside}" ]]; then
|
2018-08-13 05:16:36 +00:00
|
|
|
print 'Removing existing %q:%q' "$arg_file" "$inside"
|
2018-08-16 05:32:59 +00:00
|
|
|
rm -rf -- "${arg_mountpoint:?}/${inside}"
|
2018-08-13 01:03:56 +00:00
|
|
|
fi
|
2018-08-06 04:02:37 +00:00
|
|
|
mkdir -p -- "$(dirname -- "${arg_mountpoint}/${inside}")"
|
2018-08-13 05:16:36 +00:00
|
|
|
print 'Copying %q to %q:%q' "$outside" "$arg_file" "$inside"
|
2018-08-13 01:03:56 +00:00
|
|
|
cp -aT -- "$outside" "${arg_mountpoint}/${inside}"
|
2018-08-06 01:49:45 +00:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2018-08-12 21:53:08 +00:00
|
|
|
osi-mk:grub-install() {
|
|
|
|
local arg_mountpoint=$1
|
|
|
|
cat <<-'EOT' >> "$arg_mountpoint/etc/default/grub"
|
|
|
|
GRUB_TIMEOUT=0
|
|
|
|
GRUB_DEFAULT=1 # Use the fallback initramfs, to get all drivers
|
|
|
|
EOT
|
2018-08-16 05:32:59 +00:00
|
|
|
# shellcheck disable=SC2016
|
2018-08-12 21:53:08 +00:00
|
|
|
arch-chroot -- "$arg_mountpoint" sh -c \
|
|
|
|
'grub-install "$(awk '\''$2 == "/" { print $1 }'\'' </proc/mounts)"'
|
2018-08-14 20:53:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
osi-mk:grub-mkconfig() {
|
|
|
|
local arg_mountpoint=$1
|
2018-08-12 21:53:08 +00:00
|
|
|
arch-chroot -- "$arg_mountpoint" grub-mkconfig -o /boot/grub/grub.cfg
|
|
|
|
}
|
|
|
|
|
2018-07-25 19:23:05 +00:00
|
|
|
main() {
|
2018-08-14 20:19:07 +00:00
|
|
|
local arg_orig=("$@")
|
2018-07-25 19:23:05 +00:00
|
|
|
local arg_mode=outside
|
|
|
|
local arg_mountpoint=
|
2018-08-16 05:17:54 +00:00
|
|
|
local arg_size=
|
2018-08-12 02:35:52 +00:00
|
|
|
local arg_edit=false
|
2018-08-14 20:04:07 +00:00
|
|
|
local arg_edit_base=
|
2018-08-06 01:49:45 +00:00
|
|
|
|
|
|
|
local arg_directories=()
|
2018-08-06 00:09:42 +00:00
|
|
|
local arg_modules=()
|
2018-08-06 01:49:45 +00:00
|
|
|
local arg_packages=()
|
2018-08-18 21:50:57 +00:00
|
|
|
local arg_package_files=()
|
2018-08-06 01:49:45 +00:00
|
|
|
|
2018-07-25 19:23:05 +00:00
|
|
|
local args
|
2018-08-18 21:50:57 +00:00
|
|
|
if ! args="$(getopt -n "${0##*/}" -o "s:e::d:m:p:P:hV" -l "inside:,size:,edit::,directory:,module:,package:,package-file:,help,version" -- "$@")"; then
|
2018-07-25 19:23:05 +00:00
|
|
|
arg_mode=error
|
|
|
|
else
|
2018-08-14 20:19:07 +00:00
|
|
|
eval "set -- $args"
|
2018-07-25 19:23:05 +00:00
|
|
|
while true; do
|
|
|
|
case "$1" in
|
|
|
|
--inside) shift; arg_mode=inside; arg_mountpoint=$1; shift;;
|
2018-08-05 02:31:38 +00:00
|
|
|
-s|--size) shift; arg_size=$1; shift;;
|
2018-08-14 20:04:07 +00:00
|
|
|
-e|--edit) shift; arg_edit=true; arg_edit_base=$1; shift;;
|
2018-08-06 01:49:45 +00:00
|
|
|
|
2018-08-06 04:02:37 +00:00
|
|
|
-d|--directory) shift; arg_directories+=("$1"); shift;;
|
2018-08-06 00:09:42 +00:00
|
|
|
-m|--module) shift; arg_modules+=("$1"); shift;;
|
2018-08-06 04:02:37 +00:00
|
|
|
-p|--package) shift; arg_packages+=("$1"); shift;;
|
2018-08-18 21:50:57 +00:00
|
|
|
-P|--package-file) shift; arg_package_files+=("$1"); shift;;
|
2018-08-06 01:49:45 +00:00
|
|
|
|
|
|
|
-V|--version) shift; arg_mode=version;;
|
|
|
|
-h|--help) shift; arg_mode=usage;;
|
2018-07-25 19:23:05 +00:00
|
|
|
--) shift; break;;
|
2023-10-25 10:59:35 +00:00
|
|
|
*) error $EXIT_FAILURE 'Internal error. The programmer writing this tool screwed up.';;
|
2018-07-25 19:23:05 +00:00
|
|
|
esac
|
|
|
|
done
|
2018-08-06 00:09:42 +00:00
|
|
|
case "$arg_mode" in
|
|
|
|
outside|inside)
|
|
|
|
if (( $# != 1 )); then
|
|
|
|
if (( $# == 0 )); then
|
|
|
|
error 0 "Expected 1 positional argument, got none"
|
|
|
|
else
|
2018-08-14 20:17:31 +00:00
|
|
|
error 0 "Expected 1 positional argument, got %d: %s" "$#" "${*@Q}"
|
2018-08-06 00:09:42 +00:00
|
|
|
fi
|
|
|
|
arg_mode=error
|
|
|
|
else
|
|
|
|
arg_file=$1
|
|
|
|
fi
|
2018-08-12 22:15:43 +00:00
|
|
|
for module in "${arg_modules[@]}"; do
|
|
|
|
if ! [[ -f $module ]]; then
|
|
|
|
error 0 'Module does not exist: %s' "$module"
|
|
|
|
arg_mode=error
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
for dirspec in "${arg_directories[@]}"; do
|
|
|
|
if ! [[ -d "${dirspec%:*}" ]]; then
|
|
|
|
error 0 'Directory does not exist: %s' "${dirspec%:*}"
|
|
|
|
arg_mode=error
|
|
|
|
fi
|
|
|
|
done
|
2018-08-18 21:50:57 +00:00
|
|
|
for package_file in "${arg_package_files[@]}"; do
|
|
|
|
if ! [[ -f "$package_file" ]]; then
|
|
|
|
error 0 'Package file does not exist: %s' "$package_file"
|
|
|
|
arg_mode=error
|
|
|
|
fi
|
|
|
|
done
|
2018-08-16 05:42:04 +00:00
|
|
|
if [[ $arg_mode = outside ]]; then
|
|
|
|
if [[ ( $arg_edit = false || -n $arg_edit_base ) && -e $arg_file ]]; then
|
2023-10-25 10:59:35 +00:00
|
|
|
error $EXIT_INVALIDARGUMENT 'Image file already exists, refusing to overwrite: %s' "$arg_file"
|
2018-08-16 05:17:54 +00:00
|
|
|
fi
|
2018-08-16 05:42:04 +00:00
|
|
|
if $arg_edit; then
|
|
|
|
if ! [[ -f ${arg_edit_base:-$arg_file} ]]; then
|
2023-10-25 10:59:35 +00:00
|
|
|
error $EXIT_INVALIDARGUMENT 'Image must already exist to --edit: %s' "${arg_edit_base:-$arg_file}"
|
2018-08-16 05:42:04 +00:00
|
|
|
fi
|
|
|
|
else
|
|
|
|
if [[ -z $arg_size ]]; then
|
2023-10-25 10:59:35 +00:00
|
|
|
error $EXIT_INVALIDARGUMENT 'Must specify --size when creating a new image'
|
2018-08-16 05:42:04 +00:00
|
|
|
fi
|
2018-08-16 05:17:54 +00:00
|
|
|
fi
|
|
|
|
fi
|
2018-08-06 00:09:42 +00:00
|
|
|
;;
|
|
|
|
esac
|
2018-07-25 19:23:05 +00:00
|
|
|
fi
|
|
|
|
case "$arg_mode" in
|
2023-10-25 10:59:35 +00:00
|
|
|
error)
|
|
|
|
print "Try '%q --help' for more information" "${0##*/}" >&2
|
|
|
|
return $EXIT_INVALIDARGUMENT
|
|
|
|
;;
|
2018-07-25 19:23:05 +00:00
|
|
|
version)
|
2023-10-23 22:28:09 +00:00
|
|
|
print "%s (osi-tools) %s" "$NAME" "$VERSION"
|
2023-10-25 10:59:35 +00:00
|
|
|
return $EXIT_SUCCESS
|
2018-07-25 19:23:05 +00:00
|
|
|
;;
|
|
|
|
usage)
|
2018-08-12 20:35:56 +00:00
|
|
|
print 'Usage: %s [OPTIONS] FILENAME.img' "${0##*/}"
|
|
|
|
print 'Operating System Image: Make'
|
2018-07-25 19:23:05 +00:00
|
|
|
echo
|
|
|
|
print 'Create a mountable, bootable OS image.'
|
|
|
|
echo
|
|
|
|
print 'OPTIONS:'
|
2018-08-18 21:50:57 +00:00
|
|
|
# 000000000011111111112222222222333333333344444444445555555555666666666677777777778
|
|
|
|
# 012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
print ' -s SIZE, --size=SIZE set the size of the image'
|
|
|
|
print ' -e[BASE.img], --edit[=BASE.img] edit an existing image'
|
2018-07-25 19:23:05 +00:00
|
|
|
# --inside is internal-only; undocumented
|
2018-08-06 01:49:45 +00:00
|
|
|
echo
|
2018-08-18 21:50:57 +00:00
|
|
|
print ' -d OUTSIDE:INSIDE, --directory=OUTSIDE:INSIDE include the given directory'
|
|
|
|
print ' -m MOD.sh, --module=MOD.sh include the given module'
|
|
|
|
print ' -p PKGNAME, --package=PKGNAME include the given package (or group)'
|
|
|
|
print ' -P PKG.pkg.tar.xz, --package-file=PKG.pkg.tar.xz include the given package file'
|
2018-07-25 19:23:05 +00:00
|
|
|
echo
|
2018-08-18 21:50:57 +00:00
|
|
|
print ' -h, --help display this help'
|
|
|
|
print ' -V, --version output version information'
|
2023-10-25 10:59:35 +00:00
|
|
|
return $EXIT_SUCCESS
|
2018-07-25 19:23:05 +00:00
|
|
|
;;
|
|
|
|
|
|
|
|
# main code starts here
|
2023-10-25 11:04:49 +00:00
|
|
|
outside) # the part that runs as a normal user without the image mounted
|
2023-10-24 21:42:25 +00:00
|
|
|
gprintf -v prefix '%s [format]' "$NAME"
|
2018-08-16 06:00:07 +00:00
|
|
|
{
|
|
|
|
if $arg_edit; then
|
|
|
|
if [[ -n $arg_edit_base ]]; then
|
2018-08-14 20:04:07 +00:00
|
|
|
cp -T -- "$arg_edit_base" "$arg_file"
|
|
|
|
btrfstune -fu "$arg_file"
|
2018-08-16 06:00:07 +00:00
|
|
|
fi
|
|
|
|
if [[ -n $arg_size ]]; then
|
|
|
|
# Calculate sizes in exact bytes now, to avoid any discrepancies
|
|
|
|
# between truncate(1) and btrfs-filesystem(8).
|
|
|
|
# Use truncate(1) to do this. It's a little gross,
|
|
|
|
# but because TMPDIR is likely on tmpfs, it's time-cheap,
|
|
|
|
# and because of sparse files, it's space-cheap.
|
|
|
|
tmpfile=$(mktemp -t -- "${0##*/}.XXXXXXXXXX")
|
|
|
|
trap "rm -- ${tmpfile@Q}" EXIT
|
|
|
|
case "$arg_size" in
|
|
|
|
'+'*|'-'*|'<'*|'>'*|'/'*|'%'*)
|
|
|
|
truncate --reference="$arg_file" --size="$arg_size" -- "$tmpfile";;
|
|
|
|
*)
|
|
|
|
truncate --size="$arg_size" -- "$tmpfile";;
|
|
|
|
esac
|
|
|
|
old_size=$(stat --format='%s' -- "$arg_file")
|
|
|
|
new_size=$(stat --format='%s' -- "$tmpfile")
|
|
|
|
rm -- "$tmpfile"
|
|
|
|
trap - EXIT
|
2018-08-16 05:19:05 +00:00
|
|
|
|
2018-08-16 06:00:07 +00:00
|
|
|
# Do the resize
|
|
|
|
arg_mountpoint=$(mktemp -dt -- "${0##*/}.XXXXXXXXXX")
|
|
|
|
trap "rmdir -- ${arg_mountpoint@Q}" EXIT
|
|
|
|
if (( new_size > old_size )); then
|
|
|
|
truncate --size="$new_size" -- "$arg_file"
|
|
|
|
sudo -- ./osi-mount --root -- "$arg_file" "$arg_mountpoint" btrfs filesystem resize max "$arg_mountpoint"
|
|
|
|
elif (( new_size < old_size )); then
|
|
|
|
sudo -- ./osi-mount --root -- "$arg_file" "$arg_mountpoint" btrfs filesystem resize "$new_size" "$arg_mountpoint"
|
|
|
|
truncate --size="$new_size" -- "$arg_file"
|
|
|
|
fi
|
|
|
|
rmdir -- "$arg_mountpoint"
|
|
|
|
trap - EXIT
|
2018-08-16 05:19:05 +00:00
|
|
|
fi
|
2018-08-16 06:00:07 +00:00
|
|
|
else
|
2018-08-12 21:53:08 +00:00
|
|
|
truncate --size="$arg_size" -- "$arg_file"
|
|
|
|
mkfs.btrfs -- "$arg_file"
|
2018-08-16 06:00:07 +00:00
|
|
|
fi
|
|
|
|
} |& sed "s|^|${prefix} |"
|
2018-07-25 19:23:05 +00:00
|
|
|
arg_mountpoint=$(mktemp -dt -- "${0##*/}.XXXXXXXXXX")
|
|
|
|
trap "rmdir -- ${arg_mountpoint@Q}" EXIT
|
2018-08-14 20:19:07 +00:00
|
|
|
sudo -- ./osi-mount --root -- "$arg_file" "$arg_mountpoint" "${BASH_SOURCE[0]}" --inside="$arg_mountpoint" "${arg_orig[@]}"
|
2018-07-25 19:23:05 +00:00
|
|
|
;;
|
2023-10-25 11:04:49 +00:00
|
|
|
inside) # the part that runs as root with the image mounted
|
2018-08-11 18:57:24 +00:00
|
|
|
needs_sudo
|
2018-07-26 20:35:32 +00:00
|
|
|
|
2018-08-06 01:49:45 +00:00
|
|
|
### Load modules ###
|
2018-08-12 22:20:59 +00:00
|
|
|
packages=("${arg_packages[@]}")
|
2018-08-06 04:38:14 +00:00
|
|
|
cache_packages=()
|
2018-08-12 21:53:08 +00:00
|
|
|
post_install=(
|
|
|
|
50:osi-mk:directories
|
2018-08-14 20:53:02 +00:00
|
|
|
99:osi-mk:grub-mkconfig
|
2018-08-12 21:53:08 +00:00
|
|
|
)
|
2018-08-20 06:32:29 +00:00
|
|
|
if [[ -n $arg_edit_base ]]; then
|
|
|
|
post_install+=(
|
|
|
|
00:osi-mk:genfstab
|
|
|
|
)
|
|
|
|
fi
|
2018-08-12 22:20:59 +00:00
|
|
|
if ! $arg_edit; then
|
|
|
|
packages+=(grub btrfs-progs)
|
|
|
|
post_install+=(
|
2018-08-20 06:32:29 +00:00
|
|
|
00:osi-mk:genfstab
|
2018-08-14 20:53:02 +00:00
|
|
|
98:osi-mk:grub-install
|
2018-08-12 22:20:59 +00:00
|
|
|
)
|
|
|
|
fi
|
2018-08-06 00:09:42 +00:00
|
|
|
for module in "${arg_modules[@]}"; do
|
2018-08-06 04:02:37 +00:00
|
|
|
load_module "$module"
|
2018-08-06 00:09:42 +00:00
|
|
|
done
|
2018-08-06 04:38:14 +00:00
|
|
|
cache_packages+=("${packages[@]}")
|
2018-08-06 01:49:45 +00:00
|
|
|
|
2023-10-23 22:52:38 +00:00
|
|
|
### Download ###
|
2023-10-25 11:17:25 +00:00
|
|
|
gprintf -v prefix '%s [download:repos]' "$NAME"
|
2018-08-12 21:53:08 +00:00
|
|
|
{
|
2023-10-25 11:17:25 +00:00
|
|
|
# Download syncdbs to the image
|
|
|
|
mkdir -p -- "$arg_mountpoint"/var/{lib/pacman,log}
|
|
|
|
pacman -r "$arg_mountpoint" --config=/usr/share/pacman/defaults/pacman.conf.x86_64 \
|
|
|
|
-Sy --noconfirm
|
|
|
|
} |& sed "s|^|${prefix} |"
|
|
|
|
gprintf -v prefix '%s [download:packages]' "$NAME"
|
|
|
|
{
|
|
|
|
if (( ${#cache_packages[@]} > 0 )); then # this check is important for --edit
|
|
|
|
# Download needed packages to the host cache
|
2018-08-12 22:20:59 +00:00
|
|
|
pacman -r "$arg_mountpoint" --config=/usr/share/pacman/defaults/pacman.conf.x86_64 \
|
|
|
|
-Syw --noconfirm -- "${cache_packages[@]}"
|
2023-10-25 11:17:25 +00:00
|
|
|
|
2018-08-12 22:25:10 +00:00
|
|
|
# Copy needed packages from host cache to image cache
|
2023-10-25 11:17:25 +00:00
|
|
|
mkdir -p -- "$arg_mountpoint"/var/cache/pacman/pkg
|
2018-08-12 22:20:59 +00:00
|
|
|
pacman -r "$arg_mountpoint" --config=/usr/share/pacman/defaults/pacman.conf.x86_64 \
|
|
|
|
-Sp --print-format='%l' -- "${cache_packages[@]}" \
|
2023-10-25 11:17:25 +00:00
|
|
|
| sed -En 's,^file://(.*),\1\n\1.sig,p' \
|
|
|
|
| xargs -d $'\n' -r cp -t "$arg_mountpoint/var/cache/pacman/pkg" --
|
2018-08-12 22:20:59 +00:00
|
|
|
fi
|
2023-10-23 22:52:38 +00:00
|
|
|
} |& sed "s|^|${prefix} |"
|
|
|
|
|
|
|
|
### Install ###
|
2023-10-24 21:42:25 +00:00
|
|
|
gprintf -v prefix '%s [install]' "$NAME"
|
2023-10-23 22:52:38 +00:00
|
|
|
{
|
2023-10-25 11:17:25 +00:00
|
|
|
if (( ${#packages[@]} > 0 )); then # this check is important for --edit
|
2018-08-12 22:20:59 +00:00
|
|
|
# The --hookdir bit is to hack around https://bugs.archlinux.org/task/49347
|
|
|
|
pacstrap -M -C /usr/share/pacman/defaults/pacman.conf.x86_64 -- "$arg_mountpoint" \
|
|
|
|
--hookdir="$arg_mountpoint/etc/pacman.d/hooks" \
|
|
|
|
--needed \
|
|
|
|
"${packages[@]}"
|
|
|
|
fi
|
2018-08-18 21:50:57 +00:00
|
|
|
if (( ${#arg_package_files[@]} > 0 )); then
|
|
|
|
dir="$(mktemp -d -- "$arg_mountpoint/tmp/package-files.XXXXXXXXXX")"
|
|
|
|
trap "rm -rf -- ${dir@Q}" EXIT
|
|
|
|
cp -t "$dir" -- "${arg_package_files[@]}"
|
|
|
|
arch-chroot -- "$arg_mountpoint" pacman -U --noconfirm -- "${arg_package_files[@]/#*\//"/tmp/${dir##*/tmp/}"}"
|
|
|
|
rm -rf -- "$dir"
|
|
|
|
trap - EXIT
|
|
|
|
fi
|
2018-08-12 22:05:29 +00:00
|
|
|
} |& sed "s|^|${prefix} |"
|
2018-07-26 20:35:32 +00:00
|
|
|
|
2018-08-06 01:49:45 +00:00
|
|
|
### post_install ###
|
|
|
|
while IFS=: read -r n fn; do
|
2023-10-24 21:42:25 +00:00
|
|
|
printf -v prefix '%s [post_install:%s:%s]' "$NAME" "$n" "$fn"
|
2018-08-12 21:53:08 +00:00
|
|
|
{
|
2018-08-12 22:05:29 +00:00
|
|
|
print Begin
|
2018-08-12 21:53:08 +00:00
|
|
|
"$fn" "$arg_mountpoint"
|
2018-08-12 22:05:29 +00:00
|
|
|
print End
|
2018-08-12 21:53:08 +00:00
|
|
|
} |& sed "s|^|${prefix} |"
|
2018-08-06 01:49:45 +00:00
|
|
|
done < <(printf '%s\n' "${post_install[@]}" | sort)
|
2018-08-06 00:09:42 +00:00
|
|
|
|
2018-08-12 21:53:08 +00:00
|
|
|
### End ###
|
|
|
|
print '%s Done' "$NAME"
|
2018-07-25 19:23:05 +00:00
|
|
|
;;
|
|
|
|
|
2023-10-25 10:59:35 +00:00
|
|
|
*) error $EXIT_FAILURE 'Internal error. The programmer writing this tool screwed up.';;
|
2018-07-25 19:23:05 +00:00
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
main "$@"
|