diff options
Diffstat (limited to 'iso2usb.sh')
-rw-r--r-- | iso2usb.sh | 142 |
1 files changed, 107 insertions, 35 deletions
@@ -26,9 +26,14 @@ set -e # Set to '1' if you want to ignore all warnings: FORCE=0 +# By default, we use 'slhome.img' as the name of the LUKS home containerfile. +DEF_SLHOME="slhome" +SLHOME="${DEF_SLHOME}" + # By default, we use 'persistence' as the name of the persistence directory, # or 'persistence.img' as the name of the persistence container: -PERSISTENCE="persistence" +DEF_PERSISTENCE="persistence" +PERSISTENCE="${DEF_PERSISTENCE}" # Default persistence type is a directory: PERSISTTYPE="dir" @@ -40,6 +45,7 @@ UNATTENDED=0 VERBOSE=0 # Variables to store content from an initrd we are going to refresh: +OLDPERSISTENCE="" OLDWAIT="" OLDLUKS="" @@ -52,10 +58,14 @@ DOLUKS=0 # We are NOT refreshing existing Live content by default: REFRESH=0 +# These tools are required by the script, we will check for their existence: +REQTOOLS="blkid cpio extlinux fdisk gdisk isoinfo mkdosfs sgdisk" + # Initialize more variables: CNTBASE="" CNTDEV="" CNTFILE="" +HLUKSSIZE="" LUKSHOME="" LODEV="" @@ -64,6 +74,7 @@ IMGDIR="" ISOMNT="" CNTMNT="" USBMNT="" +US2MNT="" # Compressor used on the initrd ("gzip" or "xz --check=crc32"); # Note that the kernel's XZ decompressor does not understand CRC64: @@ -84,13 +95,14 @@ cleanup() { # In case of failure, only the most recent device should still be open: if mount |grep -q ${CNTDEV} ; then umount -f ${CNTDEV} - cryptsetup luksClose ${CNTBASE} + cryptsetup luksClose $(basename ${CNTBASE}) losetup -d ${LODEV} fi fi [ -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 ) + [ -n "${US2MNT}" ] && ( /sbin/umount -f ${US2MNT} 2>/dev/null; rmdir $US2MNT ) [ -n "${IMGDIR}" ] && ( rm -rf $IMGDIR ) set -e } @@ -114,8 +126,11 @@ cat <<EOT # -f|--force Ignore most warnings (except the back-out). # -h|--help This help. # -i|--infile <filename> Full path to the ISO image file. +# -l|--lukshome <name> Custom path to the containerfile for your LUKS +# encrypted /home ($SLHOME by default). # -o|--outdev <filename> The device name of your USB drive. -# -p|--persistence <dirname> Custom name of the 'persistence' directory. +# -p|--persistence <name> Custom path to the 'persistence' directory +# or containerfile ($PERSISTENCE by default). # -r|--refresh Refresh the USB stick with the ISO content. # No formatting, do not touch user content. # -u|--unattended Do not ask any questions. @@ -148,6 +163,7 @@ uncompressfs () { read_initrd() { IMGFILE="$1" + OLDPERSISTENCE=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout init |grep "^PERSISTENCE" |cut -d '"' -f2 2>/dev/null) OLDWAIT=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout wait-for-root 2>/dev/null) OLDLUKS=$(uncompressfs ${IMGFILE} |cpio -i --to-stdout luksdev 2>/dev/null) } @@ -181,11 +197,30 @@ update_initrd() { if [ $REFRESH -eq 1 ]; then echo "--- Refreshing Slackware initrd..." WAIT="$OLDWAIT" + if [ -n "$OLDLUKS" ]; then + echo "--- Detected LUKS container configuration:" + echo "$OLDLUKS" | sed 's/^/ /' + fi echo "$OLDLUKS" >> luksdev + if [ "${PERSISTENCE}" != "${DEF_PERSISTENCE}" ]; then + # If the user specified a nonstandard persistence, use that: + echo "--- Updating persistence from '$OLDPERSISTENCE' to '$PERSISTENCE'" + sed -i -e "s,^PERSISTENCE=.*,PERSISTENCE=\"${PERSISTENCE}\"," init + elif [ "${PERSISTENCE}" != "${OLDPERSISTENCE}" ]; then + # The user did not specify persistence, re-use the retrieved value: + sed -i -e "s,^PERSISTENCE=.*,PERSISTENCE=\"${OLDPERSISTENCE}\"," init + echo "--- Re-use previous '$OLDPERSISTENCE' for persistence" + PERSISTENCE="${OLDPERSISTENCE}" + fi else - echo "--- Updating 'waitforroot' time from '$OLDWAIT' to '$WAIT':" + if [ "${PERSISTENCE}" != "${DEF_PERSISTENCE}" ]; then + # If the user specified a nonstandard persistence, use that: + echo "--- Updating persistence from '$DEF_PERSISTENCE' to '$PERSISTENCE'" + sed -i -e "s,^PERSISTENCE=.*,PERSISTENCE=\"${PERSISTENCE}\"," init + fi fi + echo "--- Updating 'waitforroot' time from '$OLDWAIT' to '$WAIT'" echo ${WAIT} > wait-for-root if [ $DOLUKS -eq 1 -a -n "${LUKSHOME}" ]; then @@ -198,7 +233,7 @@ update_initrd() { echo "--- Compressing the initrd image again:" chmod 0755 ${IMGDIR} find . |cpio -o -H newc |$COMPR > ${IMGFILE} - cd - 2>/dev/null + cd - 1>/dev/null rm -rf $IMGDIR/* } # End of update_initrd() @@ -213,7 +248,7 @@ create_container() { # Create a container file or re-use previously created one: if [ -f $USBMNT/${CNTBASE}.img ]; then CNTFILE="${CNTBASE}.img" - CNTSIZE=$(( $(du -sk ${CNTFILE}) / 1024 )) + CNTSIZE=$(( $(du -sk $USBMNT/${CNTFILE} |tr '\t' ' ' |cut -f1 -d' ') / 1024 )) echo "--- Keeping existing '${CNTFILE}' (size ${CNTSIZE} MB)." return fi @@ -225,8 +260,8 @@ create_container() { PARTFREE=${PARTFREE%M} if [ $PARTFREE -lt 10 ]; then - echo "** Free space on USB partition is less than 10 MB;" - echo "** Not creating a container file!" + echo "*** Free space on USB partition is less than 10 MB;" + echo "*** Not creating a container file!" exit 1 fi @@ -243,16 +278,17 @@ create_container() { esac if [ $CNTSIZE -le 0 ]; then - echo "** Container size must be larger than ZERO!" - echo "** Check your '-c' commandline parameter." + echo "*** Container size must be larger than ZERO!" + echo "*** Check your '-c' commandline parameter." exit 1 elif [ $CNTSIZE -ge $PARTFREE ]; then - echo "** Not enough free space for container file!" - echo "** Check your '-c' commandline parameter." + echo "*** Not enough free space for container file!" + echo "*** Check your '-c' commandline parameter." exit 1 fi echo "--- Creating ${CNTSIZE} MB container file using 'dd if=/dev/urandom', patience please..." + mkdir -p $USBMNT/$(dirname "${CNTBASE}") CNTFILE="${CNTBASE}.img" # Create a sparse file (not allocating any space yet): dd of=$USBMNT/${CNTFILE} bs=1M count=0 seek=$CNTSIZE @@ -263,11 +299,17 @@ create_container() { if [ "${CNTENCR}" = "luks" ]; then # Format the loop device with LUKS: echo "--- Encrypting the container file with LUKS; enter 'YES' and a passphrase..." - cryptsetup -y luksFormat $LODEV + 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..." - cryptsetup luksOpen $LODEV ${CNTBASE} - CNTDEV=/dev/mapper/${CNTBASE} + until cryptsetup luksOpen $LODEV $(basename ${CNTBASE}) ; 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 ${CNTBASE}) # 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: @@ -305,7 +347,7 @@ create_container() { # Don't forget to clean up after ourselves: if [ "${CNTENCR}" = "luks" ]; then - cryptsetup luksClose ${CNTBASE} + cryptsetup luksClose $(basename ${CNTBASE}) fi losetup -d ${LODEV} || true @@ -325,6 +367,8 @@ while [ ! -z "$1" ]; do -c|--crypt) HLUKSSIZE="$2" DOLUKS=1 + # Needs unsquashfs to extract the /home + REQTOOLS="${REQTOOLS} unsquashfs" shift 2 ;; -f|--force) @@ -339,6 +383,10 @@ while [ ! -z "$1" ]; do SLISO="$(cd $(dirname $2); pwd)/$(basename $2)" shift 2 ;; + -l|--lukshome) + SLHOME="$2" + shift 2 + ;; -o|--outdev) TARGET="$2" shift 2 @@ -408,7 +456,7 @@ fi # Are all the required not-so-common add-on tools present? PROG_MISSING="" -for PROGN in blkid cpio extlinux fdisk gdisk isoinfo mkdosfs sgdisk unsquashfs ; do +for PROGN in ${REQTOOLS} ; do if ! PATH="/sbin:$PATH" which $PROGN 1>/dev/null 2>/dev/null ; then PROG_MISSING="${PROG_MISSING}-- $PROGN\n" fi @@ -508,7 +556,7 @@ if [ ! -d $ISOMNT ]; then else chmod 711 $ISOMNT fi -# USB mount: +# USB mounts: USBMNT=$(mktemp -d -p /mnt -t alienusb.XXXXXX) if [ ! -d $USBMNT ]; then echo "*** Failed to create a temporary mount point for the USB device!" @@ -517,6 +565,14 @@ if [ ! -d $USBMNT ]; then else chmod 711 $USBMNT fi +US2MNT=$(mktemp -d -p /mnt -t alienus2.XXXXXX) +if [ ! -d $US2MNT ]; then + echo "*** Failed to create a temporary mount point for the USB device!" + cleanup + exit 1 +else + chmod 711 $US2MNT +fi # Mount the Linux partition: /sbin/mount -t auto ${TARGET}3 ${USBMNT} @@ -561,7 +617,9 @@ if [ $REFRESH -eq 1 ]; then 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 + if [ -f ${USBMNT}/boot/extlinux/ldlinux.sys ]; then + chattr -i ${USBMNT}/boot/extlinux/ldlinux.sys 2>/dev/null + fi rsync -rlptD --delete \ ${ISOMNT}/boot/ ${USBMNT}/boot/ fi @@ -572,20 +630,35 @@ if [ -n "$VERSION" ]; then echo "$VERSION" > ${USBMNT}/.isoversion fi -if [ $DOLUKS -eq 1 ]; then - # Create LUKS container file: - create_container ${TARGET}3 ${HLUKSSIZE} slhome luks /home +if [ -n "${HLUKSSIZE}" ]; then + # Create LUKS container file for /home: + create_container ${TARGET}3 ${HLUKSSIZE} ${SLHOME} luks /home LUKSHOME=${CNTFILE} fi -# Update the initrd with longer USB wait time and LUKS /home info: +# Update the initrd with regard to USB wait time, persistence and LUKS. +# If this is a refresh and anything changed to persistence, then the +# variable $PERSISTENCE will have the correct value when exing this function: +# If you want to move your LUKS home containerfile you'll have to do that +# manually - not a supported option for now. 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 [ "${PERSISTENCE}" != "${OLDPERSISTENCE}" ]; then + # The user specified a nonstandard persistence, so move the old one first; + # hide any errors if it did not *yet* exist: + mkdir -p ${USBMNT}/$(dirname ${PERSISTENCE}) + mv ${USBMNT}/${OLDPERSISTENCE}.img ${USBMNT}/${PERSISTENCE}.img 2>/dev/null + mv ${USBMNT}/${OLDPERSISTENCE} ${USBMNT}/${PERSISTENCE} 2>/dev/null + fi if [ -f ${USBMNT}/${PERSISTENCE}.img ]; then # If a persistence container exists, we re-use it: PERSISTTYPE="file" + if cryptsetup isLuks ${USBMNT}/${PERSISTENCE}.img ; then + # If the persistence file is LUKS encrypted we need to record its size: + PLUKSSIZE=$(( $(du -sk $USBMNT/${PERSISTENCE}.img |tr '\t' ' ' |cut -f1 -d' ') / 1024 )) + fi 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 @@ -623,35 +696,34 @@ mv ${USBMNT}/boot/extlinux/isolinux.cfg ${USBMNT}/boot/extlinux/extlinux.conf rm -f ${USBMNT}/boot/extlinux/isolinux.* /sbin/extlinux --install ${USBMNT}/boot/extlinux -# No longer needed: -if /sbin/mount |grep -qw ${USBMNT} ; then /sbin/umount ${USBMNT} ; fi - if [ $EFIBOOT -eq 1 ]; then # Mount the EFI partition and copy /EFI as well as /boot directories into it: - /sbin/mount -t vfat -o shortname=mixed ${TARGET}2 ${USBMNT} - mkdir -p ${USBMNT}/EFI/BOOT - rsync -rlptD ${ISOMNT}/EFI/BOOT/* ${USBMNT}/EFI/BOOT/ + /sbin/mount -t vfat -o shortname=mixed ${TARGET}2 ${US2MNT} + mkdir -p ${US2MNT}/EFI/BOOT + rsync -rlptD ${ISOMNT}/EFI/BOOT/* ${US2MNT}/EFI/BOOT/ mkdir -p ${USBMNT}/boot echo "--- Copying EFI boot files from ISO to USB." if [ $VERBOSE -eq 1 ]; then - rsync -rlptD -v ${ISOMNT}/boot/* ${USBMNT}/boot/ + rsync -rlptD -v ${ISOMNT}/boot/* ${US2MNT}/boot/ else - rsync -rlptD ${ISOMNT}/boot/* ${USBMNT}/boot/ + rsync -rlptD ${ISOMNT}/boot/* ${US2MNT}/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/ + ${ISOMNT}/EFI/BOOT/ ${US2MNT}/EFI/BOOT/ rsync -rlptD --delete \ - ${ISOMNT}/boot/ ${USBMNT}/boot/ + ${ISOMNT}/boot/ ${US2MNT}/boot/ fi - # Update the initrd with longer USB wait time and LUKS container info: - update_initrd ${USBMNT}/boot/initrd.img + # Copy the modified initrd over from the Linux partition: + cat ${USBMNT}/boot/initrd.img > ${US2MNT}/boot/initrd.img + sync fi # No longer needed: if /sbin/mount |grep -qw ${USBMNT} ; then /sbin/umount ${USBMNT} ; fi +if /sbin/mount |grep -qw ${US2MNT} ; then /sbin/umount ${US2MNT} ; fi # Unmount/remove stuff: cleanup |