#!/bin/sh # set -e export PATH=/usr/bin:/usr/sbin:/bin:/sbin mountpoint=/cdrom LIVE_MEDIA_PATH=casper LIVE_ROOTFS=filesystem.squashfs USERNAME=casper USERFULLNAME="Live session user" HOST=live BUILD_SYSTEM=Custom mkdir -p $mountpoint tried=/tmp/tried [ -f /etc/casper.conf ] && . /etc/casper.conf export USERNAME USERFULLNAME HOST BUILD_SYSTEM . /scripts/functions . /scripts/casper-helpers if [ ! -f /casper.vars ]; then touch /casper.vars fi parse_cmdline() { for x in $(cat /proc/cmdline); do case $x in union=*) export UNIONFS="${x#union=}";; ignore_uuid) IGNORE_UUID="Yes" ;; live-rootfs=*) LIVE_ROOTFS="${x#live-rootfs=}" export LIVE_ROOTFS echo "export LIVE_ROOTFS=\"$LIVE_ROOTFS\"" >> /etc/casper.conf ;; live-media-path=*) LIVE_MEDIA_PATH="${x#live-media-path=}" export LIVE_MEDIA_PATH echo "export LIVE_MEDIA_PATH=\"$LIVE_MEDIA_PATH\"" >> /etc/casper.conf ;; toram) export TORAM="Yes" ;; todisk=*) export TODISK="${x#todisk=}" ;; esac done if [ "${UNIONFS}" = "" ]; then export UNIONFS="unionfs" fi } is_casper_path() { local path=$1 if [ -d "$path/$LIVE_MEDIA_PATH" ]; then if [ "$(echo $path/$LIVE_MEDIA_PATH/*.squashfs)" != \ "$path/$LIVE_MEDIA_PATH/*.squashfs" ]; then return 0 fi fi return 1 } matches_uuid() { if [ "$IGNORE_UUID" ] || [ ! -e /conf/uuid.conf ]; then return 0 fi local path="$1" local uuid="$(cat /conf/uuid.conf)" for try_uuid_file in "$path/.disk/casper-uuid"*; do [ -e "$try_uuid_file" ] || continue try_uuid="$(cat "$try_uuid_file")" if [ "$uuid" = "$try_uuid" ]; then return 0 fi done return 1 } get_backing_device() { case "$1" in *.squashfs) echo $(setup_loop "$1" "loop" "/sys/block/loop*") ;; *) panic "Unrecognized casper filesystem: $1" ;; esac } mount_image_in_directory() { local directory="$1" local rootmnt="$2" if [ ! -f "$directory/$LIVE_MEDIA_PATH/$LIVE_ROOTFS" ]; then panic "Cannot find $directory/$LIVE_MEDIA_PATH/$LIVE_ROOTFS" fi setup_unionfs "$directory/$LIVE_MEDIA_PATH" "$rootmnt" } is_nice_device() { local sysfs_path="${1#/sys}" if /lib/udev/path_id "${sysfs_path}" | egrep -q "ID_PATH=(usb|pci-[^-]*-(ide|scsi|usb)|platform-orion-ehci|platform- mmc|platform-mxsdhci)"; then return 0 fi if echo ${sysfs_path} | grep -q "^/block/dm-"; then return 0 fi return 1 } copy_live_to() { local copyfrom="${1}" local copytodev="${2}" local copyto="${copyfrom}_swap" local size freespace mount_options free_string fstype dev size=$(fs_size "" ${copyfrom} "used") if [ "${copytodev}" = "ram" ]; then # copying to ram: freespace=$(awk '/^MemFree:/{f=$2} /^Cached:/{c=$2} END{print f+c}' /proc/meminfo) mount_options="-o size=${size}k" free_string="memory" fstype="tmpfs" dev="/dev/shm" else # it should be a writable block device if [ -b "${copytodev}" ]; then dev="${copytodev}" free_string="space" fstype=$(get_fstype "${dev}") freespace=$(fs_size "${dev}") else [ "$quiet" != "y" ] && \ log_warning_msg "${copytodev} is not a block device." return 1 fi fi if [ "${freespace}" -lt "${size}" ] ; then [ "$quiet" != "y" ] && log_warning_msg "Not enough free ${free_string} (${freespace}k > ${size}k) to copy live media in ${copytodev}." return 1 fi # begin copying.. mkdir "${copyto}" echo "mount -t ${fstype} ${mount_options} ${dev} ${copyto}" mount -t "${fstype}" ${mount_options} "${dev}" "${copyto}" # "cp -a" from busybox also copies hidden files cp -a ${copyfrom}/* ${copyto} umount ${copyfrom} mount -r -o move ${copyto} ${copyfrom} rmdir ${copyto} return 0 } setup_unionfs() { local image_directory="$1" local rootmnt="$2" local croot rofsstring rofslist roopt image imagename backdev local fstype cowdevice cow_fstrype cow_mountopt case ${UNIONFS} in aufs|unionfs) modprobe "${MP_QUIET}" -b ${UNIONFS} || true ;; esac # 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, # put them in / since move-mounting them into / breaks mono and # some other apps. croot="/" # Let's just mount the read-only file systems first rofsstring="" rofslist="" if [ "${UNIONFS}" = "aufs" ]; then roopt="rr" else roopt="ro" fi mkdir -p "${croot}" image="${image_directory}/${LIVE_ROOTFS}" imagename=$(basename "$image") backdev=$(get_backing_device "$image") fstype=$(get_fstype "${backdev}") if [ "${fstype}" = "unknown" ]; then panic "Unknown file system type on ${backdev} (${image})" fi mkdir -p "${croot}/${imagename}" 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}" rofsstring=${rofsstring%:} mkdir -p /cow cowdevice="tmpfs" cow_fstype="tmpfs" cow_mountopt="rw,noatime,mode=755" mount -t ${cow_fstype} -o ${cow_mountopt} ${cowdevice} \ /cow || panic "Can not mount $cowdevice on /cow" mount -t ${UNIONFS} -o noatime,dirs=/cow=rw:$rofsstring \ ${UNIONFS} "$rootmnt" || panic "${UNIONFS} mount failed" # move the first mount. mkdir -p "${rootmnt}/rofs" mount -o move ${croot}${imagename} "${rootmnt}/rofs" } check_dev() { local sysdev="${1}" local devname="${2}" local skip_uuid_check="${3}" local loopdevname devuid if [ -z "${devname}" ]; then devname=$(sys2dev "${sysdev}") fi if [ -d "${devname}" ]; then mount -o bind "${devname}" $mountpoint || continue if is_casper_path $mountpoint; then echo $mountpoint return 0 else umount $mountpoint fi fi [ -e "$devname" ] || continue if [ -n "${LIVEMEDIA_OFFSET}" ]; then loopdevname=$(setup_loop "${devname}" "loop" "/sys/block/loop*" "${LIVEMEDIA_OFFSET}") devname="${loopdevname}" fi fstype=$(get_fstype "${devname}") 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_casper_path $mountpoint && \ ([ "$skip_uuid_check" ] || matches_uuid $mountpoint); then echo $mountpoint return 0 else umount $mountpoint fi fi if [ -n "${LIVEMEDIA_OFFSET}" ]; then losetup -d "${loopdevname}" fi return 1 } find_livefs() { local timeout="${1}" local devname fstype dev # first look at the one specified in the command line if [ ! -z "${LIVEMEDIA}" ]; then if check_dev "null" "${LIVEMEDIA}" "skip_uuid_check"; then return 0 fi fi # don't start autodetection before timeout has expired if [ -n "${LIVEMEDIA_TIMEOUT}" ]; then if [ "${timeout}" -lt "${LIVEMEDIA_TIMEOUT}" ]; then return 1 fi fi # or do the scan of block devices for sysblock in \ $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|fd)"); do devname=$(sys2dev "${sysblock}") [ -e "$devname" ] || continue fstype=$(get_fstype "${devname}") if /lib/udev/cdrom_id ${devname} > /dev/null; then if check_dev "null" "${devname}" ; then return 0 fi elif is_nice_device "${sysblock}" ; then for dev in $(subdevices "${sysblock}"); do if check_dev "${dev}" ; then return 0 fi done elif [ "${fstype}" = "squashfs" ]; then # This is an ugly hack situation, the block device has # an image directly on it. It's hopefully # casper, so take it and run with it. ln -s "${devname}" "${devname}.${fstype}" echo "${devname}.${fstype}" return 0 fi done return 1 } mountroot() { local i livefs_root live_dest parse_cmdline wait_for_udev 10 maybe_break casper-premount log_begin_msg "Running /scripts/casper-premount" run_scripts /scripts/casper-premount log_end_msg # Scan local devices for the image i=0 while [ "$i" -lt 10 ]; do livefs_root=$(find_livefs $i) [ -n "${livefs_root}" ] && break sleep 1 i="$(($i + 1))" done if [ -z "${livefs_root}" ]; then panic "Unable to find a medium containing a live file system" fi if [ "${TORAM}" ]; then live_dest="ram" elif [ "${TODISK}" ]; then live_dest="${TODISK}" fi if [ "${live_dest}" ]; then log_begin_msg "Copying live_media to ${live_dest}" copy_live_to "${livefs_root}" "${live_dest}" log_end_msg fi mount_image_in_directory "${livefs_root}" "${rootmnt}" maybe_break casper-bottom log_begin_msg "Running /scripts/casper-bottom" run_scripts /scripts/casper-bottom log_end_msg }