summaryrefslogtreecommitdiffstats
path: root/iso2usb.sh
diff options
context:
space:
mode:
Diffstat (limited to 'iso2usb.sh')
-rw-r--r--iso2usb.sh267
1 files changed, 171 insertions, 96 deletions
diff --git a/iso2usb.sh b/iso2usb.sh
index e23e670..4228c56 100644
--- a/iso2usb.sh
+++ b/iso2usb.sh
@@ -39,13 +39,21 @@ UNATTENDED=0
# By default do not show file operations in detail:
VERBOSE=0
+# Variables to store content from an initrd we are going to refresh:
+OLDWAIT=""
+OLDLUKS=""
+
# Seconds to add to the initrd as wait-for-root value:
WAIT=5
# No LUKS encryption by default:
DOLUKS=0
+# We are NOT refreshing existing Live content by default:
+REFRESH=0
+
# Initialize more variables:
+CNTBASE=""
CNTDEV=""
CNTFILE=""
LUKSHOME=""
@@ -53,7 +61,6 @@ LODEV=""
# Define ahead of time, so that cleanup knows about them:
IMGDIR=""
-EFIMNT=""
ISOMNT=""
CNTMNT=""
USBMNT=""
@@ -73,7 +80,7 @@ cleanup() {
# During cleanup, do not abort due to non-zero exit code:
set +e
sync
- if [ $DOLUKS -eq 1 ]; then
+ if [ $DOLUKS -eq 1 -a -n "$CNTDEV" ]; then
# In case of failure, only the most recent device should still be open:
if mount |grep -q ${CNTDEV} ; then
umount -f ${CNTDEV}
@@ -81,7 +88,6 @@ cleanup() {
losetup -d ${LODEV}
fi
fi
- [ -n "${EFIMNT}" ] && ( /sbin/umount -f ${EFIMNT} 2>/dev/null; rmdir $EFIMNT )
[ -n "${ISOMNT}" ] && ( /sbin/umount -f ${ISOMNT} 2>/dev/null; rmdir $ISOMNT )
[ -n "${CNTMNT}" ] && ( /sbin/umount -f ${CNTMNT} 2>/dev/null; rmdir $CNTMNT )
[ -n "${USBMNT}" ] && ( /sbin/umount -f ${USBMNT} 2>/dev/null; rmdir $USBMNT )
@@ -110,6 +116,8 @@ cat <<EOT
# -i|--infile <filename> Full path to the ISO image file.
# -o|--outdev <filename> The device name of your USB drive.
# -p|--persistence <dirname> Custom name of the 'persistence' directory.
+# -r|--refresh Refresh the USB stick with the ISO content.
+# No formatting, do not touch user content.
# -u|--unattended Do not ask any questions.
# -v|--verbose Show verbose messages.
# -w|--wait<number> Add <number> seconds wait time to initialize USB.
@@ -136,14 +144,21 @@ uncompressfs () {
fi
}
+# Read configuration data from old initrd:
+read_initrd() {
+ IMGFILE="$1"
+
+ OLDWAIT=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout wait-for-root 2>/dev/null)
+ OLDLUKS=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout luksdev 2>/dev/null)
+}
+
# Add longer USB WAIT to the initrd:
update_initrd() {
IMGFILE="$1"
# USB boot medium needs a few seconds boot delay else the overlay will fail.
# Check if we need to update the wait-for-root file in the initrd:
- OLDWAIT=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout wait-for-root 2>/dev/null)
- if [ "$OLDWAIT" = "$WAIT" -a $DOLUKS -eq 0 ]; then
+ if [ "$OLDWAIT" = "$WAIT" -a $DOLUKS -eq 0 -a $REFRESH -eq 0 ]; then
return
fi
@@ -162,7 +177,15 @@ update_initrd() {
cd ${IMGDIR}
uncompressfs ${IMGFILE} \
| cpio -i -d -H newc --no-absolute-filenames
- echo "--- Updating 'waitforroot' time from '$OLDWAIT' to '$WAIT':"
+
+ if [ $REFRESH -eq 1 ]; then
+ echo "--- Refreshing Slackware initrd..."
+ WAIT="$OLDWAIT"
+ echo "$OLDLUKS" >> luksdev
+ else
+ echo "--- Updating 'waitforroot' time from '$OLDWAIT' to '$WAIT':"
+ fi
+
echo ${WAIT} > wait-for-root
if [ $DOLUKS -eq 1 -a -n "${LUKSHOME}" ]; then
@@ -187,6 +210,14 @@ create_container() {
CNTENCR=$4 # 'none' or 'luks'
CNTUSED=$5 # '/home' or 'persistence'
+ # Create a container file or re-use previously created one:
+ if [ -f $USBMNT/${CNTBASE}.img ]; then
+ CNTFILE="${CNTBASE}.img"
+ CNTSIZE=$(( $(du -sk ${CNTFILE}) / 1024 ))
+ echo "--- Keeping existing '${CNTFILE}' (size ${CNTSIZE} MB)."
+ return
+ fi
+
# Determine size of the target partition (in MB), and the free space:
PARTSIZE=$(df -P -BM ${CNTPART} |tail -1 |tr -s '\t' ' ' |cut -d' ' -f2)
PARTSIZE=${PARTSIZE%M}
@@ -221,23 +252,10 @@ create_container() {
exit 1
fi
- # Create an empty container file (re-use previously created one):
- if [ -f $USBMNT/${CNTBASE}.img ]; then
- CNTFILE="${CNTBASE}.img"
- CNTSIZE=$(( $(du -sk ${CNTFILE}) / 1024 ))
- if [ $UNATTENDED -eq 0 ]; then
- echo "*** File '${CNTFILE}' already exists (size ${CNTSIZE} MB). ***"
- echo "*** If you do not want to re-use it for '$CNTUSED', ***"
- echo "*** then press CONTROL-C now and rename that file! ***"
- read -p "Else press ENTER to continue: " JUNK
- # OK... the user was sure about the file...
- fi
- else
- echo "--- Creating ${CNTSIZE} MB container file using 'dd if=/dev/urandom', patience please..."
- CNTFILE="${CNTBASE}.img"
- # Create a sparse file (not allocating any space yet):
- dd of=$USBMNT/${CNTFILE} bs=1M count=0 seek=$CNTSIZE
- fi
+ echo "--- Creating ${CNTSIZE} MB container file using 'dd if=/dev/urandom', patience please..."
+ CNTFILE="${CNTBASE}.img"
+ # Create a sparse file (not allocating any space yet):
+ dd of=$USBMNT/${CNTFILE} bs=1M count=0 seek=$CNTSIZE
# Setup a loopback device that we can use with cryptsetup:
LODEV=$(losetup -f)
@@ -329,6 +347,10 @@ while [ ! -z "$1" ]; do
PERSISTENCE="$2"
shift 2
;;
+ -r|--refresh)
+ REFRESH=1
+ shift
+ ;;
-u|--unattended)
UNATTENDED=1
shift
@@ -371,7 +393,7 @@ if [ -z "$TARGET" -o -z "$SLISO" ]; then
exit 1
fi
-if [ ! -f $SLISO -a $FORCE -eq 0 ]; then
+if [ $FORCE -eq 0 -a ! -f $SLISO ]; then
echo "*** This is not a useable file: '$SLISO' !"
exit 1
fi
@@ -398,70 +420,86 @@ if [ ! -z "$PROG_MISSING" ] ; then
exit 1
fi
-# Confirm wipe:
-cat <<EOT
+if [ $REFRESH -eq 0 ]; then
+ # We are creating a USB stick from scratch,
+ # i.e. not refreshing the Live content.
+ # Confirm wipe:
+ cat <<EOT
#
# We are going to format this device (erase all data) - '$TARGET':
+EOT
+else
+ # We are refreshing the Live content.
+ # Confirm refresh:
+ cat <<EOT
+#
+# We are going to refresh the Live OS on this device - '$TARGET':
+EOT
+fi
+ # Continue with the common text message:
+ cat <<EOT
# Vendor : $(cat /sys/block/$(basename $TARGET)/device/vendor)
# Model : $(cat /sys/block/$(basename $TARGET)/device/model)
# Size : $(( $(cat /sys/block/$(basename $TARGET)/size) / 2048)) MB
#
# FDISK OUTPUT:
EOT
-echo q |/sbin/gdisk -l $TARGET 2>/dev/null | while read LINE ; do echo "# $LINE" ; done
-if [ $UNATTENDED -eq 0 ]; then
- cat <<EOT
+ echo q |/sbin/gdisk -l $TARGET 2>/dev/null | \
+ while read LINE ; do echo "# $LINE" ; done
+
+ if [ $UNATTENDED -eq 0 ]; then
+ cat <<EOT
*** ***
*** If this is the wrong drive, then press CONTROL-C now! ***
*** ***
EOT
- read -p "Or press ENTER to continue: " JUNK
- # OK... the user was sure about the drive...
-fi
+ read -p "Or press ENTER to continue: " JUNK
+ # OK... the user was sure about the drive...
+ fi
-# Get the LABEL used for the ISO:
-LIVELABEL=$(/sbin/blkid -s LABEL -o value ${SLISO})
-
-# Use sgdisk to wipe and then setup the USB device:
-# - 1 MB BIOS boot partition
-# - 100 MB EFI system partition
-# - Let Slackware have the rest
-# - Make the Linux partition "legacy BIOS bootable"
-# Make sure that there is no MBR nor a partition table anymore:
-dd if=/dev/zero of=$TARGET bs=512 count=1 conv=notrunc
-# The first sgdisk command is allowed to have non-zero exit code:
-/sbin/sgdisk -og $TARGET || true
-/sbin/sgdisk \
- -n 1:2048:4095 -c 1:"BIOS Boot Partition" -t 1:ef02 \
- -n 2:4096:208895 -c 2:"EFI System Partition" -t 2:ef00 \
- -n 3:208896:0 -c 3:"Slackware Linux" -t 3:8300 \
- $TARGET
-/sbin/sgdisk -A 3:set:2 $TARGET
-# Show what we did to the USB stick:
-/sbin/sgdisk -p -A 3:show $TARGET
-
-# Create filesystems:
-# Not enough clusters for a 32 bit FAT:
-/sbin/mkdosfs -s 2 -n "DOS" ${TARGET}1
-/sbin/mkdosfs -F32 -s 2 -n "EFI" ${TARGET}2
-# KDE tends to automount.. so try an umount:
-if /sbin/mount |grep -qw ${TARGET}3 ; then /sbin/umount ${TARGET}3 || true ; fi
-/sbin/mkfs.ext4 -F -F -L "${LIVELABEL}" -m 0 ${TARGET}3
-/sbin/tune2fs -c 0 -i 0 ${TARGET}3
-
-# Create temporary mount points for the ISO file:
+if [ $REFRESH -eq 0 ]; then
+ # Continue with the wipe/partitioning/formatting.
+
+ # Get the LABEL used for the ISO:
+ LIVELABEL=$(/sbin/blkid -s LABEL -o value ${SLISO})
+
+ # Use sgdisk to wipe and then setup the USB device:
+ # - 1 MB BIOS boot partition
+ # - 100 MB EFI system partition
+ # - Let Slackware have the rest
+ # - Make the Linux partition "legacy BIOS bootable"
+ # Make sure that there is no MBR nor a partition table anymore:
+ dd if=/dev/zero of=$TARGET bs=512 count=1 conv=notrunc
+ # The first sgdisk command is allowed to have non-zero exit code:
+ /sbin/sgdisk -og $TARGET || true
+ /sbin/sgdisk \
+ -n 1:2048:4095 -c 1:"BIOS Boot Partition" -t 1:ef02 \
+ -n 2:4096:208895 -c 2:"EFI System Partition" -t 2:ef00 \
+ -n 3:208896:0 -c 3:"Slackware Linux" -t 3:8300 \
+ $TARGET
+ /sbin/sgdisk -A 3:set:2 $TARGET
+ # Show what we did to the USB stick:
+ /sbin/sgdisk -p -A 3:show $TARGET
+
+ # Create filesystems:
+ # Not enough clusters for a 32 bit FAT:
+ /sbin/mkdosfs -s 2 -n "DOS" ${TARGET}1
+ /sbin/mkdosfs -F32 -s 2 -n "EFI" ${TARGET}2
+ # KDE tends to automount.. so try an umount:
+ if /sbin/mount |grep -qw ${TARGET}3 ; then
+ /sbin/umount ${TARGET}3 || true
+ fi
+ /sbin/mkfs.ext4 -F -F -L "${LIVELABEL}" -m 0 ${TARGET}3
+ /sbin/tune2fs -c 0 -i 0 ${TARGET}3
+
+fi # End [ $REFRESH -eq 0 ]
+
+# Create temporary mount points for the ISO file and USB device:
mkdir -p /mnt
-EFIMNT=$(mktemp -d -p /mnt -t alienefi.XXXXXX)
-if [ ! -d $EFIMNT ]; then
- echo "*** Failed to create a temporary mount point for the ISO!"
- cleanup
- exit 1
-else
- chmod 711 $EFIMNT
-fi
+# ISO mount:
ISOMNT=$(mktemp -d -p /mnt -t alieniso.XXXXXX)
if [ ! -d $ISOMNT ]; then
echo "*** Failed to create a temporary mount point for the ISO!"
@@ -470,23 +508,7 @@ if [ ! -d $ISOMNT ]; then
else
chmod 711 $ISOMNT
fi
-
-# Find out if the ISO contains an EFI bootloader and use it:
-EFIBOOT=0
-EFIOFFSET=$(/sbin/fdisk -lu ${SLISO} 2>/dev/null |grep EFI |tr -s ' ' | cut -d' ' -f 2)
-if [ -n "$EFIOFFSET" ]; then
- # Mount the EFI partition so we can retrieve the EFI bootloader:
- /sbin/mount -o loop,offset=$((512*$EFIOFFSET)) ${SLISO} ${EFIMNT}
- if [ ! -f ${EFIMNT}/EFI/BOOT/boot*.efi ]; then
- echo "-- Note: UEFI boot file 'bootx64.efi' or 'bootia32.efi' not found on ISO."
- echo "-- UEFI boot will not be supported"
- else
- EFIBOOT=1
- fi
-fi
-
-# Create a temporary mount point for the USB device:
-mkdir -p /mnt
+# USB mount:
USBMNT=$(mktemp -d -p /mnt -t alienusb.XXXXXX)
if [ ! -d $USBMNT ]; then
echo "*** Failed to create a temporary mount point for the USB device!"
@@ -502,18 +524,46 @@ fi
# Loop-mount the ISO (or 1st partition if this is a hybrid ISO):
/sbin/mount -o loop ${SLISO} ${ISOMNT}
+# Find out if the ISO contains an EFI bootloader and use it:
+if [ ! -f ${ISOMNT}/EFI/BOOT/boot*.efi ]; then
+ EFIBOOT=0
+ echo "-- Note: UEFI boot file 'bootx64.efi' or 'bootia32.efi' not found on ISO."
+ echo "-- UEFI boot will not be supported"
+else
+ EFIBOOT=1
+fi
+
+if [ $REFRESH -eq 0 ]; then
+ # Collect data from the ISO initrd:
+ read_initrd ${ISOMNT}/boot/initrd.img
+else
+ # Collect data from the USB initrd:
+ read_initrd ${USBMNT}/boot/initrd.img
+fi
+
# Copy the ISO content into the USB Linux partition:
echo "--- Copying files from ISO to USB... takes some time."
if [ $VERBOSE -eq 1 ]; then
# Show verbose progress:
- rsync -av --progress --exclude=EFI ${ISOMNT}/* ${USBMNT}/
+ rsync -rlptD -v --progress --exclude=EFI ${ISOMNT}/* ${USBMNT}/
elif [ -z "$(rsync --info=progress2 2>&1 |grep "unknown option")" ]; then
# Use recent rsync to display some progress because this can take _long_ :
- rsync -a --no-inc-recursive --info=progress2 --exclude=EFI \
+ rsync -rlptD --no-inc-recursive --info=progress2 --exclude=EFI \
${ISOMNT}/* ${USBMNT}/
else
# Remain silent if we have an older rsync:
- rsync -a --exclude=EFI ${ISOMNT}/* ${USBMNT}/
+ rsync -rlptD --exclude=EFI ${ISOMNT}/* ${USBMNT}/
+fi
+
+if [ $REFRESH -eq 1 ]; then
+ # Clean out old Live system data:
+ echo "--- Cleaning out old Live system data."
+ LIVEMAIN="$(echo $(find ${ISOMNT} -name "0099*") |rev |cut -d/ -f3 |rev)"
+ rsync -rlptD --delete \
+ ${ISOMNT}/${LIVEMAIN}/system/ ${USBMNT}/${LIVEMAIN}/system/
+ chattr -i ${USBMNT}/boot/extlinux/ldlinux.sys 2>/dev/null
+ rsync -rlptD --delete \
+ ${ISOMNT}/boot/ ${USBMNT}/boot/
fi
# Write down the version of the ISO image:
@@ -528,9 +578,22 @@ if [ $DOLUKS -eq 1 ]; then
LUKSHOME=${CNTFILE}
fi
-# Add more USB WAIT seconds to the initrd:
+# Update the initrd with longer USB wait time and LUKS /home info:
update_initrd ${USBMNT}/boot/initrd.img
+if [ $REFRESH -eq 1 ]; then
+ # Determine what we need to do with persistence if this is a refresh.
+ if [ -f ${USBMNT}/${PERSISTENCE}.img ]; then
+ # If a persistence container exists, we re-use it:
+ PERSISTTYPE="file"
+ elif [ -d ${USBMNT}/${PERSISTENCE} -a "${PERSISTTYPE}" = "file" ]; then
+ # A persistence directory exists but the user wants a container now;
+ # so we will delete the persistence directory and create a container file
+ # (sorry persistent data will not be migrated):
+ rm -rf ${USBMNT}/${PERSISTENCE}
+ fi
+fi
+
if [ "${PERSISTTYPE}" = "dir" ]; then
# Create persistence directory:
mkdir -p ${USBMNT}/${PERSISTENCE}
@@ -557,7 +620,7 @@ fi
echo "--- Making the USB drive '$TARGET' bootable using extlinux..."
mv ${USBMNT}/boot/syslinux ${USBMNT}/boot/extlinux
mv ${USBMNT}/boot/extlinux/isolinux.cfg ${USBMNT}/boot/extlinux/extlinux.conf
-rm ${USBMNT}/boot/extlinux/isolinux.*
+rm -f ${USBMNT}/boot/extlinux/isolinux.*
/sbin/extlinux --install ${USBMNT}/boot/extlinux
# No longer needed:
@@ -569,14 +632,26 @@ if [ $EFIBOOT -eq 1 ]; then
mkdir -p ${USBMNT}/EFI/BOOT
rsync -rlptD ${ISOMNT}/EFI/BOOT/* ${USBMNT}/EFI/BOOT/
mkdir -p ${USBMNT}/boot
- rsync -rlptD ${ISOMNT}/boot/* ${USBMNT}/boot/
- # Add more USB WAIT seconds to the initrd:
+ echo "--- Copying EFI boot files from ISO to USB."
+ if [ $VERBOSE -eq 1 ]; then
+ rsync -rlptD -v ${ISOMNT}/boot/* ${USBMNT}/boot/
+ else
+ rsync -rlptD ${ISOMNT}/boot/* ${USBMNT}/boot/
+ fi
+ if [ $REFRESH -eq 1 ]; then
+ # Clean out old Live system data:
+ echo "--- Cleaning out old Live system data."
+ rsync -rlptD --delete \
+ ${ISOMNT}/EFI/BOOT/ ${USBMNT}/EFI/BOOT/
+ rsync -rlptD --delete \
+ ${ISOMNT}/boot/ ${USBMNT}/boot/
+ fi
+ # Update the initrd with longer USB wait time and LUKS container info:
update_initrd ${USBMNT}/boot/initrd.img
fi
# No longer needed:
if /sbin/mount |grep -qw ${USBMNT} ; then /sbin/umount ${USBMNT} ; fi
-if /sbin/mount |grep -qw ${EFIMNT} ; then /sbin/umount ${EFIMNT} ; fi
# Unmount/remove stuff:
cleanup