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