Merging casper 1.216.
[live-boot-grml.git] / scripts / live
index d399d87..26a6a46 100755 (executable)
@@ -20,6 +20,7 @@ USERFULLNAME="Live user"
 HOSTNAME="host"
 
 mkdir -p "${mountpoint}"
+tried="/tmp/tried"
 
 # Create /etc/mtab for debug purpose and future syncs
 if [ ! -d /etc ]
@@ -45,10 +46,40 @@ fi
 Arguments ()
 {
        PRESEEDS=""
+       LOCATIONS=""
 
        for ARGUMENT in $(cat /proc/cmdline)
        do
                case "${ARGUMENT}" in
+                       skipconfig)
+                               NOACCESSIBILITY="Yes"
+                               NOAPPARMOR="Yes"
+                               NOAPTCDROM="Yes"
+                               NOAUTOLOGIN="Yes"
+                               NOCONSOLEKEYBOARD="Yes"
+                               NOFASTBOOT="Yes"
+                               NOFSTAB="Yes"
+                               NOGNOMEPANEL="Yes"
+                               NOHOSTS="Yes"
+                               NOJOCKEY="Yes"
+                               NOKPERSONALIZER="Yes"
+                               NOLANGUAGESELECTOR="Yes"
+                               NOLOCALES="Yes"
+                               NONETWORKING="Yes"
+                               NOPOLKITCONF="Yes"
+                               NOPOWERMANAGEMENT="Yes"
+                               NOPROGRAMCRASHES="Yes"
+                               NOSUDO="Yes"
+                               NOTIMEZONE="Yes"
+                               NOUPDATENOTIFIER="Yes"
+                               NOUSER="Yes"
+                               NOXAUTOCONFIG="Yes"
+                               NOXAUTOLOGIN="Yes"
+                               NOXSCREENSAVER="Yes"
+
+                               export NOACCESSIBILITY NOAPPARMOR NOAPTCDROM NOAUTOLOGIN NOCONSOLEKEYBOARD NOFASTBOOT NOFSTAB NOGNOMEPANEL NOHOSTS NOJOCKEY NOKPERSONALIZER NOLANGUAGESELECTOR NOLOCALES NONETWORKING NOPOLKITCONF NOPOWERMANAGEMENT NOPROGRAMCRASHES NOSUDO NOTIMEZONE NOUPDATENOTIFIER NOUSER NOXAUTOCONFIG NOXAUTOLOGIN NOXSCREENSAVER
+                               ;;
+
                        access=*)
                                ACCESS="${ARGUMENT#access=}"
                                export ACCESS
@@ -66,11 +97,31 @@ Arguments ()
                                set -x
                                ;;
 
+                       ethdevice=*)
+                               DEVICE="${ARGUMENT#ethdevice=}"
+                               export DEVICE
+                               ;;
+
+                       ethdevice=*)
+                               ETHDEVICE="${ARGUMENT#ethdevice=}"
+                               export ETHDEVICE
+                               ;;
+
+                       ethdevice-timeout=*)
+                               ETHDEV_TIMEOUT="${ARGUMENT#ethdevice-timeout=}"
+                               export ETHDEV_TIMEOUT
+                               ;;
+
                        fetch=*)
                                 FETCH="${ARGUMENT#fetch=}"
                                 export FETCH
                                 ;;
 
+                       forcepersistentfsck)
+                               FORCEPERSISTENTFSCK="Yes"
+                               export FORCEPERSISTENTFSCK
+                               ;;
+
                        hook=*)
                                HOOK="${ARGUMENT#hook=}"
                                export HOOK
@@ -92,6 +143,11 @@ Arguments ()
                                export HOSTNAME LIVECONF
                                ;;
 
+                       isofrom=*|fromiso=*)
+                               FROMISO="${ARGUMENT#*=}"
+                               export FROMISO
+                               ;;
+
                        username=*)
                                USERNAME="${ARGUMENT#username=}"
                                LIVECONF="changed"
@@ -109,6 +165,11 @@ Arguments ()
                                export IGNORE_UUID
                                ;;
 
+                       integrity-check)
+                               INTEGRITY_CHECK="Yes"
+                               export INTEGRITY_CHECK
+                               ;;
+
                        ip=*)
                                STATICIP="${ARGUMENT#ip=}"
 
@@ -335,14 +396,31 @@ Arguments ()
                                export PERSISTENT
                                ;;
 
+                       persistent-path=*)
+                               PERSISTENT_PATH="${ARGUMENT#persistent-path=}"
+                               export PERSISTENT_PATH
+                               ;;
+
+                       persistent-subtext=*)
+                               root_persistence="${root_persistence}-${ARGUMENT#persistent-subtext=}"
+                               home_persistence="${home_persistence}-${ARGUMENT#persistent-subtext=}"
+                               root_snapshot_label="${root_snapshot_label}-${ARGUMENT#persistent-subtext=}"
+                               home_snapshot_label="${home_snapshot_label}-${ARGUMENT#persistent-subtext=}"
+                               ;;
+
                        nopersistent)
                                NOPERSISTENT="Yes"
                                export NOPERSISTENT
                                ;;
 
+                       quickusbmodules)
+                               QUICKUSBMODULES="Yes"
+                               export QUICKUSBMODULES
+                               ;;
+
                        preseed/file=*|file=*)
-                               LOCATION="${ARGUMENT#*=}"
-                               export LOCATION
+                               LOCATIONS="${ARGUMENT#*=} ${LOCATIONS}"
+                               export LOCATIONS
                                ;;
 
                        nopreseed)
@@ -351,22 +429,22 @@ Arguments ()
                                ;;
 
                        url=*)
-                               location="${ARGUMENT#url=}"
+                               URL_LOCATION="${ARGUMENT#url=}"
 
                                mount -o bind /sys /root/sys
                                mount -o bind /proc /root/proc
                                mount -o bind /dev /root/dev
 
                                mkdir -p /root/var/run/network
-                               chroot /root dhclient eth0
-                               chroot /root wget -P /tmp "${location}"
-                               chroot /root ifconfig eth0 down
+                               [ "${NETBOOT}" ] || chroot /root dhclient eth0
+                               chroot /root wget -P /tmp "${URL_LOCATION}"
+                               [ "${NETBOOT}" ] || chroot /root ifconfig eth0 down
 
                                umount /root/sys
                                umount /root/proc
                                umount /root/dev
 
-                               LOCATION="/tmp/$(basename "${location}")"
+                               LOCATIONS="/tmp/$(basename ${URL_LOCATION}) ${LOCATIONS}"
                                ;;
 
                        */*=*)
@@ -381,6 +459,11 @@ Arguments ()
                                export SHOWMOUNTS
                                ;;
 
+                       silent)
+                               SILENT="Yes"
+                               export SILENT
+                               ;;
+
                        textonly)
                                TEXTONLY="Yes"
                                export TEXTONLY
@@ -422,6 +505,11 @@ Arguments ()
                                export PLAIN_ROOT
                                ;;
 
+                       skipunion)
+                                SKIP_UNION_MOUNTS="Yes"
+                                export SKIP_UNION_MOUNTS
+                                ;;
+
                        root=*)
                                ROOT="${ARGUMENT#root=}"
                                export ROOT
@@ -487,7 +575,7 @@ is_live_path ()
 
        if [ -d "${DIRECTORY}"/"${LIVE_MEDIA_PATH}" ]
        then
-               for FILESYSTEM in squashfs ext2 ext3 xfs dir jffs2
+               for FILESYSTEM in squashfs ext2 ext3 ext4 xfs dir jffs2
                do
                        if [ "$(echo ${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM})" != "${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM}" ]
                        then
@@ -527,7 +615,7 @@ matches_uuid ()
 get_backing_device ()
 {
        case "${1}" in
-               *.squashfs|*.ext2|*.ext3|*.jffs2)
+               *.squashfs|*.ext2|*.ext3|*.ext4|*.jffs2)
                        echo $(setup_loop "${1}" "loop" "/sys/block/loop*" '0' "${LIVE_MEDIA_ENCRYPTION}" "${2}")
                        ;;
 
@@ -564,13 +652,14 @@ mount_images_in_directory ()
        if match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.squashfs" ||
                match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext2" ||
                match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext3" ||
+               match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext4" ||
                match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.jffs2" ||
                match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.dir"
        then
                [ -n "${mac}" ] && adddirectory="${directory}/${LIVE_MEDIA_PATH}/${mac}"
                setup_unionfs "${directory}/${LIVE_MEDIA_PATH}" "${rootmnt}" "${adddirectory}"
        else
-               log_warning_msg "Error: no filesystem images found at /${LIVE_MEDIA_PATH}."
+               panic "No supported filesystem images found at /${LIVE_MEDIA_PATH}."
        fi
 }
 
@@ -578,12 +667,15 @@ is_nice_device ()
 {
        sysfs_path="${1#/sys}"
 
-       if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-[^-]*-(ide|scsi|usb))"
+       if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-|platform-orion-ehci|platform-mmc|platform-mxsdhci|)"
        then
                return 0
        elif echo "${sysfs_path}" | grep -q '^/block/vd[a-z]$'
        then
                return 0
+       elif echo ${sysfs_path} | grep -q "^/block/dm-"
+       then
+               return 0
        fi
 
        return 1
@@ -597,7 +689,7 @@ copy_live_to ()
 
        if [ -z "${MODULETORAM}" ]
        then
-               size=$(fs_size "" ${copyfrom} "used")
+               size=$(fs_size "" ${copyfrom}/${LIVE_MEDIA_PATH} "used")
        else
                MODULETORAMFILE="${copyfrom}/${LIVE_MEDIA_PATH}/${MODULETORAM}"
 
@@ -640,7 +732,7 @@ copy_live_to ()
 
        # begin copying (or uncompressing)
        mkdir "${copyto}"
-       echo "mount -t ${fstype} ${mount_options} ${dev} ${copyto}"
+       log_begin_msg "mount -t ${fstype} ${mount_options} ${dev} ${copyto}"
        mount -t "${fstype}" ${mount_options} "${dev}" "${copyto}"
 
        if [ "${extension}" = "tgz" ]
@@ -653,12 +745,24 @@ copy_live_to ()
        else
                if [ -n "${MODULETORAMFILE}" ]
                then
-                       cp ${MODULETORAMFILE} ${copyto} # copy only the filesystem module
+                       if [ -x /bin/rsync ]
+                       then
+                               echo " * Copying $MODULETORAMFILE to RAM" 1>/dev/console
+                               rsync -a --progress ${MODULETORAMFILE} ${copyto} 1>/dev/console # copy only the filesystem module
+                       else
+                               cp ${MODULETORAMFILE} ${copyto} # copy only the filesystem module
+                       fi
                else
-                       cp -a ${copyfrom}/* ${copyto}   # "cp -a" from busybox also copies hidden files
+                       if [ -x /bin/rsync ]
+                       then
+                               echo " * Copying whole medium to RAM" 1>/dev/console
+                               rsync -a --progress ${copyfrom}/* ${copyto} 1>/dev/console  # "cp -a" from busybox also copies hidden files
+                       else
+                               mkdir -p ${copyto}/${LIVE_MEDIA_PATH}
+                               cp -a ${copyfrom}/${LIVE_MEDIA_PATH}/* ${copyto}/${LIVE_MEDIA_PATH}   # "cp -a" from busybox also copies hidden files
+                       fi
                fi
 
-               livefs_root
                umount ${copyfrom}
                mount -r -o move ${copyto} ${copyfrom}
        fi
@@ -673,18 +777,59 @@ do_netmount ()
 
        modprobe -q af_packet # For DHCP
 
-       if [ -x /sbin/udevadm ]
+       udevadm trigger
+       udevadm settle
+
+       if [ -z "${NETBOOT}" ] && [ -z "${FETCH}" ] && \
+          [ -z "${HTTPFS}" ] && [ -z "${FTPFS}" ]
        then
-               # lenny
-               udevadm trigger
-               udevadm settle
-       else
-               # etch
-               udevtrigger
-               udevsettle
+
+       # if ethdevice was not specified on the kernel command line
+       # make sure we try to get a working network configuration
+       # for *every* present network device (except for loopback of course)
+       if [ -z "$ETHDEVICE" ] ; then
+               echo "If you want to boot from a specific device use bootoption ethdevice=..."
+               for device in /sys/class/net/*; do
+                       dev=${device##*/} ;
+                       if [ "$dev" != "lo" ] ; then
+                               ETHDEVICE="$ETHDEVICE $dev"
+                       fi
+               done
        fi
 
+       # split args of ethdevice=eth0,eth1 into "eth0 eth1"
+       for device in $(echo $ETHDEVICE | sed 's/,/ /g') ; do
+               devlist="$devlist $device"
+       done
+
+       [ -n "$ETHDEV_TIMEOUT" ] || ETHDEV_TIMEOUT=15
+       echo "Using timeout of $ETHDEV_TIMEOUT seconds for network configuration."
+
+       # this is tricky (and ugly) because ipconfig sometimes just hangs/runs into
+       # an endless loop; iff execution fails give it two further tries, that's
+       # why we use '$devlist $devlist $devlist' for the other for loop
+       for dev in $devlist $devlist $devlist ; do
+               echo "Executing ipconfig -t $ETHDEV_TIMEOUT $dev"
+               ipconfig -t "$ETHDEV_TIMEOUT" $dev | tee -a /netboot.config &
+               jobid=$!
+               sleep "$ETHDEV_TIMEOUT" ; sleep 1
+               if [ -r /proc/"$jobid"/status ] ; then
+                       echo "Killing job $jobid for device $dev as ipconfig ran into recursion..."
+                       kill -9 $jobid
+               fi
+
+               # if configuration of device worked we should have an assigned
+               # IP address, iff so let's use the according as $DEVICE for later usage
+               # simple and primitive approach which seems to work fine
+               if ifconfig $dev | grep -q 'inet.*addr:' ; then
+                       export DEVICE="$dev"
+                       break
+               fi
+       done
+
+       else
        ipconfig ${DEVICE} | tee /netboot.config
+       fi
 
        # source relevant ipconfig output
        OLDHOSTNAME=${HOSTNAME}
@@ -692,6 +837,16 @@ do_netmount ()
        [ -z ${HOSTNAME} ] && HOSTNAME=${OLDHOSTNAME}
        export HOSTNAME
 
+       # Check if we have a network device at all
+       if ! ls /sys/class/net/"$DEVICE" > /dev/null 2>&1 && \
+          ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \
+          ! ls /sys/class/net/wlan0 > /dev/null 2>&1 && \
+          ! ls /sys/class/net/ath0 > /dev/null 2>&1 && \
+          ! ls /sys/class/net/ra0 > /dev/null 2>&1
+       then
+               panic "No supported network device found, maybe a non-mainline driver is required."
+       fi
+
        if [ "${NFSROOT}" = "auto" ]
        then
                NFSROOT=${ROOTSERVER}:${ROOTPATH}
@@ -744,9 +899,11 @@ do_httpmount ()
                                        then
                                                case "$url" in
                                                        tftp*)
-                                                               ip="$(dirname $url | sed -e 's|tftp://||g')"
-                                                               log_begin_msg "Trying tftp -g -b 10240 -r $(basename ${url})  -l ${dest}/$(basename ${url}) $ip"
-                                                               tftp -g -b 10240 -r $(basename ${url})  -l ${dest}/$(basename ${url}) $ip
+                                                               ip="$(dirname $url | sed -e 's|tftp://||g' -e 's|/.*$||g')"
+                                                               rfile="$(echo $url | sed -e "s|tftp://$ip||g")"
+                                                               lfile="$(basename $url)"
+                                                               log_begin_msg "Trying tftp -g -b 10240 -r $rfile -l ${dest}/$lfile $ip"
+                                                               tftp -g -b 10240 -r $rfile -l ${dest}/$lfile $ip
                                                        ;;
 
                                                        *)
@@ -896,7 +1053,7 @@ find_snap ()
        if [ "${PERSISTENT}" != "nofiles" ]
        then
                # search for image files
-               snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.ext2 ${snap_label}.ext3 ${snap_label}.jffs2")
+               snapdata=$(find_files "${PERSISTENT_PATH}${snap_label}.squashfs ${PERSISTENT_PATH}${snap_label}.cpio.gz ${PERSISTENT_PATH}${snap_label}.ext2 ${PERSISTENT_PATH}${snap_label}.ext3 ${PERSISTENT_PATH}${snap_label}.ext4 ${PERSISTENT_PATH}${snap_label}.jffs2")
        fi
 
        if [ -z "${snapdata}" ]
@@ -915,7 +1072,7 @@ try_snap ()
        snap_mount="${2}"
        snap_type="${3}"
 
-       if [ ! -z "${snapdata}" ]
+       if [ -n "${snapdata}" ] && [ ! -b "${snapdata}" ]
        then
                log_success_msg "found snapshot: ${snapdata}"
                snapdev="$(echo ${snapdata} | cut -f1 -d ' ')"
@@ -928,23 +1085,32 @@ try_snap ()
                        break
                fi
 
-               if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|jffs2\)'
+               if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\|ext3\|ext4\|jffs2\)'
                then
-                       # squashfs, jffs2 or ext2/ext3 snapshot
+                       # squashfs, jffs2 or ext2/ext3/ext4 snapshot
                        dev=$(get_backing_device "${snapback}/${snapfile}")
 
                        do_snap_copy "${dev}" "${snap_mount}" "${snap_type}"
                        RES=$?
                else
                        # cpio.gz snapshot
-                       cd "${snap_mount}"
-                       zcat "${snapback}/${snapfile}" | /bin/cpio --extract --preserve-modification-time --no-absolute-filenames --sparse --unconditional --make-directories > /dev/null 2>&1
-                       RES=$?
-                       if [ "${RES}" != "0" ]
+
+                       # Unfortunately klibc's cpio is incompatible with the
+                       # rest of the world; everything else requires -u -d,
+                       # while klibc doesn't implement them. Try to detect
+                       # whether it's in use.
+                       cpiopath="$(which cpio)" || true
+                       if [ "$cpiopath" ] && grep -aq /lib/klibc "$cpiopath"
+                       then
+                               cpioargs=
+                       else
+                               cpioargs='--unconditional --make-directories'
+                       fi
+
+                       if ! (cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | cpio $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse 2>/dev/null)
                        then
-                               log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | /bin/cpio --extract --preserve-modification-time --no-absolute-filenames --sparse --unconditional --make-directories\""
+                               log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | cpio $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\""
                        fi
-                       cd "${OLDPWD}"
                fi
 
                umount "${snapback}" ||  log_warning_msg "failure to \"umount ${snapback}\""
@@ -954,12 +1120,11 @@ try_snap ()
                        log_warning_msg "Impossible to include the ${snapfile} Snapshot file"
                fi
 
-
        elif [ -b "${snapdata}" ]
        then
                # Try to find if it could be a snapshot partition
                dev="${snapdata}"
-               log_success_msg "found snapshot device on ${dev}"
+               log_success_msg "found snapshot ${snap_type} device on ${dev}"
                if echo "${dev}" | grep -qs loop
                then
                        # strange things happens, user confused?
@@ -986,7 +1151,7 @@ try_snap ()
                return 1
        fi
 
-       echo "export ${snap_type}SNAP="${snap_mount}":${snapdev}:${snapfile}" >> /etc/live.conf # for resync on reboot/halt
+       echo "export ${snap_type}SNAP="/cow${snap_mount#$rootmnt}":${snapdev}:${snapfile}" >> /etc/live.conf # for resync on reboot/halt
        return 0
 }
 
@@ -995,7 +1160,25 @@ setup_unionfs ()
        image_directory="${1}"
        rootmnt="${2}"
         addimage_directory="${3}"
-       modprobe -q -b ${UNIONTYPE}
+
+       case ${UNIONTYPE} in
+               aufs|unionfs)
+                       modprobe -q -b ${UNIONTYPE}
+
+                       if ! cut -f2 /proc/filesystems | grep -q "^${UNIONTYPE}\$" && [ -x /bin/unionfs-fuse ]
+                       then
+                               echo "${UNIONTYPE} not available, falling back to unionfs-fuse."
+                               echo "This might be really slow."
+
+                               UNIONTYPE="unionfs-fuse"
+                       fi
+                       ;;
+       esac
+
+       if [ "${UNIONTYPE}" = unionfs-fuse ]
+       then
+               modprobe fuse
+       fi
 
        # run-init can't deal with images in a subdir, but we're going to
        # move all of these away before it runs anyway.  No, we're not,
@@ -1007,50 +1190,38 @@ setup_unionfs ()
        # Let's just mount the read-only file systems first
        rofsstring=""
        rofslist=""
-       minor_kernel_version=$(uname -r|cut -c 5-|sed 's/[^0-9].*//')
 
-       if [ "${NETBOOT}" = "nfs" ] && [ "${minor_kernel_version}" -lt 22 ]
-       then
-               # go aroung a bug in nfs-unionfs locking for unionfs <= 1.4
-               roopt="nfsro"
-       elif [ "${UNIONTYPE}" = "aufs" ]
+       if [ "${UNIONTYPE}" = "aufs" ]
        then
                roopt="rr"
+               noxino_opt="noxino,"
+       elif [ "${UNIONTYPE}" = "unionfs-fuse" ]
+       then
+               roopt="RO"
        else
                roopt="ro"
        fi
 
-       # Read image names from ${MODULE}.module if it exists
-       if [ -e "${image_directory}/filesystem.${MODULE}.module" ]
-       then
-               for IMAGE in $(cat ${image_directory}/filesystem.${MODULE}.module)
-               do
-                       image_string="${image_string} ${image_directory}/${IMAGE}"
-               done
-       elif [ -e "${image_directory}/${MODULE}.module" ]
+       if [ -z "${PLAIN_ROOT}" ]
        then
-               for IMAGE in $(cat ${image_directory}/${MODULE}.module)
-               do
-                       image_string="${image_string} ${image_directory}/${IMAGE}"
-               done
-       else
-               # ${MODULE}.module does not exist, create a list of images
-               for FILESYSTEM in squashfs ext2 ext3 xfs jffs2 dir
-               do
-                       for IMAGE in "${image_directory}"/*."${FILESYSTEM}"
+               # Read image names from ${MODULE}.module if it exists
+               if [ -e "${image_directory}/filesystem.${MODULE}.module" ]
+               then
+                       for IMAGE in $(cat ${image_directory}/filesystem.${MODULE}.module)
                        do
-                               if [ -e "${IMAGE}" ]
-                               then
-                                       image_string="${image_string} ${IMAGE}"
-                               fi
+                               image_string="${image_string} ${image_directory}/${IMAGE}"
                        done
-               done
-
-               if [ -n "${addimage_directory}" ] && [ -d "${addimage_directory}" ]
+               elif [ -e "${image_directory}/${MODULE}.module" ]
                then
-                       for FILESYSTEM in squashfs ext2 ext3 xfs jffs2 dir
+                       for IMAGE in $(cat ${image_directory}/${MODULE}.module)
                        do
-                               for IMAGE in "${addimage_directory}"/*."${FILESYSTEM}"
+                               image_string="${image_string} ${image_directory}/${IMAGE}"
+                       done
+               else
+                       # ${MODULE}.module does not exist, create a list of images
+                       for FILESYSTEM in squashfs ext2 ext3 ext4 xfs jffs2 dir
+                       do
+                               for IMAGE in "${image_directory}"/*."${FILESYSTEM}"
                                do
                                        if [ -e "${IMAGE}" ]
                                        then
@@ -1058,52 +1229,80 @@ setup_unionfs ()
                                        fi
                                done
                        done
-               fi
 
-               # Now sort the list
-               image_string="$(echo ${image_string} | sed -e 's/ /\n/g' | sort )"
-       fi
+                       if [ -n "${addimage_directory}" ] && [ -d "${addimage_directory}" ]
+                       then
+                               for FILESYSTEM in squashfs ext2 ext3 ext4 xfs jffs2 dir
+                               do
+                                       for IMAGE in "${addimage_directory}"/*."${FILESYSTEM}"
+                                       do
+                                               if [ -e "${IMAGE}" ]
+                                               then
+                                                       image_string="${image_string} ${IMAGE}"
+                                               fi
+                                       done
+                               done
+                       fi
+
+                       # Now sort the list
+                       image_string="$(echo ${image_string} | sed -e 's/ /\n/g' | sort )"
+               fi
 
        [ -n "${MODULETORAMFILE}" ] && image_string="${image_directory}/$(basename ${MODULETORAMFILE})"
 
-       mkdir -p "${croot}"
+               mkdir -p "${croot}"
 
-       for image in ${image_string}
-       do
-               imagename=$(basename "${image}")
+               for image in ${image_string}
+               do
+                       imagename=$(basename "${image}")
 
-               if [ -d "${image}" ]
-               then
-                       # it is a plain directory: do nothing
-                       rofsstring="${image}=${roopt}:${rofsstring}"
-                       rofslist="${image} ${rofslist}"
-               elif [ -f "${image}" ]
-               then
-                       if losetup --help 2>&1 | grep -q -- "-r\b"
-                       then
-                               backdev=$(get_backing_device "${image}" "-r")
-                       else
-                               backdev=$(get_backing_device "${image}")
-                       fi
-                       fstype=$(get_fstype "${backdev}")
+                       export image devname
+                       maybe_break live-realpremount
+                       log_begin_msg "Running /scripts/live-realpremount"
+                       run_scripts /scripts/live-realpremount
+                       log_end_msg
 
-                       if [ "${fstype}" = "unknown" ]
+                       if [ -d "${image}" ]
                        then
-                               panic "Unknown file system type on ${backdev} (${image})"
-                       fi
-
-                       if [ -z "${fstype}" ]
+                               # it is a plain directory: do nothing
+                               rofsstring="${image}=${roopt}:${rofsstring}"
+                               rofslist="${image} ${rofslist}"
+                       elif [ -f "${image}" ]
                        then
-                               fstype="${imagename##*.}"
-                               log_warning_msg "Unknown file system type on ${backdev} (${image}), assuming ${fstype}."
-                       fi
+                               if losetup --help 2>&1 | grep -q -- "-r\b"
+                               then
+                                       backdev=$(get_backing_device "${image}" "-r")
+                               else
+                                       backdev=$(get_backing_device "${image}")
+                               fi
+                               fstype=$(get_fstype "${backdev}")
 
-                       mkdir -p "${croot}/${imagename}"
-                       log_begin_msg "Mounting \"${image}\" on \"${croot}${imagename}\" via \"${backdev}\""
-                       mount -t "${fstype}" -o ro,noatime "${backdev}" "${croot}/${imagename}" || panic "Can not mount ${backdev} (${image}) on ${croot}/${imagename}" && rofsstring="${croot}/${imagename}=${roopt}:${rofsstring}" && rofslist="${croot}/${imagename} ${rofslist}"
-                       log_end_msg
-               fi
-       done
+                               if [ "${fstype}" = "unknown" ]
+                               then
+                                       panic "Unknown file system type on ${backdev} (${image})"
+                               fi
+
+                               if [ -z "${fstype}" ]
+                               then
+                                       fstype="${imagename##*.}"
+                                       log_warning_msg "Unknown file system type on ${backdev} (${image}), assuming ${fstype}."
+                               fi
+
+                               mkdir -p "${croot}/${imagename}"
+                               log_begin_msg "Mounting \"${image}\" on \"${croot}${imagename}\" via \"${backdev}\""
+                               mount -t "${fstype}" -o ro,noatime "${backdev}" "${croot}/${imagename}" || panic "Can not mount ${backdev} (${image}) on ${croot}/${imagename}" && rofsstring="${croot}/${imagename}=${roopt}:${rofsstring}" && rofslist="${croot}/${imagename} ${rofslist}"
+                               log_end_msg
+                       fi
+               done
+       else
+               # we have a plain root system
+               mkdir -p "${croot}/filesystem"
+               log_begin_msg "Mounting \"${image_directory}\" on \"${croot}/filesystem\""
+               mount -t $(get_fstype "${image_directory}") -o ro,noatime "${image_directory}" "${croot}/filesystem" || panic "Can not mount ${image_directory} on ${croot}/filesystem" && rofsstring="${croot}/filesystem=${roopt}:${rofsstring}" && rofslist="${croot}/filesystem ${rofslist}"
+               # probably broken:
+               mount -o bind ${croot}/filesystem $mountpoint
+               log_end_msg
+       fi
 
        rofsstring=${rofsstring%:}
 
@@ -1112,37 +1311,32 @@ setup_unionfs ()
        # Looking for "${root_persistence}" device or file
        if [ -n "${PERSISTENT}" ] && [ -z "${NOPERSISTENT}" ]
        then
-               # Load USB modules
-               num_block=$(ls -l /sys/block | wc -l)
-               for module in sd_mod uhci-hcd ehci-hcd ohci-hcd usb-storage
-               do
-                       modprobe -q -b ${module}
-               done
-
-               if [ -x /sbin/udevadm ]
+               if [ -z "${QUICKUSBMODULES}" ]
                then
-                       # lenny
+                       # Load USB modules
+                       num_block=$(ls -l /sys/block | wc -l)
+                       for module in sd_mod uhci-hcd ehci-hcd ohci-hcd usb-storage
+                       do
+                               modprobe -q -b ${module}
+                       done
+
                        udevadm trigger
                        udevadm settle
-               else
-                       # etch
-                       udevtrigger
-                       udevsettle
-               fi
 
-               # For some reason, udevsettle does not block in this scenario,
-               # so we sleep for a little while.
-               #
-               # See https://bugs.launchpad.net/ubuntu/+source/casper/+bug/84591
-               for timeout in 5 4 3 2 1
-               do
-                       sleep 1
+                       # For some reason, udevsettle does not block in this scenario,
+                       # so we sleep for a little while.
+                       #
+                       # See https://bugs.launchpad.net/ubuntu/+source/casper/+bug/84591
+                       for timeout in 5 4 3 2 1
+                       do
+                               sleep 1
 
-                       if [ $(ls -l /sys/block | wc -l) -gt ${num_block} ]
-                       then
-                               break
-                       fi
-               done
+                               if [ $(ls -l /sys/block | wc -l) -gt ${num_block} ]
+                               then
+                                       break
+                               fi
+                       done
+               fi
 
                # search for label and files (this could be hugely optimized)
                cowprobe=$(find_cow_device "${root_persistence}")
@@ -1166,7 +1360,7 @@ setup_unionfs ()
                root_snapdata=$(find_snap "${root_snapshot_label}" "${blacklistdev}")
                # This second type should be removed when snapshot will get smarter,
                # hence when "/etc/live-snapshot*list" will be supported also by
-               # ext2|ext3|jffs2 snapshot types.
+               # ext2|ext3|ext4|jffs2 snapshot types.
                home_snapdata=$(find_snap "${home_snapshot_label}" "${blacklistdev}")
 
                if [ -b "${cowprobe}" ]
@@ -1174,6 +1368,11 @@ setup_unionfs ()
                        cowdevice=${cowprobe}
                        cow_fstype=$(get_fstype "${cowprobe}")
                        cow_mountopt="rw,noatime"
+
+                       if [ "${FORCEPERSISTENTFSCK}" = "Yes" ]
+                       then
+                               fsck -y ${cowdevice}
+                       fi
                else
                        log_warning_msg "Unable to find the persistent medium"
                        cowdevice="tmpfs"
@@ -1229,23 +1428,45 @@ setup_unionfs ()
                mount --bind ${exposedrootfs} ${rootmnt} || \
                        panic "bind mount of ${exposedrootfs} failed"
 
-               cow_dirs='/var/tmp /var/lock /var/run /var/log /var/spool
-                       /home /var/lib/live'
+               if [ -z "${SKIP_UNION_MOUNTS}" ]
+               then
+                       cow_dirs='/var/tmp /var/lock /var/run /var/log /var/spool /home /var/lib/live'
+               else
+                       cow_dirs=''
+               fi
 
                for dir in ${cow_dirs}; do
                        mkdir -p /cow${dir}
-                       mount -t ${UNIONTYPE} \
-                               -o rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro \
-                               ${UNIONTYPE} "${rootmnt}${dir}" || \
-                               panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option \
-                                       rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro"
+
+                       case "${UNIONTYPE}" in
+                               unionfs-fuse)
+                                       (ulimit -n 16384; unionfs-fuse -o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid /cow=RW:${exposedrootfs}${dir} "${rootmnt}${dir}" || panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option cow,noinitgroups,default_permissions,allow_other,use_ino,suid=/cow=RW:${exposedrootfs}${dir}")
+                                       mkdir -p /dev/.initramfs/varrun
+                                       pidof unionfs-fuse >> /dev/.initramfs/varrun/sendsigs.omit || true
+                                       ;;
+
+                               *)
+                                       mount -t ${UNIONTYPE} -o rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro ${UNIONTYPE} "${rootmnt}${dir}" || panic "mount ${UNIONTYPE} on ${rootmnt}${dir} failed with option rw,noatime,dirs=/cow${dir}=rw:${exposedrootfs}${dir}=ro"
+                                       ;;
+                       esac
                done
        else
-               mount -t ${UNIONTYPE} -o noatime,dirs=/cow=rw:${rofsstring} \
-                       ${UNIONTYPE} "${rootmnt}" || panic "mount ${UNIONTYPE} on \
-                       ${rootmnt} failed with option noatime,dirs=/cow=rw:${rofsstring}"
+               case "${UNIONTYPE}" in
+                       unionfs-fuse)
+                               (ulimit -n 16384; unionfs-fuse -o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid /cow=RW:${rofsstring} "${rootmnt}" || panic "mount ${UNIONTYPE} on ${rootmnt} failed with option cow,noinitgroups,default_permissions,allow_other,use_ino,suid=/cow:RW:${rofsstring}")
+                               mkdir -p /dev/.initramfs/varrun
+                               pidof unionfs-fuse >> /dev/.initramfs/varrun/sendsigs.omit || true
+                               ;;
+
+                       *)
+                               mount -t ${UNIONTYPE} -o noatime,${noxino_opt}dirs=/cow=rw:${rofsstring} ${UNIONTYPE} "${rootmnt}" || panic "mount ${UNIONTYPE} on ${rootmnt} failed with option noatime,${noxino_opt}dirs=/cow=rw:${rofsstring}"
+                               ;;
+               esac
        fi
 
+       # Correct the permissions of /:
+       chmod 0755 "${rootmnt}"
+
        # tmpfs file systems
        touch /etc/fstab
        mkdir -p "${rootmnt}/live"
@@ -1283,7 +1504,15 @@ setup_unionfs ()
                                        ;;
 
                                *)
-                                       mount -o move "${d}" "${rootmnt}/live/${d##*/}"
+                                       case "${UNIONTYPE}" in
+                                               unionfs-fuse)
+                                                       mount -o bind "${d}" "${rootmnt}/live/${d##*/}"
+                                                       ;;
+
+                                               *)
+                                                       mount -o move "${d}" "${rootmnt}/live/${d##*/}"
+                                                       ;;
+                                       esac
                                        ;;
                        esac
                done
@@ -1300,6 +1529,36 @@ check_dev ()
        devname="${2}"
        skip_uuid_check="${3}"
 
+       # support for fromiso=.../isofrom=....
+       if [ -n "$FROMISO" ]
+       then
+               ISO_DEVICE=$(dirname $FROMISO)
+               if ! [ -b $ISO_DEVICE ]
+               then
+                       # to support unusual device names like /dev/cciss/c0d0p1
+                       # as well we have to identify the block device name, let's
+                       # do that for up to 15 levels
+                       i=15
+                       while [ -n "$ISO_DEVICE" ] && [ "$i" -gt 0 ]
+                       do
+                               ISO_DEVICE=$(dirname ${ISO_DEVICE})
+                               [ -b "$ISO_DEVICE" ] && break
+                               i=$(($i -1))
+                       done
+               fi
+
+               if [ "$ISO_DEVICE" = "/" ]
+               then
+                       echo "Warning: device for bootoption isofrom= ($FROMISO) not found.">>/live.log
+               else
+                       mkdir /isofrom
+                       mount "$ISO_DEVICE" /isofrom
+                       ISO_NAME="$(echo $FROMISO | sed "s|$ISO_DEVICE||")"
+                       loopdevname=$(setup_loop "/isofrom/${ISO_NAME}" "loop" "/sys/block/loop*" "" '')
+                       devname="${loopdevname}"
+               fi
+       fi
+
        if [ -z "${devname}" ]
        then
                devname=$(sys2dev "${sysdev}")
@@ -1317,6 +1576,7 @@ check_dev ()
                        umount $mountpoint
                fi
        fi
+       [ -e "$devname" ] || continue
 
        if [ -n "${LIVE_MEDIA_OFFSET}" ]
        then
@@ -1328,7 +1588,10 @@ check_dev ()
 
        if is_supported_fs ${fstype}
        then
+               devuid=$(blkid -o value -s UUID "$devname")
+               [ -n "$devuid" ] && grep -qs "\<$devuid\>" $tried && continue
                mount -t ${fstype} -o ro,noatime "${devname}" ${mountpoint} || continue
+               [ -n "$devuid" ] && echo "$devuid" >> $tried
 
                if is_live_path ${mountpoint} && \
                        ([ "${skip_uuid_check}" ] || matches_uuid ${mountpoint})
@@ -1352,15 +1615,6 @@ find_livefs ()
 {
        timeout="${1}"
 
-       # first look at the one specified in the command line
-       if [ ! -z "${LIVE_MEDIA}" ]
-       then
-               if check_dev "null" "${LIVE_MEDIA}" "skip_uuid_check"
-               then
-                       return 0
-               fi
-       fi
-
        # don't start autodetection before timeout has expired
        if [ -n "${LIVE_MEDIA_TIMEOUT}" ]
        then
@@ -1370,10 +1624,74 @@ find_livefs ()
                fi
        fi
 
+       # first look at the one specified in the command line
+       case "${LIVE_MEDIA}" in
+               removable-usb)
+                       for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)")
+                       do
+                               if [ "$(cat ${sysblock}/removable)" = "1" ]
+                               then
+                                       if readlink ${sysblock} | grep -q usb ||
+                                          readlink ${sysblock}/device | grep -q usb # linux < 2.6.29
+                                       then
+                                               for dev in $(subdevices "${sysblock}")
+                                               do
+                                                       if check_dev "${dev}"
+                                                       then
+                                                               return 0
+                                                       fi
+                                               done
+                                       fi
+                               fi
+                       done
+                       return 1
+                       ;;
+
+               removable)
+                       for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)")
+                       do
+                               if [ "$(cat ${sysblock}/removable)" = "1" ]
+                               then
+                                       for dev in $(subdevices "${sysblock}")
+                                       do
+                                               if check_dev "${dev}"
+                                               then
+                                                       return 0
+                                               fi
+                                       done
+                               fi
+                       done
+                       return 1
+                       ;;
+
+               *)
+                       if [ ! -z "${LIVE_MEDIA}" ]
+                       then
+                               if check_dev "null" "${LIVE_MEDIA}" "skip_uuid_check"
+                               then
+                                       return 0
+                               fi
+                       fi
+                       ;;
+       esac
+
        # or do the scan of block devices
+       # prefer removable devices over non-removable devices, so scan them first
        for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)")
        do
+               if [ "$(cat ${sysblock}/removable)" = "1" ]
+               then
+                       removable_devices_to_scan="$removable_devices_to_scan $sysblock"
+               else
+                       nonremovable_devices_to_scan="$nonremovable_devices_to_scan $sysblock"
+               fi
+       done
+       devices_to_scan="$removable_devices_to_scan $nonremovable_devices_to_scan"
+
+       for sysblock in $devices_to_scan
+       do
                devname=$(sys2dev "${sysblock}")
+               [ -e "$devname" ] || continue
                fstype=$(get_fstype "${devname}")
 
                if /lib/udev/cdrom_id ${devname} > /dev/null
@@ -1394,6 +1712,7 @@ find_livefs ()
                elif [ "${fstype}" = "squashfs" -o \
                        "${fstype}" = "ext2" -o \
                        "${fstype}" = "ext3" -o \
+                       "${fstype}" = "ext4" -o \
                        "${fstype}" = "jffs2" ]
                then
                        # This is an ugly hack situation, the block device has
@@ -1418,6 +1737,40 @@ set_usplash_timeout ()
        fi ; fi
 }
 
+integrity_check ()
+{
+       media_mountpoint="${1}"
+
+       log_begin_msg "Checking media integrity"
+
+       cd ${media_mountpoint}
+       /bin/md5sum -c md5sum.txt < /dev/tty8 > /dev/tty8
+       RC="${?}"
+
+       log_end_msg
+
+       if [ "${RC}" -eq 0 ]
+       then
+               log_success_msg "Everything ok, will reboot in 10 seconds."
+               sleep 10
+               cd /
+               umount ${media_mountpoint}
+               sync
+               echo u > /proc/sysrq-trigger
+               echo b > /proc/sysrq-trigger
+       else
+               panic "Not ok, a media defect is likely, switch to VT8 for details."
+       fi
+}
+
+start_usplash_pulse ()
+{
+       if [ -x /sbin/usplash_write ]
+       then
+               /sbin/usplash_write "PULSELOGO"
+       fi
+}
+
 mountroot ()
 {
         if [ -x /scripts/local-top/cryptroot ]; then
@@ -1437,6 +1790,7 @@ mountroot ()
        Arguments
 
        set_usplash_timeout
+       start_usplash_pulse
 
        maybe_break live-premount
        log_begin_msg "Running /scripts/live-premount"
@@ -1484,6 +1838,11 @@ mountroot ()
                panic "Unable to find a medium containing a live file system"
        fi
 
+       if [ "${INTEGRITY_CHECK}" ]
+       then
+               integrity_check "${livefs_root}"
+       fi
+
        if [ "${TORAM}" ]
        then
                live_dest="ram"
@@ -1499,7 +1858,16 @@ mountroot ()
                log_end_msg
        fi
 
-       if [ -n "${MODULETORAMFILE}" ]
+       # if we do not unmount the ISO we can't run "fsck /dev/ice" later on
+       # because the mountpoint is left behind in /proc/mounts, so let's get
+       # rid of it when running from RAM
+       if [ -n "$FROMISO" ] && [ "${TORAM}" ]
+       then
+         losetup -d /dev/loop0
+         grep -q /isofrom /proc/mounts && umount /isofrom
+       fi
+
+       if [ -n "${MODULETORAMFILE}" ] || [ -n "${PLAIN_ROOT}" ]
        then
                setup_unionfs "${livefs_root}" "${rootmnt}"
        else
@@ -1510,14 +1878,59 @@ mountroot ()
 
        log_end_msg
 
+       # unionfs-fuse needs /dev to be bind-mounted for the duration of
+       # live-bottom; udev's init script will take care of things after that
+       if [ "${UNIONTYPE}" = unionfs-fuse ]
+       then
+               mount -n -o bind /dev "${rootmnt}/dev"
+       fi
+
+       # Open up two fifo's fd's for debconf-communicate to use. Speeds up
+       # the live-initramfs process considerably.
+       log_begin_msg "Creating debconf-communicate fifo mechanism"
+       mkfifo /tmp/debconf-in.fifo
+       mkfifo /tmp/debconf-out.fifo
+
+       chroot /root debconf-communicate -fnoninteractive live-initramfs > /tmp/debconf-out.fifo < /tmp/debconf-in.fifo &
+
+       # Save the PID so it can be killed later.
+       DEBCONF_COMMUNICATE_PID="$!"
+
+       if [ ! -p /tmp/debconf-in.fifo ] || [ ! -p /tmp/debconf-out.fifo ]
+       then
+               log_warning_msg "failed to setup debconf-communicate channel"
+       fi
+       log_end_msg
+
+       # Order matters!
+       # These file descriptors must stay open until we're finished with
+       # debconf-communicate.
+       exec 4</tmp/debconf-out.fifo 3>/tmp/debconf-in.fifo
+
        maybe_break live-bottom
-       log_begin_msg "Running /scripts/live-bottom"
+       log_begin_msg "Running /scripts/live-bottom\n"
 
        run_scripts /scripts/live-bottom
        log_end_msg
 
+       if [ "${UNIONFS}" = unionfs-fuse ]
+       then
+               umount "${rootmnt}/dev"
+       fi
+
+       # Kill the debconf-communicate instance and close fd's associated with·
+       # debconf-communicate.
+       kill $DEBCONF_COMMUNICATE_PID
+       exec 3>&- 4<&-
+       rm -f /tmp/debconf-in.fifo
+       rm -f /tmp/debconf-out.fifo
+
        exec 1>&6 6>&-
        exec 2>&7 7>&-
        kill ${tailpid}
-       cp live.log "${rootmnt}/var/log/"
+       [ -w "${rootmnt}/var/log/" ] && cp live.log "${rootmnt}/var/log/" 2>/dev/null
+       if [ -f /etc/live.conf ]
+       then
+               cp /etc/live.conf "${rootmnt}/etc/"
+       fi
 }