367 lines
9.6 KiB
Bash
367 lines
9.6 KiB
Bash
#!/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 /sbin/udevadm test-builtin 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
|
|
}
|