aboutsummaryrefslogtreecommitdiffstats
path: root/isocomp.sh
diff options
context:
space:
mode:
author Eric Hameleers <alien@slackware.com>2022-08-15 20:42:11 +0200
committer Eric Hameleers <alien@slackware.com>2022-08-15 20:42:11 +0200
commitdd0327d77f2741474245ecd3026cf66e55581733 (patch)
treebd9c4682e21ddf13789c33db3dc5046d2bda9d1c /isocomp.sh
parentfea7b0264016240fd1b5c06b26a70a7f7f219546 (diff)
downloadliveslak-dd0327d77f2741474245ecd3026cf66e55581733.tar.gz
liveslak-dd0327d77f2741474245ecd3026cf66e55581733.tar.xz
Full support for Ventoy; encrypted OS persistence/homedirectory for ISO boot
New features: Ventoy is now fully supported. Liveslak implements the "Ventoy-compatible" guideline. There is nothing you have to do, this works out of the box. When you are booting from an ISO file (whether via Ventoy, or through your own hand-crafted Grub menu entry, or Windows BCD), Operating System persistence and an encrypted homedirectory are now supported, as well as the ability to load additional live modules (as 'addons' or 'optional') that are not part of the ISO. All of this is possible without the need for any modification to the ISO image. The configuration is stored in a file next to the ISO. A new script, "isocomp.sh" aka the ISO Companion script, has been added. Like with all of my scripts, it accepts a "--help" parameter which will show you how to use it. This script allows you to: - create encrypted containers for OS persistence and a persistent homedirectory (actually not just for /home but you can create as many containers as fit on the disk and mount them wherever you want) - size extension of existing encrypted containers if they threaten to run out of space - creating a secondary liveslak root on the disk partition where you can add more (optional/add-on) live modules that you need in the Live OS but are not contained in the ISO The configuration of these new features is stored in a file with the same name and full path as the ISO file but with a ".cfg" file extension instead of ".iso". The "isocomp.sh" script manages this configuration file for you, but you can safely edit and modify it manually if you want to. The "isocomp.sh" script will leave your customizations alone. Here is an example of such a configuration file; it is copied from my own Ventoy disk, for a Slackware LEAN Live ISO image: LIVESLAKROOT=/liveslak LUKSVOL=/liveslak/myhome.icc:/home ISOPERSISTENCE=/liveslak/persistence.icc TZ=Europe/Amsterdam LIVE_HOSTNAME=zelazny I added the variables "TZ" and "LIVE_HOSTNAME" manually by opening the configuration file in an editor. The following variables are supported in the isocomp configuration file, but not managed by "isocomp.sh"; they all correspond to liveslak boot parameters by the way: BLACKLIST, KEYMAP, LIVE_HOSTNAME, LOAD, LOCALE, NOLOAD, RUNLEVEL, TWEAKS, TZ and XKB. The value of the "LUKSVOL" variable can hold multiple "containerfile:mountpoint" definitions, separated by commas. The variable "LIVESLAKROOT" defines the root of a secondary liveslak directory tree on your disk.
Diffstat (limited to 'isocomp.sh')
-rw-r--r--isocomp.sh763
1 files changed, 763 insertions, 0 deletions
diff --git a/isocomp.sh b/isocomp.sh
new file mode 100644
index 0000000..a1884df
--- /dev/null
+++ b/isocomp.sh
@@ -0,0 +1,763 @@
+#!/bin/bash
+#
+# Copyright 2022 Eric Hameleers, Eindhoven, NL
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# -----------------------------------------------------------------------------
+#
+# This script can perform some specific changes on the USB stick
+# containing an ISO of Slackware Live Edition,
+# when you boot from that ISO using a multi-boot manager.
+# - create a directory structure on the USB partition to add more
+# functionality to the ISO (e.g. load extra addons/optional modules).
+# - create an encrypted container file for storing persistence data.
+# - create an encrypted container file to mount on /home .
+# - write all the above information into a configuration file for the ISO.
+#
+# -----------------------------------------------------------------------------
+
+# Be careful:
+set -e
+
+# Limit the search path:
+export PATH="/usr/sbin:/sbin:/usr/bin:/bin"
+
+# Use of force is sometimes needed:
+FORCE=0
+
+# Version is obtained from the ISO metadata:
+VERSION=""
+
+# The extension for containerfiles accompanying an ISO is '.icc',
+# whereas the persistent USB stick created with iso2usb.sh uses '.img'.
+DEFEXT=".icc"
+CNTEXT="${DEFEXT}"
+
+# Default mount point for a LUKS container if not specified:
+DEFMNT="/home"
+LUKSMNT=""
+
+# Values for container sizes:
+PERSSIZE=""
+LUKSSIZE=""
+INCSIZE=""
+LUKSVOL=""
+
+# Associative array to capture LUKSVOL definitions:
+declare -A CONTAINERS=()
+
+# Values obtained from a pre-existing .cfg file:
+ISOPERSISTENCE=""
+LUKSCNT=""
+LIVESLAKROOT=""
+
+# Define ahead of time, so that cleanup knows about them:
+IMGDIR=""
+ISOMNT=""
+CNTMNT=""
+EXTENSION=""
+PERSISTENCE=""
+
+# Minimim free space (in MB) we want to have left in any partition
+# after we are done.
+# The default value can be changed from the environment:
+MINFREE=${MINFREE:-10}
+
+# Compressor used on the initrd ("gzip" or "xz --check=crc32");
+# Note that the kernel's XZ decompressor does not understand CRC64:
+COMPR="xz --check=crc32"
+
+# These tools are required by the script, we will check for their existence:
+REQTOOLS="cpio cryptsetup fsck gzip isoinfo lsblk resize2fs unsquashfs xz zstd"
+
+#
+# -- function definitions --
+#
+
+# Clean up in case of failure:
+cleanup() {
+ # Clean up by unmounting our loopmounts, deleting tempfiles:
+ echo "--- Cleaning up the staging area..."
+ # During cleanup, do not abort due to non-zero exit code:
+ set +e
+ sync
+
+ if [ -n "$CNTDEV" ]; then
+ # In case of failure, only most recent LUKS mapped device is still open:
+ if mount | grep -q ${CNTDEV} ; then
+ umount -f ${CNTDEV}
+ cryptsetup luksClose $(basename ${CNTFILE} ${CNTEXT})
+ losetup -d ${LODEV}
+ fi
+ fi
+ [ -n "${ISOMNT}" ] && ( umount -f ${ISOMNT} 2>/dev/null; rmdir $ISOMNT 2>/dev/null )
+ [ -n "${CNTMNT}" ] && ( umount -f ${CNTMNT} 2>/dev/null; rmdir $CNTMNT 2>/dev/null )
+ [ -n "${IMGDIR}" ] && ( rm -rf $IMGDIR )
+ set -e
+} # End of cleanup()
+
+trap 'echo "*** $0 FAILED at line $LINENO ***"; cleanup; exit 1' ERR INT TERM
+
+# Show the help text for this script:
+showhelp() {
+cat <<EOT
+#
+# Purpose: enhance the functionality when booting a Slackware Live ISO file.
+# When supplying pathnames as parameter values below, use full pathnames in
+# your local filesystem. The script will figure out where your USB disk
+# partition is mounted and will adjust the path names accordingly
+# in the USB configuration.
+#
+# $(basename $0) accepts the following parameters:
+# -d|--directory <path> Create a liveslak directory structure to store
+# additional modules. The parameter value is
+# used as the root path below which the
+# liveslak/{addons,optional} subdirectories
+# will be created.
+# -e|--examples Show some common usage examples.
+# -f|--force Force execution in some cases where the script
+# reports an issue.
+# -h|--help This help text.
+# -i|--iso <fullpath> Full path to your liveslak ISO image.
+# -l|--lukscontainer <fullpath> Full path to encrypted container file to be
+# created by this script, and to be mounted
+# in the live OS under /home
+# (or any other mountpoint you supply).
+# (filename needs to end in '${CNTEXT}'!).
+# -p|--persistence <fullpath > Full path to encrypted persistence container
+# file to be created in the filesystem
+# (filename extension must be '${CNTEXT}'!).
+# -x|--extend <fullpath> Full path to existing (encrypted) container
+# file that you want to extend in size
+# (filename needs to end in '${CNTEXT}'!).
+# Limitations:
+# - container needs to be LUKS encrypted, and
+# - internal filesystem needs to be ext{2,3,4}.
+# -L|--lcsize <size|perc> Size of LUKS encrypted /home ; value is the
+# requested size of the container in kB, MB, GB,
+# or as a percentage of free space
+# (integer numbers only).
+# Examples: '-L 125M', '-L 2G', '-L 20%'.
+# -P|--perssize <size|perc> Size of persistence container ; value is the
+# requested size of the container in kB, MB, GB,
+# or as a percentage of free space
+# (integer numbers only).
+# Examples: '-P 125M', '-P 2G', '-P 20%'.
+# -X|--extendsize <size|perc> Extend size of existing container; value
+# is the requested extension of the container
+# in kB, MB, GB, or as percentage of free space
+# (integer numbers only).
+# Examples: '-X 125M', '-X 2G', '-X 20%'.
+#
+EOT
+} # End of showhelp()
+
+# Show some common usage examples:
+showexamples() {
+cat <<EOT
+#
+# Some common usage examples for $(basename $0)
+# ---------------------------------------------------------------------------
+# First, mount your USB partition, for instance
+# a Ventoy disk will be mounted for you at /run/media/<user>/Ventoy/.
+# Then:
+# ---------------------------------------------------------------------------
+# Create a 1GB encrypted persistence container:
+# ./$(basename $0) -p /run/media/<user>/Ventoy/myfiles/persistence.icc -P 1G
+#
+# Create a 4GB encrypted home:
+# ./$(basename $0) -l /run/media/<user>/Ventoy/somedir/lukscontainers.icc -L 4000M -i /run/media/<user>/Ventoy/slackware64-live-current.iso
+#
+# Increase the size of that encrypted home container with another 2GB:
+# ./$(basename $0) -x /run/media/<user>/Ventoy/somedir/lukscontainers.icc -X 2G -i /run/media/<user>/Ventoy/slackware64-live-current.iso
+#
+# Create a 10GB encrypted container to be mounted on /data in the Live OS:
+# ./$(basename $0) -l /run/media/<user>/Ventoy/somedir/mydata.icc:/data -L 10G -i /run/media/<user>/Ventoy/slackware64-live-current.iso
+#
+# Create a liveslak directory structure for adding extra live modules:
+# ./$(basename $0) -d /run/media/<user>/Ventoy/myliveslak -i /run/media/<user>/Ventoy/slackware64-live-current.iso
+#
+EOT
+} # End of showexamples()
+
+# Uncompress the initrd based on the compression algorithm used:
+uncompressfs () {
+ if $(file "${1}" | grep -qi ": gzip"); then
+ gzip -cd "${1}"
+ elif $(file "${1}" | grep -qi ": XZ"); then
+ xz -cd "${1}"
+ fi
+} # End of uncompressfs()
+
+# Read configuration data from the initrd inside the ISO:
+read_initrd() {
+ local IMGDIR="$1"
+ cd ${IMGDIR}
+
+ # Read the values of liveslak template variables in the init script:
+ for TEMPLATEVAR in DISTRO LIVEMAIN MARKER MEDIALABEL ; do
+ eval $(grep "^ *${TEMPLATEVAR}=" ./init |head -1)
+ done
+} # End read_initrd()
+
+# Extract the initrd:
+extract_initrd() {
+ local IMGFILE="$1"
+ local IMGDIR=$(mktemp -d -p /tmp -t alienimg.XXXXXX)
+ if [ ! -d $IMGDIR ]; then
+ echo "*** Failed to create temporary extraction directory for the initrd!"
+ cleanup
+ exit 1
+ else
+ chmod 711 $IMGDIR
+ fi
+
+ cd ${IMGDIR}
+ uncompressfs ${IMGFILE} 2>/dev/null \
+ | cpio -i -d -m -H newc 2>/dev/null
+ echo "$IMGDIR"
+} # End of extract_initrd()
+
+# Determine size of a mounted partition (in MB):
+get_part_mb_size() {
+ local MYSIZE
+ MYSIZE=$(df -P -BM ${1} |tail -n -1 |tr -s '\t' ' ' |cut -d' ' -f2)
+ echo "${MYSIZE%M}"
+} # End of get_part_mb_size()
+
+# Determine free space of a mounted partition (in MB):
+get_part_mb_free() {
+ local MYSIZE
+ MYSIZE=$(df -P -BM ${1} |tail -n -1 |tr -s '\t' ' ' |cut -d' ' -f4)
+ echo "${MYSIZE%M}"
+} # End of get_part_mb_free()
+
+# Determine requested container size in MB (allow for '%|k|K|m|M|g|G' suffix):
+cont_mb() {
+ local MYSIZE="$1"
+ case "${MYSIZE: -1}" in
+ "%") MYSIZE="$(( $PARTFREE * ${MYSIZE%\%} / 100 ))" ;;
+ "k") MYSIZE="$(( ${MYSIZE%k} / 1024 ))" ;;
+ "K") MYSIZE="$(( ${MYSIZE%K} / 1024 ))" ;;
+ "m") MYSIZE="${MYSIZE%m}" ;;
+ "M") MYSIZE="${MYSIZE%M}" ;;
+ "g") MYSIZE="$(( ${MYSIZE%g} * 1024 ))" ;;
+ "G") MYSIZE="$(( ${MYSIZE%G} * 1024 ))" ;;
+ *) MYSIZE=-1 ;;
+ esac
+ echo "$MYSIZE"
+} # End of cont_mb()
+
+# Expand existing encrypted container file:
+expand_container() {
+ local MYPART="$1" # disk partition
+ local MYINC="$2" # requested increase ('%|k|K|m|M|g|G' suffix)
+ local MYFILE="$3" # full path to ${CNTEXT} containerfile
+ local MYMAP="" # Name of the device-mapped file
+
+ # Determine requested container increase in MB:
+ MYINC=$(cont_mb ${MYINC})
+
+ # Determine size of the target partition (in MB), and the free space:
+ PARTSIZE=$(get_part_mb_size ${MYPART})
+ PARTFREE=$(get_part_mb_free ${MYPART})
+
+ if [ $PARTFREE -lt $(( ${MYINC} + ${MINFREE} )) ]; then
+ echo "*** Free space on USB partition after file-resizing would be less than ${MINFREE} MB;"
+ echo "*** Not resizing the container file!"
+ cleanup
+ exit 1
+ fi
+
+ # Append random bytes to the end of the container file:
+ dd if=/dev/urandom of=${MYFILE} bs=1M count=${MYINC} oflag=append conv=notrunc 2>/dev/null
+
+ # Unlock the LUKS encrypted container:
+ MYMAP=$(basename ${MYFILE} ${CNTEXT})
+ echo "--- Unlocking the LUKS container requires your passphrase..."
+ until cryptsetup luksOpen ${MYFILE} ${MYMAP} ; do
+ echo ">>> Did you type an incorrect passphrases?"
+ read -p ">>> Press [ENTER] to try again or Ctrl-C to abort ..." REPLY
+ done
+
+ # Run fsck so the filesystem is clean before we resize it:
+ fsck -fvy /dev/mapper/${MYMAP}
+ # Resize the filesystem to occupy the full new size:
+ resize2fs /dev/mapper/${MYMAP}
+ # Just to be safe:
+ fsck -fvy /dev/mapper/${MYMAP}
+} # End of expand_container()
+
+# Create container file in the empty space of the partition
+create_container() {
+ CNTPART=$1 # partition containing the ISO
+ CNTSIZE=$2 # size of the container file to create
+ CNTFILE=$3 # ${CNTEXT} filename with full path
+ CNTENCR=$4 # 'none' or 'luks'
+ CNTUSED=$5 # 'persistence', '/home' or custom mountpoint
+
+ # Create a container file or re-use previously created one:
+ if [ -f ${CNTFILE} ]; then
+ CNTSIZE=$(( $(du -sk ${CNTFILE} |tr '\t' ' ' |cut -f1 -d' ') / 1024 ))
+ echo "--- Keeping existing '${CNTFILE}' (size ${CNTSIZE} MB)."
+ return
+ fi
+
+ # Determine size of the target partition (in MB), and the free space:
+ PARTSIZE=$(get_part_mb_size ${CNTPART})
+ PARTFREE=$(get_part_mb_free ${CNTPART})
+
+ if [ $PARTFREE -lt ${MINFREE} ]; then
+ echo "*** Free space on USB partition is less than ${MINFREE} MB;"
+ echo "*** Not creating a container file!"
+ cleanup
+ exit 1
+ fi
+
+ # Determine requested container size in MB (allow for '%|k|K|m|M|g|G' suffix):
+ CNTSIZE=$(cont_mb ${CNTSIZE})
+
+ if [ $CNTSIZE -le 0 ]; then
+ echo "*** Container size must be larger than ZERO!"
+ echo "*** Check your commandline parameter."
+ cleanup
+ exit 1
+ elif [ $CNTSIZE -ge $PARTFREE ]; then
+ echo "*** Not enough free space for container file!"
+ echo "*** Check your commandline parameter."
+ cleanup
+ exit 1
+ fi
+
+ echo "--- Creating ${CNTSIZE} MB container file using 'dd if=/dev/urandom', patience please..."
+ mkdir -p $(dirname "${CNTFILE}")
+ # Create a sparse file (not allocating any space yet):
+ dd of=${CNTFILE} bs=1M count=0 seek=$CNTSIZE 2>/dev/null
+
+ # Setup a loopback device that we can use with cryptsetup:
+ LODEV=$(losetup -f)
+ losetup $LODEV ${CNTFILE}
+ if [ "${CNTENCR}" = "luks" ]; then
+ # Format the loop device with LUKS:
+ echo "--- Encrypting the container file with LUKS; takes SOME time..."
+ echo "--- enter 'YES' and a passphrase:"
+ until cryptsetup -y luksFormat $LODEV ; do
+ echo ">>> Did you type two different passphrases?"
+ read -p ">>> Press [ENTER] to try again or Ctrl-C to abort ..." REPLY
+ done
+ # Unlock the LUKS encrypted container:
+ echo "--- Unlocking the LUKS container requires your passphrase again..."
+ until cryptsetup luksOpen $LODEV $(basename ${CNTFILE} ${CNTEXT}) ; do
+ echo ">>> Did you type an incorrect passphrases?"
+ read -p ">>> Press [ENTER] to try again or Ctrl-C to abort ..." REPLY
+ done
+ CNTDEV=/dev/mapper/$(basename ${CNTFILE} ${CNTEXT})
+ # Now we allocate blocks for the LUKS device. We write encrypted zeroes,
+ # so that the file looks randomly filled from the outside.
+ # Take care not to write more bytes than the internal size of the container:
+ echo "--- Writing random data to encrypted container; takes LONG time..."
+ CNTIS=$(( $(lsblk -b -n -o SIZE $(readlink -f ${CNTDEV})) / 512))
+ dd if=/dev/zero of=${CNTDEV} bs=512 count=${CNTIS} 2>/dev/null || true
+ else
+ CNTDEV=$LODEV
+ # Un-encrypted container files remain sparse.
+ fi
+
+ # Format the now available block device with a linux fs:
+ mkfs.ext4 ${CNTDEV}
+ # Tune the ext4 filesystem:
+ tune2fs -m 0 -c 0 -i 0 ${CNTDEV}
+
+ if [ "${CNTUSED}" == "${DEFMNT}" ]; then
+ # Copy the original /home content into the container.
+ # NOTE: we only do this for /home, not for any other mountpoint!
+
+ # Create a mount point for the unlocked container:
+ CNTMNT=$(mktemp -d -p /var/tmp -t aliencnt.XXXXXX)
+ if [ ! -d $CNTMNT ]; then
+ echo "*** Failed to create temporary mount point for the LUKS container!"
+ cleanup
+ exit 1
+ else
+ chmod 711 $CNTMNT
+ fi
+ echo "--- Copying '${CNTUSED}' from ISO to container..."
+ HOMESRC=$(find ${ISOMNT} -name "0099-slackware_zzzconf*" |tail -1)
+ mount ${CNTDEV} ${CNTMNT}
+ unsquashfs -n -d ${CNTMNT}/temp ${HOMESRC} ${CNTUSED}
+ mv ${CNTMNT}/temp/${CNTUSED}/* ${CNTMNT}/
+ rm -rf ${CNTMNT}/temp
+ umount ${CNTDEV}
+ fi
+
+ # Don't forget to clean up after ourselves:
+ if [ "${CNTENCR}" = "luks" ]; then
+ cryptsetup luksClose $(basename ${CNTFILE} ${CNTEXT})
+ fi
+ losetup -d ${LODEV} || true
+
+} # End of create_container()
+
+read_config() {
+ local MYISO="${1}"
+ # Read ISO customization from the .cfg file if it exists:
+ if [ -f "${MYISO%.iso}.cfg" ]; then
+ for LIVEPARM in \
+ BLACKLIST KEYMAP LIVE_HOSTNAME LIVESLAKROOT LOAD LOCALE LUKSVOL \
+ NOLOAD ISOPERSISTENCE RUNLEVEL TWEAKS TZ XKB ;
+ do
+ # Read values from disk only if the variable has not been set yet:
+ if [ -z "$(eval echo \$${LIVEPARM})" ]; then
+ eval $(grep -w ^${LIVEPARM} ${MYISO%.iso}.cfg)
+ fi
+ done
+ fi
+} # End of read_config()
+
+write_config() {
+ local MYISO="${1}"
+ # Write updated customization into the ISO .cfg:
+ echo "# Liveslak ISO configuration file for ${VERSION}" > ${MYISO%.iso}.cfg 2>/dev/null
+ echo "# Generated by $(basename $0) on $(date +%Y%m%d_%H%M)" >> ${MYISO%.iso}.cfg 2>/dev/null
+ if [ $? -ne 0 ]; then
+ echo "*** Media '${USBPART}' read-only, cannot write config file."
+ else
+ for LIVEPARM in \
+ BLACKLIST KEYMAP LIVE_HOSTNAME LIVESLAKROOT LOAD LOCALE LUKSVOL \
+ NOLOAD ISOPERSISTENCE RUNLEVEL TWEAKS TZ XKB ;
+ do
+ if [ -n "$(eval echo \$$LIVEPARM)" ]; then
+ echo $LIVEPARM=$(eval echo \$$LIVEPARM) >> ${MYISO%.iso}.cfg
+ fi
+ done
+ fi
+} # End of write_config()
+
+#
+# -- end of function definitions --
+#
+
+# ===========================================================================
+
+# Parse the commandline parameters:
+if [ -z "$1" ]; then
+ showhelp
+ exit 1
+fi
+while [ ! -z "$1" ]; do
+ case $1 in
+ -d|--directory)
+ LIVESLAKROOT="$2"
+ [[ ${LIVESLAKROOT::1} != "/" ]] && LIVESLAKROOT="$(pwd)/${LIVESLAKROOT}"
+ shift 2
+ ;;
+ -e|--examples)
+ showexamples
+ exit
+ ;;
+ -f|--force)
+ FORCE=1
+ shift
+ ;;
+ -h|--help)
+ showhelp
+ exit
+ ;;
+ -i|--iso)
+ SLISO="$(cd "$(dirname "$2")"; pwd)/$(basename "$2")"
+ shift 2
+ ;;
+ -l|--lukscontainer)
+ LUKSMNT="$(echo "$2" |cut -f2 -d:)"
+ LUKSCNT="$(echo "$2" |cut -f1 -d:)"
+ # If no mountpoint was specified, use the default mountpoint (/home):
+ [ "$LUKSMNT" == "$LUKSCNT" ] && LUKSMNT=${DEFMNT}
+ LUKSCNT="$(cd "$(dirname "$LUKSCNT")"; pwd)/$(basename "$LUKSCNT")"
+ shift 2
+ ;;
+ -p|--persistence)
+ PERSISTENCE="$(cd "$(dirname "$2")"; pwd)/$(basename "$2")"
+ shift 2
+ ;;
+ -x|--extend)
+ EXTENSION="$(cd "$(dirname "$2")"; pwd)/$(basename "$2")"
+ shift 2
+ ;;
+ -L|--lcsize)
+ LUKSSIZE="$2"
+ shift 2
+ ;;
+ -P|--perssize)
+ PERSSIZE="$2"
+ shift 2
+ ;;
+ -X|--extendsize)
+ INCSIZE="$2"
+ shift 2
+ ;;
+ *)
+ echo "*** Unknown parameter '$1'!"
+ exit 1
+ ;;
+ esac
+done
+
+#
+# Sanity checks:
+#
+
+if [ "$(id -u)" != "0" ]; then
+ echo "*** You need to be root to run $(basename $0)."
+ exit 1
+fi
+
+# Are all the required tools present?
+PROG_MISSING=""
+for PROGN in ${REQTOOLS} ; do
+ if ! which $PROGN 1>/dev/null 2>/dev/null ; then
+ PROG_MISSING="${PROG_MISSING}-- $PROGN\n"
+ fi
+done
+if [ ! -z "$PROG_MISSING" ] ; then
+ echo "--- Required program(s) not found in search path '$PATH'!"
+ echo -e ${PROG_MISSING}
+ if [ $FORCE -eq 0 ]; then
+ echo "--- Exiting."
+ exit 1
+ fi
+fi
+
+if [ -z "${SLISO}" ]; then
+ echo "*** You must specify the path to the Live ISO (option '-i')!"
+ exit 1
+fi
+
+if [ ! -f "$SLISO" ]; then
+ echo "*** This is not a useable file: '$SLISO' !"
+ exit 1
+fi
+
+if [ -z "${LIVESLAKROOT}${LUKSCNT}${PERSISTENCE}${EXTENSION}" ]; then
+ echo "*** No action requested!"
+ exit 1
+fi
+
+if [ -n "${PERSISTENCE}" ]; then
+ if [ -z "${PERSSIZE}" ]; then
+ echo "*** Persistence filename '${PERSISTENCE}' defined but no filesize provided!"
+ echo "*** Not enabling persistence, please use '-P' parameter."
+ exit 1
+ elif [ "$(basename ${PERSISTENCE} ${CNTEXT})" == "$(basename ${PERSISTENCE})" ]; then
+ echo "*** File '${PERSISTENCE}' does not have an '${CNTEXT}' extension!"
+ if [ $FORCE -eq 0 ]; then
+ exit 1
+ else
+ CNTEXT=$(basename ${PERSISTENCE})
+ if [ "${CNTEXT}" != "${CNTEXT##*.}" ]; then
+ # File has a different extension:
+ echo "--- Accepting '${CNTEXT##*.}' extension for '${PERSISTENCE}'."
+ CNTEXT=${CNTEXT##*.}
+ else
+ # File does not have an extension at all, so we add one:
+ echo "--- Adding '${DEFEXT}' extension to '${PERSISTENCE}'."
+ PERSISTENCE="${PERSISTENCE}${DEFEXT}"
+ fi
+ fi
+ fi
+fi
+
+if [ -n "${LUKSCNT}" ]; then
+ if [ -z "${LUKSSIZE}" ]; then
+ echo "*** LUKS container '${LUKSCNT}' defined but no filesize provided!"
+ echo "*** Not adding encrypted ${LUKSMNT}, please use '-L' parameter."
+ exit 1
+ elif [ "$(basename ${LUKSCNT} ${CNTEXT})" == "$(basename ${LUKSCNT})" ]; then
+ echo "*** File '${LUKSCNT}' does not have an '${CNTEXT}' extension!"
+ if [ $FORCE -eq 0 ]; then
+ exit 1
+ else
+ CNTEXT=$(basename ${LUKSCNT})
+ if [ "${CNTEXT}" != "${CNTEXT##*.}" ]; then
+ # File has a different extension:
+ echo "--- Accepting '${CNTEXT##*.}' extension for '${LUKSCNT}'."
+ CNTEXT=${CNTEXT##*.}
+ else
+ # File does not have an extension at all, so we add one:
+ echo "--- Adding '${DEFEXT}' extension to '${LUKSCNT}'."
+ LUKSCNT="${LUKSCNT}${DEFEXT}"
+ fi
+ fi
+ fi
+fi
+
+if [ -n "${EXTENSION}" ]; then
+ if [ -z "${INCSIZE}" ]; then
+ echo "*** LUKS container '${EXTENSION}' defined but no extansion size provided!"
+ echo "*** Not extending encrypted ${EXTENSION}, please use '-X' parameter."
+ exit 1
+ elif [ "$(basename ${EXTENSION} ${CNTEXT})" == "$(basename ${EXTENSION})" ]; then
+ echo "*** File '${EXTENSION}' does not have an '${CNTEXT}' extension!"
+ if [ $FORCE -eq 0 ]; then
+ exit 1
+ else
+ CNTEXT=$(basename ${EXTENSION})
+ if [ "${CNTEXT}" != "${CNTEXT##*.}" ]; then
+ # File has a different extension:
+ echo "--- Accepting '${CNTEXT##*.}' extension for '${EXTENSION}'."
+ CNTEXT=${CNTEXT##*.}
+ else
+ # File does not have an extension at all, so we add one:
+ echo "--- Adding '${DEFEXT}' extension to '${EXTENSION}'."
+ EXTENSION="${EXTENSION}${DEFEXT}"
+ fi
+ fi
+ fi
+fi
+
+# Determine name and mountpoint of the partition containing the ISO:
+USBPART=$(cd $(dirname ${SLISO}) ; df . |tail -n -1 |tr -s ' ' |cut -d' ' -f1)
+USBMNT=$(cd $(dirname ${SLISO}) ; df . |tail -n -1 |tr -s ' ' |cut -d' ' -f6)
+
+# Determine size of the USB partition (in MB), and the free space:
+USBPSIZE=$(get_part_mb_size ${USBMNT})
+USBPFREE=$(get_part_mb_free ${USBMNT})
+
+# Report the Slackware Live version:
+VERSION=$(isoinfo -d -i "${SLISO}" 2>/dev/null |grep Application |cut -d: -f2-)
+echo "--- The ISO on medium '${USBPART}' is '${VERSION}'"
+
+# Create a mount point for the ISO:
+ISOMNT=$(mktemp -d -p /var/tmp -t alieniso.XXXXXX)
+if [ ! -d $ISOMNT ]; then
+ echo "*** Failed to create temporary mount point for the ISO!"
+ cleanup
+ exit 1
+else
+ chmod 711 $ISOMNT
+ mount -o loop ${SLISO} ${ISOMNT}
+fi
+
+# Collect data from the USB initrd:
+IMGDIR=$(extract_initrd ${ISOMNT}/boot/initrd.img)
+read_initrd ${IMGDIR}
+
+# Collect customization parameters for the ISO:
+read_config ${SLISO}
+
+# Determine where in LUKSVOL the /home is defined.
+# The LUKSVOL value looks like:
+# "/path/to/cntner1.icc:/mountpoint1,[/path/to/cntner2.icc:/mountpoint2,[...]]"
+# Break down the LUKSVOL value into container/mountpoint combo's:
+if [ -n "$LUKSVOL" ]; then
+ _container=""
+ _mount=""
+ for _luksvol in $(echo $LUKSVOL |tr ',' ' '); do
+ _container="$(echo $_luksvol |cut -d: -f1)"
+ _mount="$(echo $_luksvol |cut -d: -f2)"
+ if [ "$_mount" == "$_container" ]; then
+ # No optional mount point specified, so we use the default:
+ CONTAINERS["${DEFMNT}"]="$_container"
+ else
+ CONTAINERS["$_mount"]="$_container"
+ fi
+ done
+fi
+
+# Normalize paths on USB partition (remove mountpoint):
+if [ -n "${PERSISTENCE}" ]; then
+ PERSISTENCE="${PERSISTENCE#$USBMNT}"
+fi
+if [ -n "${LUKSCNT}" ]; then
+ LUKSCNT="${LUKSCNT#$USBMNT}"
+fi
+if [ -n "${EXTENSION}" ]; then
+ EXTENSION="${EXTENSION#$USBMNT}"
+fi
+
+# Should we create a liveslak root directory?
+if [ -n "${LIVESLAKROOT}" ]; then
+ # The directory may already exist, in which case we obtained its name
+ # from the configfile. But creating directory tree is harmless:
+ mkdir -p ${LIVESLAKROOT}/${LIVEMAIN}/{addons,optional,core2ram}
+ # Normalize the path, removing the mount point:
+ LIVESLAKROOT="$(cd "$(dirname "$LIVESLAKROOT")"; pwd)$(basename "$LIVESLAKROOT")"
+ LIVESLAKROOT="${LIVESLAKROOT#$USBMNT}"
+fi
+
+# Should we create a persistence container?
+if [ -n "${PERSISTENCE}" ]; then
+ # Create LUKS persistence container file (or re-use it if existing):
+ create_container ${USBPART} ${PERSSIZE} ${USBMNT}${PERSISTENCE} luks persistence
+ ISOPERSISTENCE="${PERSISTENCE}"
+fi
+
+# Should we add a LUKS container to mount at /home or specified other mount?
+if [ -n "${LUKSCNT}" ]; then
+ if [ -v 'CONTAINERS["${LUKSMNT}"]' ] && [ "${LUKSCNT}" != "${CONTAINERS["${LUKSMNT}"]}" ]; then
+ # The configfile specifies a different mount for container:
+ echo "*** On-disk configuration defines an existing mountpoint ${LUKSMNT}"
+ echo "*** at '${USBMNT}${CONTAINERS["${LUKSMNT}"]}',"
+ echo "*** which is different from your '-l ${USBMNT}${LUKSCNT}'."
+ if [ $FORCE -eq 0 ]; then
+ echo "*** Not adding encrypted container for ${LUKSMNT} , please fix the entry"
+ echo "*** in '${SLISO%.iso}.cfg',"
+ echo "*** or supply the correct value for the '-l' parameter!"
+ cleanup
+ exit 1
+ else
+ echo "--- Accepting new mountpoint '${LUKSMNT}' for encrypted container ${LUKSMNT}"
+ fi
+ fi
+ # Create LUKS container file for the mount point (or re-use it if existing):
+ create_container ${USBPART} ${LUKSSIZE} ${USBMNT}${LUKSCNT} luks ${LUKSMNT}
+ CONTAINERS["${LUKSMNT}"]="${LUKSCNT}"
+fi
+
+# Should we extend the size of a container?
+if [ -n "${EXTENSION}" ]; then
+ # Expand existing container file:
+ expand_container ${USBPART} ${INCSIZE} ${USBMNT}/${EXTENSION}
+fi
+
+if [ ${#CONTAINERS[@]} -gt 0 ]; then
+ # CONTAINERS array is non-empty; (re-)assemble the LUKSVOL variable.
+ # First zap the LUKSVOL value:
+ LUKSVOL=""
+ # Write the CONTAINERS array back into LUKSVOL in the correct format:
+ for _mount in "${!CONTAINERS[@]}"; do
+ LUKSVOL="${LUKSVOL}${CONTAINERS[$_mount]}:${_mount},"
+ done
+ # Remove the trailing ',':
+ LUKSVOL="${LUKSVOL::-1}"
+fi
+
+# Write customization parameters for the ISO to disk:
+write_config ${SLISO}
+
+# Write ISO version to the liveslak rootdir if that exists:
+if [ -d "${USBMNT}/${LIVESLAKROOT}" ]; then
+ echo "$VERSION" > ${USBMNT}/${LIVESLAKROOT}/.isoversion
+fi
+
+# Unmount/remove stuff:
+cleanup
+
+# THE END
+