Files
Raspberry-Pi-Image-Tool/root/usr/sbin/raspi-image
2026-01-27 21:23:24 +01:00

1020 lines
45 KiB
Bash

#!/usr/bin/env bash
###
#
# Options Section
#
###
set -e
set -u
set -o pipefail
###
#
# Function Section
#
###
function bind () {
local LODEV_REALPATH="LODEV_${1}_REALPATH"
local LODEV_BASENAME="LODEV_${1}_BASENAME"
export BOOT
message "Install mount point '/mnt/${!LODEV_BASENAME}' ..."
/usr/bin/install --directory "/mnt/${!LODEV_BASENAME}" || \
error "\r\rInstall mount point '/mnt/${!LODEV_BASENAME}' [ERROR]\n" \
' => The directory could not be installed.\n'
message "\r\rInstall mount point '/mnt/${!LODEV_BASENAME}' [OK]\n"
message "Mount device '${!LODEV_REALPATH}' ..."
if ! /usr/bin/grep --quiet "${!LODEV_REALPATH}p2" '/proc/mounts'; then
/usr/bin/mount --source "${!LODEV_REALPATH}p2" --target "/mnt/${!LODEV_BASENAME}" &> '/dev/null' || \
error "\r\rMount device '${!LODEV_REALPATH}' [ERROR]\n" \
" => The device partition "${!LODEV_REALPATH}p2" could not be mounted.\n"
fi
/usr/bin/test -f "/mnt/${!LODEV_BASENAME}/etc/fstab" && \
BOOT=$(/usr/bin/grep '/boot' "/mnt/${!LODEV_BASENAME}/etc/fstab" | /usr/bin/mawk '$1 !~ /^#/ && $2 ~ /^[/]/ {print $2}')
/usr/bin/test -n "${BOOT}" || \
error "\r\rMount device '${!LODEV_REALPATH}' [ERROR]\n" \
' => The mount point could not be determined.\n'
/usr/bin/install --directory "/mnt/${!LODEV_BASENAME}/${BOOT}" || \
error "\r\rMount device '${!LODEV_REALPATH}' [ERROR]\n" \
' => The firmware directory could not be installed.\n'
if ! /usr/bin/grep --quiet "${!LODEV_REALPATH}p1" '/proc/mounts'; then
/usr/bin/mount --source "${!LODEV_REALPATH}p1" --target "/mnt/${!LODEV_BASENAME}/${BOOT}" &> '/dev/null' || \
error "\r\rMount device '${!LODEV_REALPATH}' [ERROR]\n" \
" => The device partition "${!LODEV_REALPATH}p1" could not be mounted.\n"
fi
message "\r\rMount device '${!LODEV_REALPATH}' [OK]\n"
}
function bind_chroot () {
local LODEV_BASENAME="LODEV_${1}_BASENAME"
message "Bind file system '/dev' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/dev" '/proc/mounts'; then
/usr/bin/mount --bind '/dev' --target "/mnt/${!LODEV_BASENAME}/dev" &> '/dev/null' || \
error "\r\rBind file system '/dev' [ERROR]\n" \
" => The file system '/dev' could not be mounted.\n"
fi
message "\r\rBind filesystem '/dev' [OK]\n"
message "Bind file system '/dev/pts' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/dev/pts" '/proc/mounts'; then
/usr/bin/mount --bind '/dev/pts' --target "/mnt/${!LODEV_BASENAME}/dev/pts" &> '/dev/null' || \
error "\r\rBind file system '/dev/pts' [ERROR]\n" \
" => The file system '/dev/pts' could not be mounted.\n"
fi
message "\r\rBind file system '/dev/pts' [OK]\n"
message "Bind file system '/dev/mqueue' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/dev/mqueue" '/proc/mounts'; then
/usr/bin/mount --bind '/dev/mqueue' --target "/mnt/${!LODEV_BASENAME}/dev/mqueue" &> '/dev/null' || \
error "\r\rBind files ystem '/dev/mqueue' [ERROR]\n" \
" => The file system '/dev/mqueue' could not be mounted.\n"
fi
message "\r\rBind files ystem '/dev/mqueue' [OK]\n"
message "Slave file system '/dev' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/dev" '/proc/mounts'; then
/usr/bin/mount --make-rslave --target "/mnt/${!LODEV_BASENAME}/dev" &> '/dev/null' || \
error "\r\rSlave file system '/dev' [ERROR]\n" \
" => The file system '/dev' could not be slaved.\n"
fi
message "\r\rSlave file system '/dev' [OK]\n"
message "Bind file system '/proc' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/proc" '/proc/mounts'; then
/usr/bin/mount --types 'proc' --source '/proc' --target "/mnt/${!LODEV_BASENAME}/proc" &> '/dev/null' || \
error "\r\rBind file system '/proc' [ERROR]\n" \
" => The file system '/proc' could not be mounted.\n"
fi
message "\r\rBind file system '/proc' [OK]\n"
message "Bind file system '/sys' ..."
if ! /usr/bin/grep --quiet "/mnt/${!LODEV_BASENAME}/sys" '/proc/mounts'; then
/usr/bin/mount --types 'sysfs' --source '/sys' --target "/mnt/${!LODEV_BASENAME}/sys" &> '/dev/null' || \
error "\r\rBind file system '/sys' [ERROR]\n" \
" => The file system '/sys' could not be mounted.\n"
fi
message "\r\rBind file system '/sys' [OK]\n"
}
function consistency () {
local IMG_REALPATH="IMG_${1}_REALPATH"
message 'Check image consistency ...'
/usr/bin/test -f "${!IMG_REALPATH}" || \
error '\r\rCheck image consistency [ERROR]\n' \
' => The selected file could not be found.\n'
/usr/sbin/fdisk --list "${!IMG_REALPATH}" | /usr/bin/grep --quiet 'Disklabel type: dos' && \
/usr/sbin/fdisk --list "${!IMG_REALPATH}" | /usr/bin/grep --quiet 'W95 FAT32 (LBA)' && \
/usr/sbin/fdisk --list "${!IMG_REALPATH}" | /usr/bin/grep --quiet 'Linux' || \
error '\r\rCheck image consistency [ERROR]\n' \
' => The selected file does not look like an Raspberry Pi Image.\n'
message '\r\rCheck image consistency [OK]\n'
}
function error () {
if [ -n "${1:-}" ]; then
/usr/bin/echo -n -e "${1}"
fi
if [ -n "${2:-}" ]; then
/usr/bin/echo -n -e "${2}"
fi
exit 1
}
function fscheck () {
local LODEV_REALPATH="LODEV_${1}_REALPATH"
local PARTITION
local FILESYSTEM
message 'Check & Repair Filesystem ...'
for PARTITION in "${!LODEV_REALPATH}p"*; do
FILESYSTEM=$(/usr/sbin/blkid --output 'value' --match-tag 'TYPE' "${PARTITION}")
case "${FILESYSTEM}" in
ext4)
/usr/sbin/fsck.ext4 -p -c -f "${PARTITION}" &> '/dev/null' || \
error '\r\rCheck & Repair Filesystem [ERROR]\n' \
" => The file system on '${PARTITION}' could not be checked or repaired.\n"
;;
vfat)
/usr/sbin/fsck.vfat -a -t -V -w "${PARTITION}" &> '/dev/null' || \
error '\r\rCheck & Repair Filesystem [ERROR]\n' \
" => The file system on '${PARTITION}' could not be checked or repaired.\n"
;;
esac
done
message '\r\rCheck & Repair Filesystem [OK]\n'
}
function help () {
local HELP
case "${1}" in
command)
read -r -d '' HELP << EOL
Usage: raspi-image (OPTION) (IMAGE)
Options:
[ -a ] [ IMAGE ] | Archive Raspberry Pi image
[ -c ] [ IMAGE ] | Chroot Raspberry Pi image
[ -d ] [ IMAGE ] | Duplicate Raspberry Pi image
[ -e ] [ IMAGE ] | Expand Raspberry Pi image
[ -h ] | Help
[ -m ] [ IMAGE ] | Mount Raspberry Pi image
[ -n ] [ IMAGE ] | New Raspberry Pi image
[ -p ] [ IMAGE ] | Prepare Raspberry Pi image
[ -r ] [ IMAGE ] | Raspberry Pi image repository
[ -s ] [ IMAGE ] | Shrink Raspberry Pi image
[ -u ] [ IMAGE ] | Unmount Raspberry Pi image
EOL
;;
archive)
read -r -d '' HELP << EOL
Usage: raspi-image -a (IMAGE)
Description:
Compresses the image with the
data compression format 'xz'
and generates a hash sum of it.
EOL
;;
chroot)
read -r -d '' HELP << EOL
Usage: raspi-image -c (IMAGE)
Description:
Mounts the image and change the
root environment into it. After
'exit' change back, the image
will be unmounted.
EOL
;;
duplicate)
read -r -d '' HELP << EOL
Usage: raspi-image -d (IMAGE)
Description:
Generate and syncronize an shrinked
image with new partition UUID from
the image.
EOL
;;
expand)
read -r -d '' HELP << EOL
Usage: raspi-image -e (IMAGE)
Description:
Expand the image, it's partition
and the filesystem by 512 MB.
EOL
;;
mount)
read -r -d '' HELP << EOL
Usage: raspi-image -m (IMAGE)
Description:
Mount the image under '/mnt'.
EOL
;;
new)
read -r -d '' HELP << EOL
Usage: raspi-image -n (IMAGE)
Description:
Configure, generate and syncronize
an shrinked image with new partition
UUID based of the repository image.
EOL
;;
prepare)
read -r -d '' HELP << EOL
Usage: raspi-image -p (IMAGE)
Description:
Prepare and/or clean up the image.
EOL
;;
repository)
read -r -d '' HELP << EOL
Usage: raspi-image -r (IMAGE)
Description:
Download one of the following
images from the repository.
- Raspberry Pi OS Bookworm
- arm64_raspberrypios_bookworm
- arm64_raspberrypios_bookworm_pve
- arm64_raspberrypios_bookworm_pbs
- Ubuntu Noble
- arm64_ubuntu_noble-numbat
EOL
;;
shrink)
read -r -d '' HELP << EOL
Usage: raspi-image -s (IMAGE)
Description:
Shrink the image, its partition
and the filesystem to the
smallest possible size.
EOL
;;
umount)
read -r -d '' HELP << EOL
Usage: raspi-image -u (IMAGE)
Description:
Unmount the image which is mounted
under '/mnt'.
EOL
;;
esac
/usr/bin/echo -e "${HELP}"
}
function ldattach () {
local IMG_REALPATH="IMG_${1}_REALPATH"
message 'Attach loop device ...'
/usr/sbin/losetup --list --noheadings --output 'NAME,BACK-FILE' --raw | /usr/bin/grep --quiet "${!IMG_REALPATH}" && \
export LODEV_"${1}"_REALPATH=$(/usr/sbin/losetup --list --noheadings --output 'NAME,BACK-FILE' --raw | /usr/bin/grep "${!IMG_REALPATH}" | /usr/bin/sed --expression="s|${!IMG_REALPATH}||g" --expression='s/[[:space:]]*$//') || \
export LODEV_"${1}"_REALPATH=$(/usr/sbin/losetup --find --partscan --show "${!IMG_REALPATH}")
local LODEV_REALPATH="LODEV_${1}_REALPATH"
/usr/bin/test -n "${!LODEV_REALPATH}" || \
error '\r\rAttach loop device [ERROR]\n' \
' => The loop device could not be attached.\n'
export LODEV_"${1}"_BASENAME=$(/usr/bin/basename "${!LODEV_REALPATH}")
message '\r\rAttach loop device [OK]\n'
}
function lddetach () {
local LODEV_REALPATH="LODEV_${1}_REALPATH"
message 'Detach loop device ...'
/usr/sbin/losetup --detach "${!LODEV_REALPATH}" || \
error '\r\rDetach loop device [ERROR]\n' \
' => The loop device could not be detached.\n'
message '\r\rDetach loop device [OK]\n'
}
function message () {
if [ -n "${1:-}" ]; then
/usr/bin/echo -n -e "${1}"
fi
}
function partuuid () {
local IMG_REALPATH="IMG_${1}_REALPATH"
local IMG_PARTUUID="IMG_${1}_PARTUUID"
message 'Correct partition UUID ...'
/usr/sbin/sfdisk --disk-id "${!IMG_REALPATH}" "0x${!IMG_PARTUUID}" &> '/dev/null' || \
error '\r\rCorrect partition UUID [ERROR]\n' \
' => The correct UUID could not be written to the image.\n'
message '\r\rCorrect partition UUID [OK]\n'
}
function resizefs () {
function expand () {
/usr/sbin/resize2fs "${!LODEV_REALPATH}p2" || \
error '\r\rExpand filesystem [ERROR]\n' \
' => The file system could not be expanded.\n'
}
local LODEV_REALPATH="LODEV_${1}_REALPATH"
message 'Expand files system ...'
expand &> '/dev/null'
message '\r\rExpand files system [OK]\n'
}
function resizeimg () {
local IMG_REALPATH="IMG_${1}_REALPATH"
message 'Expand image ...'
/usr/bin/dd if=/dev/zero bs='512' iflag='fullblock,count_bytes' count="512M" &> '/dev/null' >> "${!IMG_REALPATH}" || \
error '\r\rExpand image [ERROR]\n' \
' => The image could not be expanded.\n'
/usr/bin/sync --data "${!IMG_REALPATH}" || \
error '\r\rExpand image [ERROR]\n' \
' => The image could not be synced.\n'
message '\r\rExpand image [OK]\n'
}
function resizepart () {
local IMG_REALPATH="IMG_${1}_REALPATH"
local LODEV_REALPATH="LODEV_${1}_REALPATH"
message 'Expand partition ...'
/usr/sbin/parted --script "${!IMG_REALPATH}" resizepart '2' '100%' &> '/dev/null' || \
error '\r\rExpand partition [ERROR]\n' \
' => The partition could not be expanded.\n'
/usr/sbin/partprobe "${!IMG_REALPATH}" || \
error '\r\rExpand partition [ERROR]\n' \
' => The partitiontable could not be read.\n'
message '\r\rExpand partition [OK]\n'
}
function resolvconf () {
local OPTION="${1}"
case "${OPTION}" in
prepare)
message 'Prepare DNS-Resolver ...'
if [[ -L "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" ]]; then
/usr/bin/unlink "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
error '\r\rPrepare DNS-Resolver [ERROR]\n' \
" => The 'resolv.conf' could not be unlinked.\n"
fi
/usr/bin/cp --force '/etc/resolv.conf' "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
error '\r\rPrepare DNS-Resolver [ERROR]\n' \
" => The 'resolv.conf' could not be copied into the Raspberry Pi image.\n"
message '\r\rPrepare DNS-Resolver [OK]\n'
;;
reset)
message 'Reset DNS-Resolver ...'
if [[ -L "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" ]]; then
/usr/bin/unlink "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
error '\r\rReset DNS-Resolver [ERROR]\n' \
" => The 'resolv.conf' could not be unlinked.\n"
fi
/usr/bin/ln --force --symbolic '../run/systemd/resolve/stub-resolv.conf' "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
error '\r\rReset DNS-Resolver [ERROR]\n' \
" => The file 'resolv.conf' could not be replaced.\n"
message '\r\rReset DNS-Resolver [OK]\n'
;;
esac
}
function shrinkfs () {
function variables () {
IMG_BLOCK_SIZE=$(/usr/sbin/tune2fs -l "${!LODEV_REALPATH}p2" | /usr/bin/grep '^Block size:' | /usr/bin/tr --delete ' ' | /usr/bin/cut --delimiter=':' --fields='2')
IMG_BLOCK_COUNT=$(/usr/sbin/tune2fs -l "${!LODEV_REALPATH}p2" | /usr/bin/grep '^Block count:' | /usr/bin/tr --delete ' ' | /usr/bin/cut --delimiter=':' --fields='2')
IMG_BLOCK_COUNT_NEW=$(/usr/sbin/resize2fs -P "${!LODEV_REALPATH}p2" | /usr/bin/tr --delete ' ' | /usr/bin/cut --delimiter=':' --fields='2')
IMG_BLOCK_COUNT_CALC=$(("${IMG_BLOCK_COUNT}" - "${IMG_BLOCK_COUNT_NEW}"))
}
function shrink () {
/usr/sbin/resize2fs "${!LODEV_REALPATH}p2" "${IMG_BLOCK_COUNT}" || \
error '\r\rShrink file system [ERROR]\n' \
' => The file system could not be shrinked.\n'
}
export IMG_BLOCK_SIZE
export IMG_BLOCK_COUNT
local LODEV_REALPATH="LODEV_${1}_REALPATH"
local IMG_BLOCK_COUNT_NEW
local IMG_BLOCK_COUNT_CALC
local NUMBER
message 'Shrink file system ...'
variables &> '/dev/null'
for NUMBER in 5000 1000 100; do
if [[ "${IMG_BLOCK_COUNT_CALC}" -gt "${NUMBER}" ]]; then
IMG_BLOCK_COUNT=$(("${IMG_BLOCK_COUNT_NEW}" + "${NUMBER}"))
fi
done
shrink &> '/dev/null'
message "\r\rShrink file system [OK]\n"
}
function shrinkimg () {
local IMG_REALPATH="IMG_${1}_REALPATH"
local SIZE
message 'Shrink image ...'
SHRINK_SIZE=$(/usr/sbin/parted --machine --script "${!IMG_REALPATH}" unit B print free | /usr/bin/tail -1 | /usr/bin/cut --delimiter=':' --fields='2' | /usr/bin/tr --delete 'B')
/usr/bin/truncate -s "${SHRINK_SIZE}" "${!IMG_REALPATH}" || \
error '\r\rShrink image [ERROR]\n' \
' => The image could not be shrinked.\n'
message '\r\rShrink image [OK]\n'
}
function shrinkpart () {
local IMG_REALPATH="IMG_${1}_REALPATH"
local IMG_PART
local IMG_PART_START
local IMG_PART_CALC
local IMG_PART_END
message 'Shrink partition ...'
IMG_PART=$(/usr/sbin/parted --machine "${!IMG_REALPATH}" unit B print | /usr/bin/tail --lines='1' | /usr/bin/cut --delimiter=':' --fields='1')
IMG_PART_START=$(/usr/sbin/parted --machine "${!IMG_REALPATH}" unit B print | /usr/bin/tail --lines='1' | /usr/bin/cut --delimiter=':' --fields='2' | /usr/bin/tr --delete 'B')
IMG_PART_CALC=$(("${IMG_BLOCK_COUNT}" * "${IMG_BLOCK_SIZE}"))
IMG_PART_END=$(("${IMG_PART_START}" + "${IMG_PART_CALC}"))
/usr/sbin/parted --script --align='min' "${!IMG_REALPATH}" rm "${IMG_PART}" &> '/dev/null' || \
error '\r\rShrink partition [ERROR]\n' \
' => The partition could not be removed.\n'
/usr/sbin/parted --script "${!IMG_REALPATH}" unit B mkpart primary "${IMG_PART_START}" "${IMG_PART_END}" &> '/dev/null' || \
error '\r\rShrink partition [ERROR]\n' \
' => The partition could not be created.\n'
/usr/sbin/partprobe "${!IMG_REALPATH}" || \
error '\r\rShrink partition [ERROR]\n' \
' => The partition could not be read.\n'
message '\r\rShrink partition [OK]\n'
}
function unbind () {
local LODEV_REALPATH="LODEV_${1}_REALPATH"
local LODEV_BASENAME="LODEV_${1}_BASENAME"
message "Unmount device '${!LODEV_REALPATH}' ..."
if /usr/bin/grep --quiet "${!LODEV_REALPATH}" '/proc/mounts'; then
/usr/bin/umount --recursive "/mnt/${!LODEV_BASENAME}" || \
error "\r\rUnmount device '${!LODEV_REALPATH}' [ERROR]\n" \
' => The device could not be unmounted.\n'
fi
message "\r\rUnmount device '${!LODEV_REALPATH}' [OK]\n"
message 'Remove mount point ...'
if [[ -d "/mnt/${!LODEV_BASENAME}" ]]; then
/usr/bin/rm --dir "/mnt/${!LODEV_BASENAME}" || \
error "\r\rRemove mount point '/mnt/${!LODEV_BASENAME}' [ERROR]\n" \
' => The mount point could not be removed.\n'
fi
message '\r\rRemove mount point [OK]\n'
}
###
#
# Runtime Environment
#
###
/usr/bin/echo -e 'Raspberry Pi Image Tool\n'
if [[ "${EUID}" -ne '0' ]]; then
/usr/bin/echo -e 'Error: Permission Denied'
exit 1
fi
while getopts ':a:c:d:e:hm:n:p:r:s:u:' OPT; do
case "${OPT}" in
a)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
IMG_0_DIRNAME=$(/usr/bin/dirname "${IMG_0_REALPATH}")
DATE=$(/usr/bin/date '+%s')
consistency '0'
trap "/usr/bin/rm --force ${IMG_0_REALPATH}.xz"* EXIT
message 'Archive Raspberry Pi image ...'
/usr/bin/xz --compress --keep -9 --extreme --quiet "${IMG_0_REALPATH}" || \
error '\r\rArchive Raspberry Pi image [ERROR]\n' \
' => The image could not be archived.\n'
message '\r\rArchive image [OK]\n'
message 'Generate Raspberry Pi image hashsum ...'
/usr/bin/sha512sum "${IMG_0_REALPATH}.xz" | /usr/bin/sed --expression='s, .*/, ,' >> "${IMG_0_REALPATH}.xz.sha512sum" || \
error '\r\rGenerate Raspberry Pi image hashsum [ERROR]\n' \
' => The image hashsum could not be generated.\n'
message '\r\rGenerate Raspberry Pi image hashsum [OK]\n'
trap '' EXIT
exit 0
;;
c)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
consistency '0'
trap "resolvconf 'reset' && unbind '0' && lddetach '0'" EXIT
ldattach '0'
bind '0'
bind_chroot '0'
resolvconf 'prepare'
message '\n ... Enter chroot environment ...\n\n'
/usr/bin/sleep '3s'
/usr/sbin/chroot "/mnt/${LODEV_0_BASENAME}" || true
message '\n ... Exit chroot environment ... \n\n'
/usr/bin/sleep '3s'
exit 0
;;
d)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
IMG_0_DIRNAME=$(/usr/bin/dirname "${IMG_0_REALPATH}")
consistency '0'
trap "unbind '0' && lddetach '0'" EXIT
ldattach '0'
bind '0'
IMG_1_BASENAME=$(/usr/bin/basename "${IMG_0_DIRNAME}/new_${IMG_0_BASENAME}")
IMG_1_REALPATH=$(/usr/bin/realpath "${IMG_0_DIRNAME}/new_${IMG_0_BASENAME}")
trap "/usr/bin/rm --force ${IMG_1_REALPATH} && unbind '0' && lddetach '0' && unbind '1' && lddetach '1'" EXIT
message 'Create Raspberry Pi image'
IMG_1_SIZE=$(/usr/bin/du --block-size='1M' --summarize "/mnt/${LODEV_0_BASENAME}" | /usr/bin/cut --delimiter='/' --fields='1' | /usr/bin/sed 's/[[:space:]]*$//')
IMG_1_SIZE=$(( "${IMG_1_SIZE}" * "2" ))
/usr/bin/dd if='/dev/zero' of="${IMG_1_REALPATH}" bs='512' iflag='fullblock,count_bytes' count="${IMG_1_SIZE}M" &> '/dev/null' || \
error '\r\rCreate Raspberry Pi image [ERROR]\n' \
' => The Raspberry Pi image could not be created.\n'
/usr/bin/sync -d "${IMG_1_REALPATH}" || \
error '\r\rCreate Raspberry Pi image [ERROR]\n' \
' => The Raspberry Pi image could not be synced.\n'
message '\r\rCreate Raspberry Pi image [OK]\n'
message 'Create partition tables'
/usr/sbin/parted --script "${IMG_1_REALPATH}" mklabel msdos mkpart primary fat32 1049kB 269MB &> '/dev/null' || \
error '\r\rCreate partition tables [ERROR]\n' \
" => The 'boot' partition could not be created.\n"
/usr/sbin/parted --script "${IMG_1_REALPATH}" mkpart primary ext4 269MB 100% &> '/dev/null' || \
error '\r\rCreate partition tables [ERROR]\n' \
" => The 'root' partition could not be created.\n"
message '\r\rCreate partition tables [OK]\n'
consistency '1'
ldattach '1'
message 'Create files ystem'
/usr/sbin/mkfs.vfat -c -F '32' -n 'FIRMWARE' "${LODEV_1_REALPATH}p1" &> '/dev/null' || \
error '\r\rCreate files sytem [ERROR]\n' \
" => The file system 'vfat' on 'boot' partition could not be created.\n"
/usr/sbin/mkfs.ext4 -c -F -L "Debian GNU/Linux" -O '^mmp' -e 'remount-ro' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
error '\r\rCreate files sytem [ERROR]\n' \
" => The file sytem 'ext4' on 'root' partition could not be created.\n"
message '\r\rCreate files sytem [OK]\n'
bind '1'
message 'Synchronize Raspberry Pi images'
/usr/bin/rsync --quiet --recursive --inplace --links --hard-links --perms --acls --xattrs --owner --group --times --preallocate "/mnt/${LODEV_0_BASENAME}/" "/mnt/${LODEV_1_BASENAME}" || \
error '\r\rSynchronize Raspberry Pi images [ERROR]\n' \
' => The old and new Raspberry Pi images could not be syncronized.\n'
message '\r\rSynchronize Raspberry Pi images [OK]\n'
unbind '0'
lddetach '0'
message 'Configure partition UUID'
IMG_1_PARTUUID=$(/usr/sbin/blkid --output 'value' --match-tag 'PTUUID' "${LODEV_1_REALPATH}")
/usr/bin/sed --follow-symlinks --in-place "s/PARTUUID=[A-Za-z0-9]*/PARTUUID=${IMG_1_PARTUUID}/g" "/mnt/${LODEV_1_BASENAME}/etc/fstab" || \
error '\r\rConfigure partition UUID [ERROR]\n' \
" => The UUID could not be written to 'fstab'.\n"
/usr/bin/sed --follow-symlinks --in-place "s/PARTUUID=[A-Za-z0-9]*/PARTUUID=${IMG_1_PARTUUID}/g" "/mnt/${LODEV_1_BASENAME}/${BOOT}/cmdline.txt" || \
error '\r\rConfigure partition UUID [ERROR]\n' \
" => The UUID could not be written to 'cmdline.txt'.\n"
message '\r\rConfigure partition UUID [OK]\n'
message 'Defragment file system'
/usr/sbin/e4defrag "/mnt/${LODEV_1_BASENAME}" &> '/dev/null' || \
error '\r\rDefragment file system [ERROR]\n' \
' => The file system could not be defragmented.\n'
message '\r\rDefragment file system [OK]\n'
message 'Trim file system'
/usr/sbin/fstrim "/mnt/${LODEV_1_BASENAME}" || \
error '\r\rTrim file system [ERROR]\n' \
' => The file system could not be trimmed.\n'
message '\r\rTrim file system [OK]\n'
unbind '1'
message 'Adjust file system configuration'
/usr/sbin/tune2fs -M '/' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
error '\r\rAdjust file system configuration [ERROR]\n' \
' => The file system could not be adjusted.\n'
message '\r\rAdjust file system configuration [OK]\n'
fscheck '1'
shrinkfs '1'
lddetach '1'
shrinkpart '1'
shrinkimg '1'
partuuid '1'
ldattach '1'
fscheck '1'
lddetach '1'
trap '' EXIT
exit 0
;;
e)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
consistency '0'
trap "lddetach '0'" EXIT
ldattach '0'
message 'Save partition UUID'
IMG_0_PARTUUID=$(/usr/sbin/blkid --output 'value' --match-tag 'PTUUID' "${LODEV_0_REALPATH}")
/usr/bin/test -n "${IMG_0_PARTUUID}" || \
error '\r\rSave partition UUID [ERROR]\n' \
' => The partition UUID could not be saved.\n'
message '\r\rSave partition UUID [OK]\n'
lddetach '0'
resizeimg '0'
resizepart '0'
ldattach '0'
fscheck '0'
resizefs '0'
fscheck '0'
lddetach '0'
partuuid '0'
trap '' EXIT
exit 0
;;
h)
set +e
help 'command'
exit 0
;;
m)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
consistency '0'
trap "unbind '0' && lddetach '0'" EXIT
ldattach '0'
bind '0'
trap '' EXIT
exit 0
;;
n)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
IMG_0_DIRNAME=$(/usr/bin/dirname "${IMG_0_REALPATH}")
IMG_0_CLEARNAME="${IMG_0_BASENAME%%.*}"
consistency '0'
trap "/usr/bin/rm --force ${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME} && unbind '0' && lddetach '0'" EXIT
message 'Prepare configuration'
if [ -f "/usr/share/raspi-image/config/${IMG_0_CLEARNAME}" ]; then
/usr/bin/cp --update='none' "/usr/share/raspi-image/config/${IMG_0_CLEARNAME}" "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare configuration [ERROR]\n' \
" => The configuration '${IMG_0_CLEARNAME}' could not be copied.\n"
elif [[ ! -f "/usr/share/raspi-image/config/${IMG_0_CLEARNAME}" ]]; then
/usr/bin/cp --update='none' '/usr/share/raspi-image/config/default' "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare configuration [ERROR]\n' \
" => The configuration 'default' could not be copied.\n"
fi
/usr/bin/editor "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare configuration [ERROR]\n' \
" => The configuration '${IMG_0_CLEARNAME}' could not be opened.\n"
message '\r\rPrepare configuration [OK]\n'
message 'Load configuration'
source "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rLoad configuration [ERROR]\n' \
" => The configuration '${IMG_0_CLEARNAME}' could not be loaded.\n"
message '\r\rLoad configuration [OK]\n'
ldattach '0'
bind '0'
message 'Configure hostname'
if [[ -n "${HOSTNAME}" ]]; then
HOSTNAME_OLD=$(/usr/bin/cat "/mnt/${LODEV_0_BASENAME}/etc/hostname")
mapfile -t HOSTNAME_LIST < <(/usr/bin/grep --recursive --files-with-matches "${HOSTNAME_OLD}" "/mnt/${LODEV_0_BASENAME}/etc")
for HOSTNAME_LIST in "${HOSTNAME_LIST[@]}"; do
/usr/bin/sed --in-place "s/${HOSTNAME_OLD}/${HOSTNAME}/g" "${HOSTNAME_LIST}" || \
error '\r\rConfigure hostname [ERROR]\n' \
' => The hostname could not be set.\n'
done
elif [[ -z "${HOSTNAME}" ]]; then
error '\r\rConfigure hostname [ERROR]\n' \
' => The hostname is not set in configuration.\n'
fi
message '\r\rConfigure hostname [OK]\n'
message 'Configure Root password'
if [[ -n "${ROOT_PASSWORD}" ]]; then
/usr/bin/echo 'root':"${ROOT_PASSWORD}" | /usr/sbin/chpasswd --root "/mnt/${LODEV_0_BASENAME}" || \
error '\r\rConfigure Root password [ERROR]\n' \
' => The Root password could not be set.\n'
elif [[ -z "${ROOT_PASSWORD}" ]]; then
error '\r\rConfigure Root password [ERROR]\n' \
' => The Root password is not set in configuration.\n'
fi
message '\r\rConfigure Root password [OK]\n'
if [[ -n "${SSH_PUBKEY}" ]]; then
message 'Confifure Root Secure Shell Public Key'
/usr/bin/echo "${SSH_PUBKEY}" > "/mnt/${LODEV_0_BASENAME}/etc/ssh/authorizedkeys.d/root" && \
/usr/bin/chmod '0600' "/mnt/${LODEV_0_BASENAME}/etc/ssh/authorizedkeys.d/root" || \
error '\r\rConfifure Root Secure Shell Public Key [ERROR]\n' \
' => The Secure Shell Public Key could not be written.\n'
message '\r\rConfifure Root Secure Shell Public Key [OK]\n'
fi
if [[ -n "${WIFI_KEY_MGMT}" ]] && \
[[ -n "${WIFI_PMF}" ]] && \
[[ -n "${WIFI_PSK}" ]] && \
[[ -n "${WIFI_SCAN_SSID}" ]] && \
[[ -n "${WIFI_SSID}" ]]; then
message 'Prepare WiFi settings'
/usr/bin/sed --in-place --expression="s/pmf=.*/pmf=${WIFI_PMF}/" "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
error '\r\rPrepare WiFi settings [ERROR]\n' \
" => The configuration for 'WiFi Protected Management Frames' could not be written.\n"
/usr/bin/sed --in-place --regexp-extended "/# RPI-IMAGE AUTOCONFIG BEGIN/,/# RPI-IMAGE AUTOCONFIG END/d" "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
error '\r\rPrepare WiFi settings [ERROR]\n' \
' => The main configuration block cloud not be removed.\n'
message '\r\rPrepare WiFi settings [OK]\n'
message 'Configure Wi-Fi connection'
/usr/bin/echo '# RPI-IMAGE AUTOCONFIG BEGIN' >> "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" && \
/usr/bin/wpa_passphrase "${WIFI_SSID}" "${WIFI_PSK}" | /usr/bin/sed --expression='3d' \
--expression='5 iscan_ssid=\' \
--expression='key_mgmt=\' | \
/usr/bin/sed --expression="s/scan_ssid=/$(/usr/bin/printf '\t')scan_ssid=${WIFI_SCAN_SSID}/g" \
--expression="s/key_mgmt=/$(/usr/bin/printf '\t')key_mgmt=${WIFI_KEY_MGMT}/g" >> \
"/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
error '\r\rConfigure Wi-Fi connection [ERROR]\n' \
' => The main configuration block cloud not be written.\n'
/usr/bin/echo '# RPI-IMAGE AUTOCONFIG END' >> "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf"
message '\r\rConfigure Wi-Fi connection [OK]\n'
fi
if [[ "${CERTIFICATE}" == 'true' ]] && \
[[ -n "${RSA_KEYSIZE}" ]] && \
[[ -n "${ECDSA_KEYSIZE}" ]] && \
[[ -n "${COUNTRY}" ]] && \
[[ -n "${STATE}" ]] && \
[[ -n "${LOCALITY}" ]] && \
[[ -n "${ORGANIZATION}" ]] && \
[[ -n "${COMMON_NAME}" ]]; then
message 'Generate RSA Root certificate'
/usr/bin/openssl req -x509 -nodes -days '360' -newkey "rsa:${RSA_KEYSIZE}" \
-keyout "/mnt/${LODEV_0_BASENAME}/etc/ssl/key/root.rsa.key" \
-out "/mnt/${LODEV_0_BASENAME}/etc/ssl/crt/root.rsa.crt" \
-subj "/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORGANIZATION_UNIT}/CN=${COMMON_NAME}" &> '/dev/null' || \
error '\r\rGenerate RSA Root certificate [ERROR]\n' \
' => The certificate or key file could not be generated.\n'
message '\r\rGenerate RSA Root certificate [OK]\n'
message 'Generate ECDSA Root certificate'
/usr/bin/openssl req -x509 -nodes -days '360' -newkey 'ec' \
-pkeyopt "ec_paramgen_curve:${ECDSA_KEYSIZE}" \
-keyout "/mnt/${LODEV_0_BASENAME}/etc/ssl/key/root.ecc.key" \
-out "/mnt/${LODEV_0_BASENAME}/etc/ssl/crt/root.ecc.crt" \
-subj "/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORGANIZATION_UNIT}/CN=${COMMON_NAME}" &> '/dev/null' || \
error '\r\rGenerate ECDSA Root certificate [ERROR]\n' \
' => The certificate or key file could not be generated.\n'
message '\r\rGenerate ECDSA Root certificate [OK]\n'
fi
if [[ "${DHPEM}" == 'true' ]] && \
[[ -n "${DHPEM_SIZE}" ]]; then
for SIZE in ${DHPEM_SIZE}; do
message "Generate ${SIZE}-Bit DHPEM"
/usr/bin/openssl dhparam -out "/mnt/${LODEV_0_BASENAME}/etc/ssl/dhpem/dh${SIZE}.pem" -2 "${SIZE}" &> '/dev/null' || \
error "\r\rGenerate ${SIZE}-Bit DHPEM [ERROR]\n" \
" => The ${SIZE}-Bit DHPEM file can not be generated.\n"
message "\r\rGenerate ${SIZE}-Bit DHPEM [OK]\n"
done
fi
IMG_1_BASENAME=$(/usr/bin/basename "${IMG_0_DIRNAME}/new_${IMG_0_BASENAME}")
IMG_1_REALPATH=$(/usr/bin/realpath "${IMG_0_DIRNAME}/new_${IMG_0_BASENAME}")
message 'Create Raspberry Pi image'
IMG_1_SIZE=$(/usr/bin/du --block-size='1M' --summarize "/mnt/${LODEV_0_BASENAME}" | /usr/bin/cut --delimiter='/' --fields='1' | /usr/bin/sed 's/[[:space:]]*$//')
IMG_1_SIZE=$(( "${IMG_1_SIZE}" * "2" ))
/usr/bin/dd if='/dev/zero' of="${IMG_1_REALPATH}" bs='512' iflag='fullblock,count_bytes' count="${IMG_1_SIZE}M" &> '/dev/null' || \
error '\r\rCreate Raspberry Pi image [ERROR]\n' \
' => The Raspberry Pi image could not be created.\n'
/usr/bin/sync -d "${IMG_1_REALPATH}" || \
error '\r\rCreate Raspberry Pi image [ERROR]\n' \
' => The Raspberry Pi image could not be synced.\n'
message "\r\rCreate Raspberry Pi image [OK]\n"
message 'Create partition tables'
/usr/sbin/parted --script "${IMG_1_REALPATH}" mklabel msdos mkpart primary fat32 1049kB 269MB &> '/dev/null' || \
error '\r\rCreate partition tables [ERROR]\n' \
" => The 'boot' partition could not be created.\n"
/usr/sbin/parted --script "${IMG_1_REALPATH}" mkpart primary ext4 269MB 100% &> '/dev/null' || \
error '\r\rCreate partition tables [ERROR]\n' \
" => The 'root' partition could not be created.\n"
message '\r\rCreate partition tables [OK]\n'
consistency '1'
ldattach '1'
message 'Create files ystem'
/usr/sbin/mkfs.vfat -c -F '32' -n 'FIRMWARE' "${LODEV_1_REALPATH}p1" &> '/dev/null' || \
error '\r\rCreate files sytem [ERROR]\n' \
" => The file system 'vfat' on 'boot' partition could not be created.\n"
/usr/sbin/mkfs.ext4 -c -F -L "Debian GNU/Linux" -O '^mmp' -e 'remount-ro' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
error '\r\rCreate files sytem [ERROR]\n' \
" => The file system 'ext4' on 'root' partition could not be created.\n"
message '\r\rCreate files sytem [OK]\n'
bind '1'
message 'Synchronize Raspberry Pi images'
/usr/bin/rsync --quiet --recursive --inplace --links --hard-links --perms --acls --xattrs --owner --group --times --preallocate "/mnt/${LODEV_0_BASENAME}/" "/mnt/${LODEV_1_BASENAME}" || \
error '\r\rSynchronize Raspberry Pi images [ERROR]\n' \
' => The old and new Raspberry Pi images could not be syncronized.\n'
message '\r\rSynchronize Raspberry Pi images [OK]\n'
unbind '0'
lddetach '0'
message 'Configure partition UUID'
IMG_1_PARTUUID=$(/usr/sbin/blkid --output 'value' --match-tag 'PTUUID' "${LODEV_1_REALPATH}")
/usr/bin/sed --follow-symlinks --in-place "s/PARTUUID=[A-Za-z0-9]*/PARTUUID=${IMG_1_PARTUUID}/g" "/mnt/${LODEV_1_BASENAME}/etc/fstab" || \
error '\r\rConfigure partition UUID [ERROR]\n' \
" => The UUID could not be written to 'fstab'.\n"
/usr/bin/sed --follow-symlinks --in-place "s/PARTUUID=[A-Za-z0-9]*/PARTUUID=${IMG_1_PARTUUID}/g" "/mnt/${LODEV_1_BASENAME}/${BOOT}/cmdline.txt" || \
error '\r\rConfigure partition UUID [ERROR]\n' \
" => The UUID could not be written to 'cmdline.txt'.\n"
message '\r\rConfigure partition UUID [OK]\n'
message 'Defragment image'
/usr/sbin/e4defrag "/mnt/${LODEV_1_BASENAME}" &> '/dev/null' || \
error '\r\rDefragment file system [ERROR]\n' \
" => The file system could not be defragmented.\n"
message '\r\rDefragment file system [OK]\n'
message 'Trim file system'
/usr/sbin/fstrim "/mnt/${LODEV_1_BASENAME}" || \
error '\r\rTrim file system [ERROR]\n' \
" => The file system could not be trimmed.\n"
message '\r\rTrim file system [OK]\n'
unbind '1'
message 'Adjust file system configuration'
/usr/sbin/tune2fs -M '/' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
error '\r\rAdjust file system configuration [ERROR]\n' \
' => The file system could not be adjusted.\n'
message '\r\rAdjust file system configuration [OK]\n'
fscheck '1'
shrinkfs '1'
lddetach '1'
shrinkpart '1'
shrinkimg '1'
partuuid '1'
ldattach '1'
fscheck '1'
lddetach '1'
trap "/usr/bin/rm --force ${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" EXIT
exit 0
;;
p)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
IMG_0_DIRNAME=$(/usr/bin/dirname "${IMG_0_REALPATH}")
IMG_0_CLEARNAME="${IMG_0_BASENAME%%.*}"
consistency '0'
trap "/usr/bin/rm --force ${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME} && unbind '0' && lddetach '0'" EXIT
ldattach '0'
bind '0'
message 'Prepare the planned file remove list ...'
if [[ -f "/usr/share/raspi-image/prepare/${IMG_0_CLEARNAME}" ]]; then
/usr/bin/cp --update='none' "/usr/share/raspi-image/prepare/${IMG_0_CLEARNAME}" "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare the planned file remove list [ERROR]\n' \
" => The remove list '${IMG_0_CLEARNAME}' could not be copied.\n"
elif [[ ! -f "/usr/share/raspi-image/prepare/${IMG_0_CLEARNAME}" ]]; then
/usr/bin/cp --update='none' "/usr/share/raspi-image/prepare/default" "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare the planned file remove list [ERROR]\n' \
" => The remove list 'default' could not be copied.\n"
fi
/usr/bin/editor "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" || \
error '\r\rPrepare the planned file remove list [ERROR]\n' \
" => The remove list '.${CT_BASENAME}' could not be opened.\n"
message '\r\rPrepare the planned file remove list [OK]\n'
message 'Remove files from remove list ...'
mapfile -t CLEANUP_LIST < <(/usr/bin/cat "${IMG_0_DIRNAME}/.${IMG_0_CLEARNAME}" | /usr/bin/sed '/#.*/d' | while read -r CLEANUP_PATH; do /usr/bin/echo "/mnt/${LODEV_0_BASENAME}${CLEANUP_PATH}"; done)
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
/usr/bin/sh -c "/usr/bin/ls --directory ${CLEANUP_LIST} | /usr/bin/xargs /usr/bin/rm --force --recursive" &> '/dev/null' || \
error '\r\rRemove files from remove list [ERROR]\n' \
" => The file or directory '${CLEANUP_LIST}' could not be removed.\n"
done
unset CLEANUP_LIST
message '\r\rRemove files from remove list [OK]\n'
message 'Cleaning up the log files ...'
mapfile -t CLEANUP_LIST < <(/usr/bin/find "/mnt/${LODEV_0_BASENAME}/var/log" -type 'f')
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
/usr/bin/dd if=/dev/null of="${CLEANUP_LIST}" &> '/dev/null' || \
error '\r\rCleaning up the log files [ERROR]\n' \
" => The file '${CLEANUP_LIST}' could not be emptied.\n"
done
unset CLEANUP_LIST
mapfile -t CLEANUP_LIST < <(/usr/bin/find "/mnt/${LODEV_0_BASENAME}/var/logrotate" -type 'f')
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
/usr/bin/sh -c "/usr/bin/ls --directory ${CLEANUP_LIST} | /usr/bin/xargs /usr/bin/rm --force --recursive" &> '/dev/null' || \
error '\r\rCleaning up the log files [ERROR]\n' \
" => The file '${CLEANUP_LIST}' could not be removed.\n"
done
message '\r\rCleaning up the log files [OK]\n'
message 'Remove Root password'
/usr/bin/passwd --delete --quiet --root "/mnt/${LODEV_0_BASENAME}" 'root' || \
error '\r\rRemove Root password [ERROR]\n' \
' => The Root password could not be removed.\n'
message '\r\rRemove Root password [OK]\n'
message 'Lock Root account'
/usr/bin/passwd --lock --quiet --root "/mnt/${LODEV_0_BASENAME}" 'root' || \
error '\r\rLock Root account [ERROR]\n' \
' => The Root account could not be locked.\n'
message '\r\rLock Root account [OK]\n'
message 'Reset WiFi settings'
/usr/bin/sed --in-place --expression='s/pmf=.*/pmf=0/' "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
error '\r\rReset WiFi settings [ERROR]\n' \
" => The configuration for 'WiFi Protected Management Frames' could not be written.\n"
/usr/bin/sed --in-place --regexp-extended "/# RPI-IMAGE AUTOCONFIG BEGIN/,/# RPI-IMAGE AUTOCONFIG END/d" "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
error '\r\rReset WiFi settings [ERROR]\n' \
' => The main configuration block cloud not be removed.\n'
message '\r\rReset WiFi settings [OK]\n'
exit 0
;;
r)
message 'Download Raspberry Pi image ...'
if [[ -f "./${OPTARG}.img" ]]; then
error '\r\rDownload Raspberry Pi image [ERROR]\n' \
" => The Raspberry Pi image '${OPTARG}.img' already exists.\n"
fi
trap "/usr/bin/rm --force --recursive ./${OPTARG}.img.xz"* EXIT
/usr/bin/wget --quiet --output-document="./${OPTARG}.img.xz" --no-hsts "https://repository.privlab.it/raspi-image/${OPTARG}.img.xz" &> '/dev/null' || \
error '\r\rDownload Raspberry Pi image [ERROR]\n' \
" => The file '${OPTARG}.img.xz' could not be downloaded.\n"
/usr/bin/wget --quiet --output-document="./${OPTARG}.img.xz.sha512sum" --no-hsts "https://repository.privlab.it/raspi-image/${OPTARG}.img.xz.sha512sum" &> '/dev/null' || \
error '\r\rDownload Raspberry Pi image [ERROR]\n' \
" => The file '${OPTARG}.img.xz.sha512sum' could not be downloaded.\n"
message '\r\rDownload Raspberry Pi image [OK]\n'
message 'Security check of the raspberry pi image archive ...'
/usr/bin/sha512sum --check --strict "./${OPTARG}.img.xz.sha512sum" &> '/dev/null' || \
error '\r\rSecurity check of the raspberry pi image archive [ERROR]\n' \
" => The SHA512 hash value for '${OPTARG}.img.xz}' could not be verified.\n"
message '\r\rSecurity check of the raspberry pi image archive [OK]\n'
message 'Decompress container archive ...'
/usr/bin/xz --decompress --quiet "./${OPTARG}.img.xz" || \
error '\r\rDecompress container archive [ERROR]\n' \
" => The container archive '${OPTARG}.img.xz' could not be decompressed.\n"
message '\r\rDecompress container archive [OK]\n'
trap "/usr/bin/rm --force --recursive ./${OPTARG}.img.xz.sha512sum" EXIT
exit 0
;;
s)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
IMG_0_DIRNAME=$(/usr/bin/dirname "${IMG_0_REALPATH}")
consistency '0'
trap "lddetach '0'" EXIT
ldattach '0'
message 'Save partition UUID'
IMG_0_PARTUUID=$(/usr/sbin/blkid --output 'value' --match-tag 'PTUUID' "${LODEV_0_REALPATH}")
/usr/bin/test -n "${IMG_0_PARTUUID}" || \
error '\r\rSave partition UUID [ERROR]\n' \
' => The partition UUID could not be saved.\n'
message '\r\rSave partition UUID [OK]\n'
fscheck '0'
shrinkfs '0'
lddetach '0'
shrinkpart '0'
shrinkimg '0'
partuuid '0'
ldattach '0'
fscheck '0'
exit 0
;;
u)
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
consistency '0'
message 'Get Loop Device Environment'
if /usr/sbin/losetup --list --noheadings --output 'NAME,BACK-FILE' --raw | /usr/bin/grep --quiet "${IMG_0_REALPATH}"; then
LODEV_0_REALPATH=$(/usr/sbin/losetup --list --noheadings --output 'NAME,BACK-FILE' --raw | /usr/bin/grep "${IMG_0_REALPATH}" | /usr/bin/sed --expression="s|${IMG_0_REALPATH}||g" --expression='s/[[:space:]]*$//') || \
LODEV_0_REALPATH=$(/usr/sbin/losetup --find --partscan --show "${IMG_0_REALPATH}")
fi
set +u
/usr/bin/test -n "${LODEV_0_REALPATH}" || \
error '\r\rGet Loop Device Environment [ERROR]\n' \
" => The Loop Devive for the Raspberry Pi image '${IMG_0_BASENAME}' could not be found.\n"
set -u
message '\r\rGet Loop Device Environment [OK]\n'
LODEV_0_BASENAME=$(/usr/bin/basename "${LODEV_0_REALPATH}")
unbind '0'
lddetach '0'
exit 0
;;
-*|*)
set +e
case "${1}" in
-a)
help 'archive'
exit 0
;;
-c)
help 'chroot'
exit 0
;;
-d)
help 'duplicate'
exit 0
;;
-e)
help 'expand'
exit 0
;;
-m)
help 'mount'
exit 0
;;
-n)
help 'new'
exit 0
;;
-p)
help 'prepare'
exit 0
;;
-r)
help 'repository'
exit 0
;;
-s)
help 'shrink'
exit 0
;;
-u)
help 'umount'
exit 0
;;
esac
help 'command'
exit 0
;;
esac
done
set +e
help 'command'
shift $((OPTIND-1))