X-Git-Url: http://git.grml.org/?a=blobdiff_plain;f=scripts%2Flive;h=26a6a4689be68b7555c326080bdc84fd3764b312;hb=c967ebfc4e43fb16a0c2c140c66900712be95ab7;hp=6af14c38c6aef2a31e40eabbd0f32ba82d765b2d;hpb=2dd7c308da963f84810583942dd39ee1c975a93e;p=live-boot-grml.git diff --git a/scripts/live b/scripts/live index 6af14c3..26a6a46 100755 --- a/scripts/live +++ b/scripts/live @@ -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 @@ -71,6 +102,16 @@ Arguments () export DEVICE ;; + ethdevice=*) + ETHDEVICE="${ARGUMENT#ethdevice=}" + export ETHDEVICE + ;; + + ethdevice-timeout=*) + ETHDEV_TIMEOUT="${ARGUMENT#ethdevice-timeout=}" + export ETHDEV_TIMEOUT + ;; + fetch=*) FETCH="${ARGUMENT#fetch=}" export FETCH @@ -372,9 +413,14 @@ Arguments () export NOPERSISTENT ;; + quickusbmodules) + QUICKUSBMODULES="Yes" + export QUICKUSBMODULES + ;; + preseed/file=*|file=*) - LOCATION="${ARGUMENT#*=}" - export LOCATION + LOCATIONS="${ARGUMENT#*=} ${LOCATIONS}" + export LOCATIONS ;; nopreseed) @@ -383,7 +429,7 @@ Arguments () ;; url=*) - location="${ARGUMENT#url=}" + URL_LOCATION="${ARGUMENT#url=}" mount -o bind /sys /root/sys mount -o bind /proc /root/proc @@ -391,14 +437,14 @@ Arguments () mkdir -p /root/var/run/network [ "${NETBOOT}" ] || chroot /root dhclient eth0 - chroot /root wget -P /tmp "${location}" + 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}" ;; */*=*) @@ -621,12 +667,15 @@ is_nice_device () { sysfs_path="${1#/sys}" - if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-|platform-mmc)" + 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 @@ -728,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} @@ -748,7 +838,8 @@ do_netmount () export HOSTNAME # Check if we have a network device at all - if ! ls /sys/class/net/eth0 > /dev/null 2>&1 && \ + 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 @@ -962,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}.ext4 ${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}" ] @@ -1003,14 +1094,23 @@ try_snap () 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 - log_warning_msg "failure to \"zcat ${snapback}/${snapfile} | /bin/cpio --extract --preserve-modification-time --no-absolute-filenames --sparse --unconditional --make-directories\"" + 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} | cpio $cpioargs --extract --preserve-modification-time --no-absolute-filenames --sparse\"" fi - cd "${OLDPWD}" fi umount "${snapback}" || log_warning_msg "failure to \"umount ${snapback}\"" @@ -1051,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 } @@ -1060,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, @@ -1072,15 +1190,14 @@ 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 @@ -1194,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}") @@ -1325,16 +1437,31 @@ setup_unionfs () 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 /: @@ -1377,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 @@ -1397,12 +1532,31 @@ check_dev () # support for fromiso=.../isofrom=.... if [ -n "$FROMISO" ] then - mkdir /isofrom - ISO_DEVICE="$(echo $FROMISO | sed 's|\(/dev/[a-z]*[0-9]*\).*|\1|')" - mount "$ISO_DEVICE" /isofrom - ISO_NAME="$(echo $FROMISO | sed 's|/dev/[a-z]*[0-9]*/||')" - loopdevname=$(setup_loop "/isofrom/${ISO_NAME}" "loop" "/sys/block/loop*" "" '') - devname="${loopdevname}" + 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}" ] @@ -1422,6 +1576,7 @@ check_dev () umount $mountpoint fi fi + [ -e "$devname" ] || continue if [ -n "${LIVE_MEDIA_OFFSET}" ] then @@ -1433,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}) @@ -1486,6 +1644,7 @@ find_livefs () fi fi done + return 1 ;; removable) @@ -1502,6 +1661,7 @@ find_livefs () done fi done + return 1 ;; *) @@ -1516,9 +1676,22 @@ find_livefs () 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 @@ -1590,6 +1763,14 @@ integrity_check () fi } +start_usplash_pulse () +{ + if [ -x /sbin/usplash_write ] + then + /sbin/usplash_write "PULSELOGO" + fi +} + mountroot () { if [ -x /scripts/local-top/cryptroot ]; then @@ -1609,6 +1790,7 @@ mountroot () Arguments set_usplash_timeout + start_usplash_pulse maybe_break live-premount log_begin_msg "Running /scripts/live-premount" @@ -1696,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-in.fifo + maybe_break 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} [ -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 }