You've already forked Raspberry-Pi-Image-Tool
983 lines
44 KiB
Bash
983 lines
44 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
|
|
###
|
|
#
|
|
# Options Section
|
|
#
|
|
###
|
|
|
|
set -e
|
|
set -u
|
|
set -o pipefail
|
|
|
|
|
|
###
|
|
#
|
|
# Function Section
|
|
#
|
|
###
|
|
|
|
function bind_filesystem () {
|
|
local LODEV_BASENAME="LODEV_${1}_BASENAME"
|
|
message "Bind filesystem '/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 filesystem '/dev' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be binded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/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 filesystem '/dev/pts' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be binded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev/pts' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/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 filesystem '/dev/mqueue' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev/mqueue' \xE2\x9C\x94\n"
|
|
message "Slave filesystem '/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 filesystem '/dev' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be slaved.\n'
|
|
fi
|
|
message "\r\rSlave filesystem '/dev' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/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 filesystem '/proc' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/proc' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/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 filesystem '/sys' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/sys' \xE2\x9C\x94\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 expand_filesystem () {
|
|
function expand () {
|
|
/usr/sbin/resize2fs "${!LODEV_REALPATH}p2" || \
|
|
error '\r\rExpand filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesystem can not be expanded.\n'
|
|
}
|
|
local LODEV_REALPATH="LODEV_${1}_REALPATH"
|
|
message 'Expand filesystem'
|
|
expand &> '/dev/null'
|
|
message '\r\rExpand filesystem \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function expand_image () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be expanded.\n'
|
|
/usr/bin/sync -d "${!IMG_REALPATH}" || \
|
|
error '\r\rExpand image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be synced.\n'
|
|
message '\r\rExpand image \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function expand_partition () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partition can not be expanded.\n'
|
|
/usr/sbin/partprobe "${!IMG_REALPATH}" || \
|
|
error '\r\rExpand partition \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partitiontable can not be read.\n'
|
|
message '\r\rExpand partition \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function fsck_device () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The filesystem on '${PARTITION}' can not be checked/repaired.\n"
|
|
;;
|
|
vfat)
|
|
/usr/sbin/fsck.vfat -a -t -V -w "${PARTITION}" &> '/dev/null' || \
|
|
error '\r\rCheck/Repair Filesystem \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The filesystem on '${PARTITION}' can not be checled/repaired.\n"
|
|
;;
|
|
esac
|
|
done
|
|
message '\r\rCheck/Repair Filesystem \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function help () {
|
|
local HELP
|
|
case "${1}" in
|
|
command)
|
|
read -r -d '' HELP << EOL
|
|
Usage: raspi-image (OPTION) (IMAGE)
|
|
|
|
Options:
|
|
[ -a ] [ IMAGE ] | Archive Image
|
|
[ -c ] [ IMAGE ] | Chroot Image
|
|
[ -d ] [ IMAGE ] | Duplicate Image
|
|
[ -e ] [ IMAGE ] | Expand Image
|
|
[ -h ] | Help
|
|
[ -m ] [ IMAGE ] | Mount Image
|
|
[ -n ] [ IMAGE ] | New Image
|
|
[ -p ] [ IMAGE ] | Prepare Image
|
|
[ -r ] [ IMAGE ] | Image Repository
|
|
[ -s ] [ IMAGE ] | Shrink Image
|
|
[ -u ] [ IMAGE ] | Unmount 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
|
|
;;
|
|
download)
|
|
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]
|
|
- arm64_raspberrypios_bookworm
|
|
- arm64_raspberrypios_bookworm_pve
|
|
- arm64_raspberrypios_bookworm_pbs
|
|
- Ubuntu Noble [ARM64]
|
|
- 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:
|
|
Umount the image which is mounted
|
|
under '/mnt'.
|
|
EOL
|
|
;;
|
|
esac
|
|
/usr/bin/echo -e "${HELP}"
|
|
}
|
|
|
|
function image_check () {
|
|
local IMG_REALPATH="IMG_${1}_REALPATH"
|
|
message 'Check image consistency'
|
|
/usr/bin/test -f "${!IMG_REALPATH}" || \
|
|
error '\r\rCheck image consistency \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The selected file can 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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The selected file does not look like an Raspberry Pi Image.\n'
|
|
message '\r\rCheck image consistency \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function loop_device_attach () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Loop Device can not be attached.\n'
|
|
export LODEV_"${1}"_BASENAME=$(/usr/bin/basename "${!LODEV_REALPATH}")
|
|
message '\r\rAttach Loop Device \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function loop_device_detach () {
|
|
local LODEV_REALPATH="LODEV_${1}_REALPATH"
|
|
message 'Detach Loop Device'
|
|
/usr/sbin/losetup --detach "${!LODEV_REALPATH}" || \
|
|
error '\r\rDetach Loop Device \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Loop Device can not be detached.\n'
|
|
message '\r\rDetach Loop Device \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function message () {
|
|
if [ -n "${1:-}" ]; then
|
|
/usr/bin/echo -n -e "${1}"
|
|
fi
|
|
}
|
|
|
|
function mount_device () {
|
|
local LODEV_REALPATH="LODEV_${1}_REALPATH"
|
|
local LODEV_BASENAME="LODEV_${1}_BASENAME"
|
|
export BOOT
|
|
message 'Prepare mount point'
|
|
/usr/bin/install --directory "/mnt/${!LODEV_BASENAME}" || \
|
|
error '\r\rPrepare mount point \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The directory can not be installed.\n'
|
|
message '\r\rPrepare mount point \xE2\x9C\x94\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}' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The device can 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}' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The mountpoint can not be determined.\n'
|
|
/usr/bin/install --directory "/mnt/${!LODEV_BASENAME}/${BOOT}" || \
|
|
error "\r\rMount device '${!LODEV_REALPATH}' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The firmware directory can 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}' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The device can not be mounted.\n'
|
|
fi
|
|
message "\r\rMount device '${!LODEV_REALPATH}' \xE2\x9C\x94\n"
|
|
}
|
|
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The UUID can not be written to image.\n'
|
|
message '\r\rCorrect partition UUID \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function shrink_image () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be shrinked.\n'
|
|
message '\r\rShrink image \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function shrink_filesystem () {
|
|
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 filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesystem can 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 filesystem'
|
|
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 filesystem \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function shrink_partition () {
|
|
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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partition can not be shrinked.\n'
|
|
/usr/sbin/parted --script "${!IMG_REALPATH}" unit B mkpart primary "${IMG_PART_START}" "${IMG_PART_END}" &> '/dev/null' || \
|
|
error '\r\rShrink partition \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partition can not be shrinked.\n'
|
|
/usr/sbin/partprobe "${!IMG_REALPATH}" || \
|
|
error '\r\rShrink partition \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partitiontable can not be read.\n'
|
|
message '\r\rShrink partition \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function umount_device () {
|
|
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}' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The device can not be unmounted.\n'
|
|
fi
|
|
message "\r\rUnmount device '${!LODEV_REALPATH}' \xE2\x9C\x94\n"
|
|
message 'Remove mount point'
|
|
if [[ -d "/mnt/${!LODEV_BASENAME}" ]]; then
|
|
/usr/bin/rm --dir "/mnt/${!LODEV_BASENAME}" || \
|
|
error '\r\rRemove mount point \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The mount point can not be removed.\n'
|
|
fi
|
|
message '\r\rRemove mount point \xE2\x9C\x94\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')
|
|
image_check '0'
|
|
message 'Compress image'
|
|
/usr/bin/xz --compress --keep -9 --extreme --quiet "${IMG_0_REALPATH}" || \
|
|
error '\r\rCompress image [ERROR]\n' \
|
|
' \xE2\x86\x92 Error: The image can not be compressed.\n'
|
|
message '\r\rCompress image \xE2\x9C\x94\n'
|
|
message 'Generate hash'
|
|
/usr/bin/sha512sum "${IMG_0_REALPATH}.xz" | /usr/bin/sed --expression='s, .*/, ,' >> "${IMG_0_REALPATH}.xz.sha512sum" || \
|
|
error '\r\rGenerate hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image hash can not be generated.\n'
|
|
message '\r\rGenerate hash \xE2\x9C\x94\n'
|
|
exit 0
|
|
;;
|
|
c)
|
|
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
image_check '0'
|
|
loop_device_attach '0'
|
|
mount_device '0'
|
|
bind_filesystem '0'
|
|
message 'Prepare System-Resolver'
|
|
RESOLVCONF='0'
|
|
if [[ -L "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" ]]; then
|
|
RESOLVCONF='1'
|
|
/usr/bin/unlink "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
|
|
error '\r\rPrepare System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be unlinked.\n'
|
|
fi
|
|
/usr/bin/cp --force '/etc/resolv.conf' "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
|
|
error '\r\rPrepare System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be copied.\n'
|
|
message '\r\rPrepare System-Resolver \xE2\x9C\x94\n'
|
|
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'
|
|
message 'Reset System-Resolver'
|
|
/usr/bin/rm --force "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
|
|
error '\r\rReset System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be removed.\n'
|
|
if [[ "${RESOLVCONF}" == '1' ]]; then
|
|
/usr/bin/ln --force --symbolic '../run/systemd/resolve/stub-resolv.conf' "/mnt/${LODEV_0_BASENAME}/etc/resolv.conf" || \
|
|
error '\r\rReset System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be linked.\n'
|
|
fi
|
|
unset RESOLVCONF
|
|
message '\r\rReset System-Resolver \xE2\x9C\x94\n'
|
|
umount_device '0'
|
|
loop_device_detach '0'
|
|
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}")
|
|
image_check '0'
|
|
loop_device_attach '0'
|
|
mount_device '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}")
|
|
message 'Create empty 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 empty image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be created.\n'
|
|
/usr/bin/sync -d "${IMG_1_REALPATH}" || \
|
|
error '\r\rCreate empty image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be synced.\n'
|
|
message '\r\rCreate emtpy image \xE2\x9C\x94\n'
|
|
message 'Create partition table'
|
|
/usr/sbin/parted --script "${IMG_1_REALPATH}" mklabel msdos mkpart primary fat32 1049kB 269MB &> '/dev/null' || \
|
|
error '\r\rCreate partition table \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The boot partition can not be created.\n'
|
|
/usr/sbin/parted --script "${IMG_1_REALPATH}" mkpart primary ext4 269MB 100% &> '/dev/null' || \
|
|
error '\r\rCreate partition table \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The root partition can not be created.\n'
|
|
message '\r\rCreate partition table \xE2\x9C\x94\n'
|
|
image_check '1'
|
|
loop_device_attach '1'
|
|
message 'Create filesystem'
|
|
/usr/sbin/mkfs.vfat -c -F '32' -n 'FIRMWARE' "${LODEV_1_REALPATH}p1" &> '/dev/null' || \
|
|
error '\r\rCreate filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesystem vfat on boot partition can 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 filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesytem ext4 on root partition can not be created.\n'
|
|
message '\r\rCreate filesystem \xE2\x9C\x94\n'
|
|
mount_device '1'
|
|
message 'Synchronize 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 images \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The images can not be syncronized.\n'
|
|
message '\r\rSynchronize images \xE2\x9C\x94\n'
|
|
umount_device '0'
|
|
loop_device_detach '0'
|
|
message 'Correct 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\rCorrect partition UUID \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The UUID can 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\rCorrect partition UUID \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The UUID can not be written to 'fstab'.\n'
|
|
message '\r\rCorrect partition UUID \xE2\x9C\x94\n'
|
|
message 'Defragment image'
|
|
/usr/sbin/e4defrag "/mnt/${LODEV_1_BASENAME}" &> '/dev/null' || \
|
|
error '\r\rDefragment image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be defragmented.\n'
|
|
message '\r\rDefragment image \xE2\x9C\x94\n'
|
|
message 'Trim image'
|
|
/usr/sbin/fstrim "/mnt/${LODEV_1_BASENAME}" || \
|
|
error '\r\rTrim image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be trimmed.\n'
|
|
message '\r\rTrim image \xE2\x9C\x94\n'
|
|
umount_device '1'
|
|
message 'Adjust image moint point'
|
|
/usr/sbin/tune2fs -M '/' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
|
|
error '\r\rAdjust image mount point \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The mount point can not be adjusted.\n'
|
|
message '\r\rAdjust image mount point \xE2\x9C\x94\n'
|
|
fsck_device '1'
|
|
shrink_filesystem '1'
|
|
loop_device_detach '1'
|
|
shrink_partition '1'
|
|
shrink_image '1'
|
|
partuuid '1'
|
|
loop_device_attach '1'
|
|
fsck_device '1'
|
|
loop_device_detach '1'
|
|
exit 0
|
|
;;
|
|
e)
|
|
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
image_check '0'
|
|
loop_device_attach '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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partition UUID can not be saved.\n'
|
|
message '\r\rSave partition UUID \xE2\x9C\x94\n'
|
|
loop_device_detach '0'
|
|
expand_image '0'
|
|
expand_partition '0'
|
|
loop_device_attach '0'
|
|
fsck_device '0'
|
|
expand_filesystem '0'
|
|
fsck_device '0'
|
|
loop_device_detach '0'
|
|
partuuid '0'
|
|
exit 0
|
|
;;
|
|
h)
|
|
set +e
|
|
help 'command'
|
|
exit 0
|
|
;;
|
|
m)
|
|
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
image_check '0'
|
|
loop_device_attach '0'
|
|
mount_device '0'
|
|
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%%.*}"
|
|
image_check '0'
|
|
message 'Load configuration'
|
|
if [ -f "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.cfg" ]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.cfg" "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.cfg" || \
|
|
error '\r\rLoad configuration \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The configuration can not be copied.\n'
|
|
elif [[ ! -f "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.cfg" ]]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/raspi-image/default.cfg" "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.cfg" || \
|
|
error '\r\rLoad configuration \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The configuration can not be copied.\n'
|
|
fi
|
|
/usr/bin/nano "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.cfg" || \
|
|
error '\r\rLoad configuration \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The configuration can not be written.\n'
|
|
message '\r\rLoad configuration \xE2\x9C\x94\n'
|
|
. "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.cfg"
|
|
loop_device_attach '0'
|
|
mount_device '0'
|
|
message 'Set 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\rSet hostname \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hostname can not be set.\n'
|
|
done
|
|
elif [[ -z "${HOSTNAME}" ]]; then
|
|
error '\r\rSet hostname \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hostname is not set.\n'
|
|
fi
|
|
message '\r\rSet hostname \xE2\x9C\x94\n'
|
|
message 'Set Root password'
|
|
if [[ -n "${ROOT_PASSWORD}" ]]; then
|
|
/usr/bin/echo 'root':"${ROOT_PASSWORD}" | /usr/sbin/chpasswd --root "/mnt/${LODEV_0_BASENAME}" || \
|
|
error '\r\rSet Root password \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Root password can not be set.\n'
|
|
elif [[ -z "${ROOT_PASSWORD}" ]]; then
|
|
error '\r\rSet Root password \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Root password is not set.\n'
|
|
fi
|
|
message '\r\rSet Root password \xE2\x9C\x94\n'
|
|
if [[ -n "${SSH_PUBKEY}" ]]; then
|
|
message 'Set 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\rSet Secure Shell Public Key \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Secure Shell Public Key can not be set.\n'
|
|
message '\r\rSet Secure Shell Public Key \xE2\x9C\x94\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 --expression="s/pmf=.*/pmf=${WIFI_PMF}" "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf" || \
|
|
error '\r\rPrepare WiFi settings \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The WiFi Protected Management Frames can not be set.\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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The WiFi credentials can not be removed.\n'
|
|
/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\rPrepare WiFi settings \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The WiFi credentials can not be set.\n'
|
|
/usr/bin/echo '# RPI-IMAGE AUTOCONFIG END' >> "/mnt/${LODEV_0_BASENAME}/etc/wpa_supplicant/wpa_supplicant.conf"
|
|
message '\r\rPrepare WiFi settings \xE2\x9C\x94\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 Root certificate [RSA]'
|
|
/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 Root certificate [RSA] \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The certificate can not be generated.\n'
|
|
message '\r\rGenerate Root certificate [RSA] \xE2\x9C\x94\n'
|
|
message 'Generate Root certificate [ECDSA]'
|
|
/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 Root certificate [ECDSA] \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The certificate can not be generated.\n'
|
|
message '\r\rGenerate Root certificate [ECDSA] \xE2\x9C\x94\n'
|
|
fi
|
|
if [[ "${DHPEM}" == 'true' ]] && \
|
|
[[ -n "${DHPEM_SIZE}" ]]; then
|
|
for SIZE in ${DHPEM_SIZE}; do
|
|
message "Generate DHPEM [dh${SIZE}.pem]"
|
|
/usr/bin/openssl dhparam -out "/mnt/${LODEV_0_BASENAME}/etc/ssl/dhpem/dh${SIZE}.pem" -2 "${SIZE}" &> '/dev/null' || \
|
|
error "\r\rGenerate DHPEM [dh${SIZE}.pem] \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The DHPEM file can not be generated.\n'
|
|
message "\r\rGenerate DHPEM [dh${SIZE}.pem] \xE2\x9C\x94\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 empty 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 empty image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be created.\n'
|
|
/usr/bin/sync -d "${IMG_1_REALPATH}" || \
|
|
error '\r\rCreate empty image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be synced.\n'
|
|
message '\r\rCreate emtpy image \xE2\x9C\x94\n'
|
|
message 'Create partition table'
|
|
/usr/sbin/parted --script "${IMG_1_REALPATH}" mklabel msdos mkpart primary fat32 1049kB 269MB &> '/dev/null' || \
|
|
error '\r\rCreate partition table \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The boot partition can not be created.\n'
|
|
/usr/sbin/parted --script "${IMG_1_REALPATH}" mkpart primary ext4 269MB 100% &> '/dev/null' || \
|
|
error '\r\rCreate partition table \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The root partition can not be created.\n'
|
|
message '\r\rCreate partition table \xE2\x9C\x94\n'
|
|
image_check '1'
|
|
loop_device_attach '1'
|
|
message 'Create filesystem'
|
|
/usr/sbin/mkfs.vfat -c -F '32' -n 'FIRMWARE' "${LODEV_1_REALPATH}p1" &> '/dev/null' || \
|
|
error '\r\rCreate filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesystem vfat on boot partition can 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 filesystem \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filesytem ext4 on root partition can not be created.\n'
|
|
message '\r\rCreate filesystem \xE2\x9C\x94\n'
|
|
mount_device '1'
|
|
message 'Synchronize 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 images \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The images can not be syncronized.\n'
|
|
message '\r\rSynchronize images \xE2\x9C\x94\n'
|
|
umount_device '0'
|
|
loop_device_detach '0'
|
|
message 'Correct 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\rCorrect partition UUID \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The UUID can 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\rCorrect partition UUID \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The UUID can not be written to 'fstab'.\n'
|
|
message '\r\rCorrect partition UUID \xE2\x9C\x94\n'
|
|
message 'Defragment image'
|
|
/usr/sbin/e4defrag "/mnt/${LODEV_1_BASENAME}" &> '/dev/null' || \
|
|
error '\r\rDefragment image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be defragmented.\n'
|
|
message '\r\rDefragment image \xE2\x9C\x94\n'
|
|
message 'Trim image'
|
|
/usr/sbin/fstrim "/mnt/${LODEV_1_BASENAME}" || \
|
|
error '\r\rTrim image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be trimmed.\n'
|
|
message '\r\rTrim image \xE2\x9C\x94\n'
|
|
umount_device '1'
|
|
message 'Adjust image moint point'
|
|
/usr/sbin/tune2fs -M '/' "${LODEV_1_REALPATH}p2" &> '/dev/null' || \
|
|
error '\r\rAdjust image mount point \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The mount point can not be adjusted.\n'
|
|
message '\r\rAdjust image mount point \xE2\x9C\x94\n'
|
|
fsck_device '1'
|
|
shrink_filesystem '1'
|
|
loop_device_detach '1'
|
|
shrink_partition '1'
|
|
shrink_image '1'
|
|
partuuid '1'
|
|
loop_device_attach '1'
|
|
fsck_device '1'
|
|
loop_device_detach '1'
|
|
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%%.*}"
|
|
image_check '0'
|
|
loop_device_attach '0'
|
|
mount_device '0'
|
|
message 'Load filelist'
|
|
if [[ -f "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.txt" ]]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.txt" "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.txt" || \
|
|
error '\r\rLoad filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The default filelist can not be copied.\n'
|
|
elif [[ ! -f "/usr/lib/raspi-image/${IMG_0_CLEARNAME}.txt" ]]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/raspi-image/default.txt" "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.txt" || \
|
|
error '\r\rLoad filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The default filelist can not be copied.\n'
|
|
fi
|
|
/usr/bin/nano "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.txt" || \
|
|
error '\r\rLoad filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filelist can not be opened.\n'
|
|
message '\r\rLoad filelist \xE2\x9C\x94\n'
|
|
message 'Remove Root password'
|
|
/usr/bin/passwd --delete --quiet --root "/mnt/${LODEV_0_BASENAME}" 'root' || \
|
|
error '\r\rRemove Root password \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Root password can not be removed.\n'
|
|
/usr/bin/passwd --lock --quiet --root "/mnt/${LODEV_0_BASENAME}" 'root' || \
|
|
error '\r\rRemove Root password \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The Root account can not be locked.\n'
|
|
message '\r\rRemove Root password \xE2\x9C\x94\n'
|
|
message 'Remove files'
|
|
mapfile -t CLEANUP_LIST < <(/usr/bin/cat "${IMG_0_DIRNAME}/${IMG_0_CLEARNAME}.txt" | /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 \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file or directory >${CLEANUP_LIST}< can not be removed.\n"
|
|
done
|
|
unset CLEANUP_LIST
|
|
message '\r\rRemove files \xE2\x9C\x94\n'
|
|
message 'Clear logfiles'
|
|
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\rClear logfiles \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file >${CLEANUP_LIST}< can not be cleared.\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\rClear logfiles \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file >${CLEANUP_LIST}< can not be removed.\n"
|
|
done
|
|
message '\r\rClear logfiles \xE2\x9C\x94\n'
|
|
message 'Remove WiFi credentials'
|
|
/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\rRemove WiFi credentials \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The WiFi credentials can not be removed.\n'
|
|
message '\r\rRemove WiFi credentials \xE2\x9C\x94\n'
|
|
umount_device '0'
|
|
loop_device_detach '0'
|
|
exit 0
|
|
;;
|
|
r)
|
|
message 'Download image'
|
|
if [[ -f "./${OPTARG}.img" ]]; then
|
|
error '\r\rDownload image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image already exists.\n'
|
|
fi
|
|
/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 image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can 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 image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image SHA512SUM can not be downloaded.\n'
|
|
message '\r\rDownload image \xE2\x9C\x94\n'
|
|
message 'Compare hash'
|
|
/usr/bin/sha512sum --check --strict "./${OPTARG}.img.xz.sha512sum" &> '/dev/null' || \
|
|
error '\r\rCompare hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hash can not be verified.\n'
|
|
/usr/bin/rm --force "./${OPTARG}.img.xz.sha512sum" || \
|
|
error '\r\rCompare hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hash can not be removed.\n'
|
|
message '\r\rCompare hash \xE2\x9C\x94\n'
|
|
message 'Decompress image'
|
|
/usr/bin/xz --decompress --quiet "./${OPTARG}.img.xz" || \
|
|
error '\r\rDecompress image \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The image can not be decompressed.\n'
|
|
message '\r\rDecompress image \xE2\x9C\x94\n'
|
|
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}")
|
|
image_check '0'
|
|
loop_device_attach '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 \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The partition UUID can not be saved.\n'
|
|
message '\r\rSave partition UUID \xE2\x9C\x94\n'
|
|
fsck_device '0'
|
|
shrink_filesystem '0'
|
|
loop_device_detach '0'
|
|
shrink_partition '0'
|
|
shrink_image '0'
|
|
partuuid '0'
|
|
loop_device_attach '0'
|
|
fsck_device '0'
|
|
loop_device_detach '0'
|
|
exit 0
|
|
;;
|
|
u)
|
|
IMG_0_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
IMG_0_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
image_check '0'
|
|
/usr/sbin/losetup --list --noheadings --output 'NAME,BACK-FILE' --raw | /usr/bin/grep --quiet "${IMG_0_REALPATH}" && \
|
|
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}")
|
|
/usr/bin/test -n "${LODEV_0_REALPATH}" || \
|
|
error ' \xE2\x86\x92 Error: The selected file is not be mounted.\n'
|
|
LODEV_0_BASENAME=$(/usr/bin/basename "${LODEV_0_REALPATH}")
|
|
umount_device '0'
|
|
loop_device_detach '0'
|
|
exit 0
|
|
;;
|
|
-*|*)
|
|
set +e
|
|
case "${1}" in
|
|
-a)
|
|
help 'archive'
|
|
exit 0
|
|
;;
|
|
-c)
|
|
help 'chroot'
|
|
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))
|