X-Git-Url: http://git.grml.org/?a=blobdiff_plain;f=scripts%2Flive;h=26a6a4689be68b7555c326080bdc84fd3764b312;hb=c967ebfc4e43fb16a0c2c140c66900712be95ab7;hp=96ab63a044df0261739a8080648a0d3ee21003c2;hpb=85e2939c446d0ead490be57d0a0edac9f6a3f772;p=live-boot-grml.git diff --git a/scripts/live b/scripts/live index 96ab63a..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,6 +46,7 @@ fi Arguments () { PRESEEDS="" + LOCATIONS="" for ARGUMENT in $(cat /proc/cmdline) do @@ -100,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 @@ -407,8 +419,8 @@ Arguments () ;; preseed/file=*|file=*) - LOCATION="${ARGUMENT#*=}" - export LOCATION + LOCATIONS="${ARGUMENT#*=} ${LOCATIONS}" + export LOCATIONS ;; nopreseed) @@ -417,7 +429,7 @@ Arguments () ;; url=*) - location="${ARGUMENT#url=}" + URL_LOCATION="${ARGUMENT#url=}" mount -o bind /sys /root/sys mount -o bind /proc /root/proc @@ -425,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}" ;; */*=*) @@ -655,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 @@ -765,7 +780,56 @@ do_netmount () udevadm trigger udevadm settle + if [ -z "${NETBOOT}" ] && [ -z "${FETCH}" ] && \ + [ -z "${HTTPFS}" ] && [ -z "${FTPFS}" ] + then + + # 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} @@ -774,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 @@ -1029,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 + 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}\"" @@ -1077,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 } @@ -1086,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, @@ -1101,7 +1193,11 @@ setup_unionfs () if [ "${UNIONTYPE}" = "aufs" ] then - roopt="rr,noxino" + roopt="rr" + noxino_opt="noxino," + elif [ "${UNIONTYPE}" = "unionfs-fuse" ] + then + roopt="RO" else roopt="ro" fi @@ -1341,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 /: @@ -1393,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 @@ -1413,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}" ] @@ -1438,6 +1576,7 @@ check_dev () umount $mountpoint fi fi + [ -e "$devname" ] || continue if [ -n "${LIVE_MEDIA_OFFSET}" ] then @@ -1449,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}) @@ -1534,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 @@ -1608,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 @@ -1627,6 +1790,7 @@ mountroot () Arguments set_usplash_timeout + start_usplash_pulse maybe_break live-premount log_begin_msg "Running /scripts/live-premount" @@ -1714,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 }