Adding casper 1.77+debian-1.
[live-boot-grml.git] / scripts / casper
1 #!/bin/sh
2
3 # set -e
4
5 export PATH=/root/usr/bin:/root/usr/sbin:/root/bin:/root/sbin:/usr/bin:/usr/sbin:/bin:/sbin
6
7 mountpoint=/live_media
8
9 root_persistence="casper-rw"
10 home_persistence="home-rw"
11 root_snapshot="casper-sn"
12 home_snapshot="home-sn"
13
14 USERNAME="casper"
15 USERFULLNAME="Live session user"
16 HOST="live"
17 BUILD_SYSTEM="Debian"
18
19 mkdir -p $mountpoint
20
21 [ -f /etc/casper.conf ] && . /etc/casper.conf
22
23 export USERNAME USERFULLNAME HOST BUILD_SYSTEM
24
25 if [ "${BUILD_SYSTEM}" == "Ubuntu" ]; then
26     MP_QUIET="-Q"
27 else
28     MP_QUIET="-q"
29 fi
30
31 parse_cmdline ()
32 {
33     # looking for casper specifics options as kernel parameters
34     for x in $(cat /proc/cmdline); do
35         case $x in
36             userfullname=*)
37                 export USERFULLNAME=${x#userfullname=}
38                 export CASPERCONF="changed"
39                 ;;
40             host=*)
41                 export HOST=${x#host=}
42                 export CASPERCONF="changed"
43                 ;;
44             username=*)
45                 export USERNAME=${x#username=}
46                 export CASPERCONF="changed"
47                 ;;
48             netboot*)
49                 export NETBOOT=${x#netboot=} ;;
50             toram)
51                 export TORAM=1 ;;
52             todisk=)
53                 export TODISK=${x#todisk=} ;;
54             showmounts)
55                 export SHOWMOUNTS=1 ;;
56             persistent)
57                 export PERSISTENT=1 ;;
58             ip*)
59                 STATICIP=${x#ip=}
60                 if [ "${STATICIP}" == "" ]; then
61                     STATICIP="frommedia"
62                 fi
63                 export STATICIP ;;
64             casper-getty)
65                 export CASPERGETTY=1 ;;
66             console=*)
67                 export DEFCONSOLE=$(sed -e 's%.*console=%console=%' /proc/cmdline) ;;
68             bootfrom=*)
69                 export LIVEMEDIA=${x#bootfrom=} ;;
70             live-media=*)
71                 export LIVEMEDIA=${x#live-media=} ;;
72             debian-installer/locale=*)
73                 export LOCALE=${x#debian-installer/locale=} ;;
74             locale=*)
75                 export LOCALE=${x#locale=} ;;
76             kbd-chooser/method=*)
77                 export KBD=${x#kbd-chooser/method=} ;;
78             keyb=*)
79                 export KBD=${x#kbd=} ;;
80             console-setup/layoutcode=*)
81                 export CSLAYOUT=${x#console-setup/layoutcode=} ;;
82             console-setup/variantcode=*)
83                 export CSVARIANT=${x#console-setup/variantcode=} ;;
84             console-setup/modelcode=*)
85                 export CSMODEL=${x#console-setup/modelcode=} ;;
86         esac
87     done
88
89     # sort of compatibility with netboot.h from linux docs
90     if [ -z "${NETBOOT}" ]; then
91         if [ "${ROOT}" == "/dev/nfs" ]; then
92             NETBOOT="nfs"
93             export NETBOOT
94         elif [ "${ROOT}" == "/dev/cifs" ]; then
95             NETBOOT="cifs"
96             export NETBOOT
97         fi
98     fi
99 }
100
101 is_casper_path() {
102     path=$1
103     if [ -d "$path/casper" ]; then
104         if [ "$(echo $path/casper/*.cloop)" != "$path/casper/*.cloop" ] ||
105             [ "$(echo $path/casper/*.squashfs)" != "$path/casper/*.squashfs" ] ||
106             [ "$(echo $path/casper/*.ext2)" != "$path/casper/*.ext2" ] ||
107             [ "$(echo $path/casper/*.dir)" != "$path/casper/*.dir" ]; then
108             return 0
109         fi
110     fi
111     return 1
112 }
113
114 subdevices() {
115     sysblock=$1
116     r=""
117     for dev in "${sysblock}" "${sysblock}"/*; do
118         if [ -e "${dev}/dev" ]; then
119             r="${r} ${dev}"
120         fi
121     done
122     echo ${r}
123 }
124
125 get_backing_device() {
126     case "$1" in
127         *.cloop)
128             echo $(setup_loop "$1" "cloop" "/sys/block/cloop*")
129             ;;
130         *.squashfs|*.ext2)
131             echo $(setup_loop "$1" "loop" "/sys/block/loop*")
132             ;;
133         *.dir)
134             echo "directory"
135             ;;
136         *)
137             panic "Unrecognized casper filesystem: $1"
138             ;;
139     esac
140 }
141
142 match_files_in_dir() {
143     # Does any files match pattern $1 ?
144
145     local pattern="$1"
146     if [ "$(echo $pattern)" != "$pattern" ]; then
147         return 0
148     fi
149     return 1
150 }
151
152 mount_images_in_directory() {
153     directory="$1"
154     rootmnt="$2"
155     if match_files_in_dir "$directory/casper/*.cloop"; then
156         # Let's hope there's just one matching *.cloop... FIXME
157         setup_devmapper $(get_backing_device "$directory/casper/*.cloop") "$rootmnt"
158     elif match_files_in_dir "$directory/casper/*.squashfs" || 
159         match_files_in_dir "$directory/casper/*.ext2" ||
160         match_files_in_dir "$directory/casper/*.dir"; then
161         setup_unionfs "$directory/casper" "$rootmnt"
162     else
163         :
164     fi
165 }
166
167 sys2dev() {
168     sysdev=${1#/sys}
169     echo "/dev/$(udevinfo -q name -p ${sysdev} 2>/dev/null|| echo ${sysdev##*/})"
170 }
171
172 setup_loop() {
173     local fspath=$1
174     local module=$2
175     local pattern=$3
176
177     modprobe "${MP_QUIET}" -b "$module"
178     udevsettle
179
180     for loopdev in $pattern; do
181         if [ "$(cat $loopdev/size)" -eq 0 ]; then
182             dev=$(sys2dev "${loopdev}")
183             losetup "$dev" "$fspath"
184             echo "$dev"
185             return 0
186         fi
187     done
188     panic "No loop devices available"
189 }
190
191 get_fstype() {
192     local FSTYPE
193     local FSSIZE
194     eval $(fstype < $1)
195     if [ "$FSTYPE" != "unknown" ]; then
196         echo $FSTYPE
197         return 0
198     fi
199     /lib/udev/vol_id -t $1 2>/dev/null
200 }
201
202 setup_devmapper() {
203     backdev="$1"
204     rootmnt="$2"
205
206     modprobe "${MP_QUIET}" -b dm-mod
207     COW_DEVICE=/dev/ram1
208     COW_NAME="casper-cow"
209
210     BACKING_FILE_SIZE=$(blockdev --getsize "$backdev")
211     MAX_COW_SIZE=$(blockdev --getsize "$COW_DEVICE")
212     CHUNK_SIZE=8 # sectors
213
214     if [ -z "$COW_SIZE" -o "$COW_SIZE" -gt "$MAX_COW_SIZE" ]; then
215         COW_SIZE=$MAX_COW_SIZE
216     fi
217
218     echo "0 $COW_SIZE linear $COW_DEVICE 0" | dmsetup create $COW_NAME
219
220     echo "0 $BACKING_FILE_SIZE snapshot $backdev /dev/mapper/$COW_NAME p $CHUNK_SIZE" | \
221         dmsetup create casper-snapshot
222     if [ "$(get_fstype $backdev)" = "unknown" ]; then
223         panic "Unknown file system type on $backdev"
224     fi
225     mount -t $(get_fstype "$backdev") /dev/mapper/casper-snapshot $rootmnt || panic "Can not mount /dev/mapper/casper/snapshot on $rootmnt"
226
227     mkdir -p "$rootmnt/rofs"
228     echo "0 $BACKING_FILE_SIZE linear $backdev 0" | dmsetup create casper-backing
229     mount -t $(get_fstype "$backdev") /dev/mapper/casper-backing "$rootmnt/rofs"
230 }
231
232 is_nice_device() {
233     sysfs_path="${1#/sys}"
234     if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-[^-]*-[ide|scsi|usb])"; then
235         return 0
236     fi
237     return 1
238 }
239
240 is_supported_fs ()
241 {
242     # FIXME: do something better like the scan of supported filesystems
243     fstype="${1}"
244     case ${fstype} in
245         vfat|iso9660|udf|ext2|ext3|ntfs)
246             return 0
247             ;;
248     esac
249     return 1
250 }
251
252 where_is_mounted() {
253     device=$1
254     if grep -q "^$device " /proc/mounts; then
255         grep "^$device " /proc/mounts | read d mountpoint rest
256         echo $mountpoint
257         return 0
258     fi
259     return 1
260 }
261
262 used_fs_size ()
263 {
264     # Returns used fs kbytes + 5% more
265     # You could pass a block device as $1 or the mount point as $2
266
267     dev="${1}"
268     mountp="${2}"
269
270     if [ -z "${mountp}" ]; then
271         mountp=$(where_is_mounted "${dev}")
272         if [ "$?" -gt 0 ]; then
273             mountp=/mnt/tmp_fs_size
274             mkdir -p "${mountp}"
275             mount -t $(get_fstype "${dev}") -o ro "${dev}" "${mountp}"
276             doumount=1
277         fi
278     fi
279
280     size=$(du -ks ${mountp} | cut -f1)
281     size=$(expr ${size} + ${size}/20 ) # FIXME: 5% more to be sure
282     needed_space=$(expr ${size} * 1024)
283
284     if [ ! -z "${doumount}" ]; then
285         umount "${mountp}"
286         rmdir "${mountp}"
287     fi
288     echo "${needed_space}"
289 }
290
291 copy_live_to() {
292     copyfrom="${1}"
293     copytodev="${2}"
294     copyto="${copyfrom}_swap"
295
296     size=$(used_fs_size "null" "${copyfrom}")
297
298     if [ "${copytodev}" = "ram" ]; then
299         # copying to ram:
300         freespace=$( expr $(awk '/MemFree/{print $2}' /proc/meminfo) + $( cat /proc/meminfo | grep Cached | head -n 1 | awk '/Cached/{print $2}' - ) )
301         mount_options="-o size=${size}k"
302         free_string="memory"
303         fstype="tmpfs"
304         dev="/dev/shm"
305     else
306         # it should be a writable block device
307         if [ -b "${copytodev}" ]; then
308             free_string="space"
309             freespace="$(df -k ${copytodev} | grep -s ${copytodev} | awk '{print $4}')"
310             fstype="$(get_fstype ${devname})"
311             dev="${copytodev}"
312         else
313             return 1
314         fi
315     fi
316     if [ ! ${freespace} -lt ${size}  ] ; then
317         [ "$quiet" != "y" ] && log_begin_msg "Not enough free ${free_string} to copy live media in ${copytodev}."
318         [ "$quiet" != "y" ] && log_end_msg
319         return 1
320     fi
321
322     # begin copying..
323     [ "$quiet" != "y" ] && log_begin_msg "Copying live media to ${copytodev}..." 
324     mkdir "${copyto}"
325     mount -t "${fstype}" ${mount_options} "${dev}" "${copyto}"
326     cp -a ${copyfrom}/* ${copyto} # "cp -a" from busybox also copies hidden files
327     umount ${copyfrom}
328     mount -r -o move ${copyto} ${copyfrom}
329     rmdir ${copyto}
330     [ "$quiet" != "y" ] && log_end_msg
331     return 0
332 }
333
334 try_mount ()
335 {
336     dev="${1}"
337     mountp="${2}"
338     opts="${3}"
339
340     if where_is_mounted ${dev} > /dev/null; then
341         mount -o remount,"${opts}" ${dev} $(where_is_mounted ${dev}) || panic "Remounting failed"
342         mount -o bind $(where_is_mounted ${dev}) ${mountp} || panic "Cannot bind-mount"
343     else
344         mount -t $(get_fstype "${dev}") -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}"
345     fi
346 }
347
348 find_cow_device() {
349     pers_label="${1}"
350     cow_backing="/${pers_label}-backing"
351     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
352         for dev in $(subdevices "${sysblock}"); do
353             devname=$(sys2dev "${dev}")
354             if [ "$(/lib/udev/vol_id -l $devname 2>/dev/null)" = "${pers_label}" ]; then
355                 echo "$devname"
356                 return
357             elif [ "$(get_fstype ${devname})" = "vfat" ]; then # FIXME: all supported block devices should be scanned
358                 mkdir -p "${cow_backing}"
359                 try_mount "${devname}" "${cow_backing}" "rw"
360                 if [ -e "${cow_backing}/${pers_label}" ]; then
361                     echo $(setup_loop "${cow_backing}/${pers_label}" "loop" "/sys/block/loop*")
362                     return 0
363                 else
364                     umount ${cow_backing}
365                 fi
366             fi
367         done
368     done
369 }
370
371 find_files()
372 # return the first of $filenames found on vfat and ext2 devices
373 # FIXME: merge with above function
374 {
375     filenames="${1}"
376     snap_backing="/snap-backing"
377     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
378         for dev in $(subdevices "${sysblock}"); do
379             devname=$(sys2dev "${dev}")
380             devfstype="$(get_fstype ${devname})"
381             if [ "${devfstype}" = "vfat" ] ||  [ "${devfstype}" = "ext2" ] ; then # FIXME: all supported block devices should be scanned
382                 mkdir -p "${snap_backing}"
383                 try_mount "${devname}" "${snap_backing}" "ro"
384                 for filename in ${filenames}; do
385                     if [ -e "${snap_backing}/${filename}" ]; then
386                         echo "${devname} ${snap_backing} ${filename}"
387                         return 0
388                     fi
389                 done
390                 umount ${snap_backing}
391             fi
392         done
393     done
394 }
395
396 do_netmount() {
397     rc=1
398
399     modprobe "${MP_QUIET}" af_packet # For DHCP
400
401     ipconfig ${DEVICE} /tmp/net-${DEVICE}.conf
402
403     if [ "${NFSROOT}" = "auto" ]; then
404         NFSROOT=${ROOTSERVER}:${ROOTPATH}
405     fi
406
407     [ "$quiet" != "y" ] && log_begin_msg "Trying netboot from ${NFSROOT}"
408
409     if [ "${NETBOOT}" != "nfs" ] && do_cifsmount ; then
410         rc=0
411     elif do_nfsmount ; then
412         NETBOOT="nfs"
413         export NETBOOT
414         rc=0
415     fi
416
417     [ "$quiet" != "y" ] && log_end_msg
418     return ${rc}
419 }
420
421 do_nfsmount() {
422     rc=1
423     modprobe "${MP_QUIET}" nfs
424     if [ -z "${NFSOPTS}" ]; then
425         NFSOPTS=""
426     fi
427
428     [ "$quiet" != "y" ] && log_begin_msg "Trying nfsmount -o nolock -o ro ${NFSOPTS} ${NFSROOT} ${mountpoint}"
429     # FIXME: This for loop is an ugly HACK round an nfs bug
430     for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13; do
431         nfsmount -o nolock -o ro ${NFSOPTS} "${NFSROOT}" "${mountpoint}" && rc=0 && break
432         sleep 1
433     done
434     return ${rc}
435 }
436
437 do_cifsmount() {
438     rc=1
439     if [ -x "/sbin/mount.cifs" ]; then
440         if [ -z "${NFSOPTS}" ]; then
441             CIFSOPTS="-ouser=root,password="
442         else
443             CIFSOPTS="${NFSOPTS}"
444         fi
445
446         [ "$quiet" != "y" ] && log_begin_msg "Trying mount.cifs ${NFSROOT} ${mountpoint} ${CIFSOPTS}"
447         modprobe "${MP_QUIET}" cifs
448
449         if mount.cifs "${NFSROOT}" "${mountpoint}" "${CIFSOPTS}" ; then
450             rc=0
451         fi
452     fi
453     return ${rc}
454 }
455
456 do_snap_copy ()
457 {
458     fromdev="${1}"
459     todir="${2}"
460     snap_type="${3}"
461
462     size=$(used_fs_size "${fromdev}")
463
464     if [ -b "${fromdev}" ]; then
465         # look for free mem
466         if [ ! -z "${HOMEMOUNTED}" ] && [ "${snap_type}" = "HOME" ]; then
467             freespace="$(df -k ${copytodev} | grep -s ${copytodev} | awk '{print $4}')"
468         else
469             freespace=$( expr $(awk '/MemFree/{print $2}' /proc/meminfo) + $( cat /proc/meminfo | grep Cached | head -n 1 | awk '/Cached/{print $2}' - ))
470         fi
471         tomount="/mnt/tmpsnap"
472         mkdir -p "${tomount}"
473         mount -t $(get_fstype "${fromdev}") -o ro "${fromdev}" "${tomount}"
474         cp -a "${tomount}"/* ${todir}
475         umount "${tomount}"
476
477         if echo ${fromdev} | grep -qs loop; then
478             losetup -d "${fromdev}"
479         fi
480
481         return 0
482     else
483         return 1
484         [ "$quiet" != "y" ] && log_warning_msg "Unable to find the snapshot ${snap_type} medium"
485     fi
486 }
487
488 try_snap ()
489 {
490     snap_label="${1}"
491     snap_mount="${2}"
492     snap_type="${3}"
493
494     snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.cpz ${snap_label}.gz")
495     if [ ! -z "${snapdata}" ]; then
496         snapdev=$(echo ${snapdata} | cut -f1 -d ' ')
497         snapback=$(echo ${snapdata} | cut -f2 -d ' ')
498         snapfile=$(echo ${snapdata} | cut -f3 -d ' ')
499         if echo "${snapfile}" | grep -qs "squashfs" ; then
500             # squashfs snapshot
501             if ! do_snap_copy $( get_backing_device "${snapback}/${snapfile}" ) "${snap_mount}" "${snap_type}"; then
502                  log_warning_msg "Impossible to include the ${snapfile} Snapshot"
503                  return 1
504             fi
505         else
506             # cpio.gz snapshot
507             if ! (cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | cpio -i -u -d ) ; then
508                 log_warning_msg "Impossible to include the ${snapfile} Snapshot"
509                 return 1
510             fi
511         fi
512         umount "${snapback}"
513     else # try pure snapshot device better elif.. rework all that routine
514         if ! do_snap_copy $(find_cow_device "${snap_label}") "${snap_mount}" "${snap_type}"; then
515             log_warning_msg "Impossible to include the ${snap_label} Snapshot"
516             return 1
517         fi
518     fi
519     echo "export ${snap_type}SNAP=${snapdev}:${snapfile}" >> /etc/casper.conf # for resync on reboot/halt
520     return 0
521 }
522
523 do_others_persistences ()
524 {
525     # directly mount /home
526     # FIXME: add a custom mounts configurable system
527     homecow=$(find_cow_device "${home_persistence}" )
528     if [ -b "${homecow}" ]; then
529         mount ${homecow} -t $(get_fstype "${homecow}") -o rw "${rootmnt}/home"
530         export HOMEMOUNTED=1
531     else
532         [ "$quiet" != "y" ] && log_warning_msg "Unable to find the persistent home medium"
533     fi
534
535     # Look for snapshots to copy in
536     try_snap "${root_snapshot}" "${rootmnt}" "ROOT"
537     try_snap "${home_snapshot}" "${rootmnt}/home" "HOME"
538 }
539
540 setup_unionfs() {
541     image_directory="$1"
542     rootmnt="$2"
543
544     modprobe "${MP_QUIET}" -b unionfs
545
546     # run-init can't deal with images in a subdir, but we're going to
547     # move all of these away before it runs anyway.  No, we're not,
548     # put them in / since move-mounting them into / breaks mono and
549     # some other apps.
550
551     croot="/"
552
553     # Let's just mount the read-only file systems first
554     rofsstring=""
555     rofslist=""
556     if [ "${NETBOOT}" == "nfs" ] ; then
557         roopt="nfsro" # go aroung a bug in nfs-unionfs locking
558     else
559         roopt="ro"
560     fi
561
562     mkdir -p "${croot}"
563     for image_type in "ext2" "squashfs" "dir" ; do
564         for image in "${image_directory}"/*."${image_type}"; do
565             imagename=$(basename "${image}")
566             if [ -d "${image}" ]; then
567                 # it is a plain directory: do nothing
568                 rofsstring="${image}=${roopt}:${rofsstring}"
569                 rofslist="${image} ${rofslist}"
570             elif [ -f "${image}" ]; then
571                 backdev=$(get_backing_device "$image")
572                 fstype=$(get_fstype "${backdev}")
573                 if [ "${fstype}" = "unknown" ]; then
574                     panic "Unknown file system type on ${backdev} (${image})"
575                 fi
576                 mkdir -p "${croot}/${imagename}"
577                 mount -t "${fstype}" -o ro "${backdev}" "${croot}/${imagename}" || panic "Can not mount $backdev ($image) on ${croot}/${imagename}" && rofsstring="${croot}/${imagename}=${roopt}:${rofsstring}" && rofslist="${croot}/${imagename} ${rofslist}"
578             fi
579         done
580     done
581     rofsstring=${rofsstring%:}
582
583     mkdir -p /cow
584     cowdevice="tmpfs"
585     cow_fstype="tmpfs"
586
587     # Looking for "${root_persistence}" device or file
588     if [ ! -z "${PERSISTENT}" ]; then
589         cowprobe=$(find_cow_device "${root_persistence}")
590         if [ -b "${cowprobe}" ]; then
591             cowdevice=${cowprobe}
592             cow_fstype=$(get_fstype "${cowprobe}")
593         else
594             [ "$quiet" != "y" ] && log_warning_msg "Unable to find the persistent medium"
595         fi
596     fi
597
598     mount ${cowdevice} -t ${cow_fstype} -o rw /cow || panic "Can not mount $cowdevice on /cow"
599
600     mount -t unionfs -o dirs=/cow=rw:$rofsstring unionfs "$rootmnt" || panic "Unionfs mount failed"
601
602     # Adding other custom mounts
603     if [ ! -z "${PERSISTENT}" ]; then
604         do_others_persistences
605     fi
606
607     if [ ! -z "${SHOWMOUNTS}" ]; then
608         for d in ${rofslist}; do
609             mkdir -p "${rootmnt}/casper/${d##*/}"
610             case d in
611                 *.dir) # do nothing # mount -o bind "${d}" "${rootmnt}/casper/${d##*/}"
612                     ;;
613                 *) mount -o move "${d}" "${rootmnt}/casper/${d##*/}"
614                     ;;
615             esac
616         done
617     fi
618
619     # shows cow fs on /cow for use by casper-snapshot
620     mkdir -p "$rootmnt/cow"
621     mount -o bind /cow "$rootmnt/cow"
622 }
623
624 check_dev ()
625 {
626     sysdev="${1}"
627     devname="${2}"
628     if [ -z "${devname}" ]; then
629         devname=$(sys2dev "${sysdev}")
630     fi
631     fstype=$(get_fstype "${devname}")
632     if is_supported_fs ${fstype}; then
633         mount -t ${fstype} -o ro "${devname}" $mountpoint || continue
634         if is_casper_path $mountpoint; then
635             echo $mountpoint
636             return 0
637         else
638             umount $mountpoint
639         fi
640     fi
641     return 1
642 }
643
644 find_livefs() {
645     # first look at the one specified in the command line
646     if [ ! -z "${LIVEMEDIA}" ]; then
647         if check_dev "null" "${LIVEMEDIA}"; then
648             return 0
649         fi
650     fi
651     # or do the scan of block devices
652     for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop | grep -v ram); do
653         devname=$(sys2dev "${sysblock}")
654         fstype=$(get_fstype "${devname}")
655         if /lib/udev/cdrom_id ${devname} > /dev/null; then
656             if check_dev "null" "${devname}" ; then
657                 return 0
658             fi
659         elif is_nice_device "${sysblock}" ; then
660             for dev in $(subdevices "${sysblock}"); do
661                 if check_dev "${dev}" ; then
662                     return 0
663                 fi
664             done
665         elif [ "${fstype}" = "squashfs" -o \
666                 "${fstype}" = "ext3" ] -o \
667                 "${fstype}" = "ext2" ]; then
668             # This is an ugly hack situation, the block device has
669             # an image directly on it.  It's hopefully
670             # casper, so take it and run with it.
671             ln -s "${devname}" "${devname}.${fstype}"
672             echo "${devname}.${fstype}"
673             return 0
674         fi
675     done
676     return 1
677 }
678
679 pulsate() {
680     if [ -x /sbin/usplash_write ]; then
681         /sbin/usplash_write "PULSATE"
682     fi
683 }
684
685 set_usplash_timeout() {
686     if [ -x /sbin/usplash_write ]; then
687         /sbin/usplash_write "TIMEOUT 120"
688     fi
689 }
690
691 mountroot() {
692     exec 6>&1
693     exec 7>&2
694     exec > casper.log
695     exec 2>&1
696
697     parse_cmdline
698
699     set_usplash_timeout
700     [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/casper-premount"
701     pulsate
702     run_scripts /scripts/casper-premount
703     [ "$quiet" != "y" ] && log_end_msg
704
705     # Needed here too because some things (*cough* udev *cough*)
706     # changes the timeout
707
708     set_usplash_timeout
709
710     if [ ! -z "${NETBOOT}" ]; then
711         if do_netmount ; then
712             livefs_root="${mountpoint}"
713         else
714             panic "Unable to find a the network rootfs live file system"
715         fi
716     else
717         # Scan local devices for the image
718         for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13; do
719             livefs_root=$(find_livefs)
720             if [ ! -z "${livefs_root}" ]; then
721                 break
722             fi
723             sleep 1
724         done
725     fi
726
727     if [ -z "${livefs_root}" ]; then
728         panic "Unable to find a medium containing a live file system"
729     fi
730
731     if [ ! -z "${TORAM}" ]; then
732         copy_live_to "${livefs_root}" "ram"
733     elif [ ! -z "${TODISK}" ]; then
734         copy_live_to "${livefs_root}" "${TODISK}"
735     fi
736
737     mount_images_in_directory "${livefs_root}" "${rootmnt}"
738
739     log_end_msg
740
741     maybe_break casper-bottom
742     [ "$quiet" != "y" ] && log_begin_msg "Running /scripts/casper-bottom"
743
744     pulsate
745     run_scripts /scripts/casper-bottom
746     [ "$quiet" != "y" ] && log_end_msg
747
748     exec 1>&6 6>&-
749     exec 2>&7 7>&-
750     cp casper.log "${rootmnt}/var/log/"
751 }