linux-live/livekitlib

334 lines
7.5 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#!/bin/sh
# Functions library :: for Linux Live Kit scripts
# Author: Tomas M. <http://www.linux-live.org>
#
# =================================================================
# debug and output functions
# =================================================================
debug_log()
{
if [ "$DEBUG_IS_ENABLED" ]; then
echo "- debug: $*" >&2
log "- debug: $*"
fi
}
# header
# $1 = text to show
#
header()
{
echo """$@"""
}
# echo green star
#
echo_green_star()
{
echo -ne """* """
}
# log - store given text in /var/log/livedbg
log()
{
echo "$@" 2>/dev/null >>/var/log/livedbg
}
echolog()
{
echo "$@"
log "$@"
}
# show information about the debug shell
show_debug_banner()
{
echo
echo "====="
echo ": Debugging started. Here is the root shell for you."
echo ": Type your desired commands or hit Ctrl+D to continue booting."
echo
}
# debug_shell
# executed when debug boot parameter is present
#
debug_shell()
{
if [ "$DEBUG_IS_ENABLED" ]; then
show_debug_banner
sh < /dev/console
echo
fi
}
fatal()
{
echolog
header "Fatal error occured - $1"
echolog "Something went wrong and we can't continue. This should never happen."
echolog "Please reboot your computer with Ctrl+Alt+Delete ..."
echolog
sh < /dev/console
}
# test if the script is started by root user. If not, exit
#
allow_only_root()
{
if [ "0$UID" -ne 0 ]; then
echo "Only root can run $(basename $0)"; exit 1
fi
}
# Create bundle
# call mksquashfs with apropriate arguments
# $1 = directory which will be compressed to squashfs bundle
# $2 = output file
# $3..$9 = optional arguments like -keep-as-directory or -b 123456789
#
create_bundle()
{
debug_log "create_module" "$*"
rm -f "$2" # overwrite, never append to existing file
mksquashfs "$1" "$2" -comp xz -b 512K $3 $4 $5 $6 $7 $8 $9>/dev/null
}
# Move entire initramfs tree to ramfs mount.
# It's a bit tricky but is necessray to enable pivot_root
# even for initramfs boot image
#
transfer_initramfs()
{
if [ ! -r /lib/initramfs_escaped ]; then
echo "switch root from initramfs to ramfs"
SWITCH=/m # one letter directory
mkdir -p $SWITCH
mount -t ramfs ramfs $SWITCH
cp -a /??* $SWITCH 2>/dev/null # only copy two-and-more-letter directories
cd $SWITCH
echo "This file indicates that we successfully escaped initramfs" > $SWITCH/lib/initramfs_escaped
exec switch_root -c /dev/console . $0
fi
}
# mount virtual filesystems like proc etc
#
init_proc_sysfs()
{
debug_log "vfs_mount_init"
mount -n -t proc proc /proc
echo "0" >/proc/sys/kernel/printk
mount -n -t sysfs sysfs /sys
mount -n -o remount,rw rootfs /
ln -sf /proc/mounts /etc/mtab
}
# make sure some devices are there
init_devs()
{
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
modprobe zram 2>/dev/null
modprobe loop 2>/dev/null
modprobe squashfs 2>/dev/null
}
# Activate zram (auto-compression of RAM)
# Compressed RAM consumes 1/2 or even 1/4 of original size
# Setup static size of 500MB
#
init_zram()
{
debug_log "init_zram"
echo_green_star
echo "Setting dynamic RAM compression using ZRAM"
echo 536870912 > /sys/block/zram0/disksize # 512MB
echo 100 > /proc/sys/vm/swappiness
mkswap /dev/zram0 >/dev/null
swapon /dev/zram0 -p 32767
}
# load the AUFS kernel module if needed
#
init_aufs()
{
debug_log "init_aufs"
# TODO maybe check here if aufs support is working at all
# and procude useful error message if user has no aufs
modprobe aufs 2>/dev/null
}
# Setup empty union
# $1 = memory directory (tmpfs will be mounted there)
# $2 = union directory where to mount the union
#
init_union()
{
debug_log "init_union"
echo_green_star
echo "Setting up union using AUFS 3"
mkdir -p "$1"
mkdir -p "$2"
mount -t aufs -o xino="$1/.xino",br="$1" none "$2"
}
# Return device mounted for given directory
# $1 = directory
#
mounted_device()
{
local MNT TARGET
MNT="$1"
while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do
TARGET="$(grep -F " $MNT " /proc/mounts | cut -d " " -f 1)"
if [ "$TARGET" != "" ]; then
echo "$TARGET"
return
fi
MNT="$(dirname $MNT)"
done
}
# Make sure to mount FAT12/16/32 using vfat
# in order to support long filenames
# $1 = device
#
device_bestfs()
{
debug_log "device_bestfs"
local PEEK
PEEK="$(dd if="$1" bs=1k count=1 2>/dev/null | strings)"
if [ "$(echo "$PEEK" | egrep -i "FAT[13][26]")" != "" ]; then
echo "-t vfat"
# TODO: this will work only with fuse
# else if [ "$(echo "$PEEK" | egrep -i 'NTFS')" != "" ]; then
# echo "-t ntfs-3g"
fi
}
# Find LIVEKIT data by mounting all devices
# If found, keep mounted, else unmount
# $1 = data directory target (mount here)
#
find_data_try()
{
debug_log "find_data_try"
local DEVICE FS MNT
mkdir -p "$1"
blkid | sort | cut -d: -f 1 | grep -E -v "/loop|/ram|/zram" | while read DEVICE; do
FS="$(device_bestfs "$DEVICE")"
mount -r "$DEVICE" "$1" $FS
if [ -d "$1/$LIVEKITNAME" ]; then
echo "$1/$LIVEKITNAME"
return
fi
umount "$1" 2>/dev/null
done
}
# Retry finding LIVEKIT data several times,
# until timeouted or until data is found
# $1 = timeout
# $2 = data directory target (mount here)
#
find_data()
{
debug_log "find_data"
local DATA
echo_green_star >&2
echo -n "Looking for $LIVEKITNAME data .." >&2
for timeout in $(seq 1 $1); do
echo -n "." >&2
DATA="$(find_data_try "$2")"
if [ "$DATA" != "" ]; then
echo "" >&2
echo "- found in $(mounted_device "$DATA")" >&2
echo "$DATA"
return
fi
sleep 1
done
echo "" >&2
if [ "$DATA" = "" ]; then
fatal "$LIVEKITNAME data not found"
fi
}
# Mount squashfs filesystem bundles
# and add them to union
# $1 = directory where to search for bundles
# $2 = directory where to mount bundles
# $3 = directory where union is mounted
#
union_append_bundles()
{
debug_log "union_append_bundles"
echo_green_star
echo "Adding bundles to union"
ls -1 "$1" | grep '.'$BEXT'$' | sort | while read BUNDLE; do
echo "- $BUNDLE"
mkdir -p "$2/$BUNDLE"
mount -o loop -t squashfs "$1/$BUNDLE" "$2/$BUNDLE"
mount -o remount,add:1:"$2/$BUNDLE" none "$3"
done
}
# Create empty fstab properly
# $1 = root directory
#
fstab_create()
{
local FSTAB
FSTAB="$1/etc/fstab"
echo aufs / aufs defaults 0 0 > $FSTAB
echo proc /proc proc defaults 0 0 >> $FSTAB
echo sysfs /sys sysfs defaults 0 0 >> $FSTAB
echo devpts /dev/pts devpts gid=5,mode=620 0 0 >> $FSTAB
echo tmpfs /dev/shm tmpfs defaults 0 0 >> $FSTAB
}
# Change root and execute init
# $1 = where to change root
#
change_root()
{
umount /proc
umount /sys
cd "$1"
# make sure important devices are in union
if [ ! -e dev/console ]; then mknod dev/console c 5 1; fi
if [ ! -e dev/null ]; then mknod dev/null c 1 3; fi
# find chroot and init
if [ -x bin/chroot ]; then CHROOT=bin/chroot; fi
if [ -x sbin/chroot ]; then CHROOT=sbin/chroot; fi
if [ -x usr/bin/chroot ]; then CHROOT=usr/bin/chroot; fi
if [ -x usr/sbin/chroot ]; then CHROOT=usr/sbin/chroot; fi
if [ "$CHROOT" = "" ]; then fatal "Can't find executable chroot command"; fi
if [ -x bin/init ]; then INIT=bin/init; fi
if [ -x sbin/init ]; then INIT=sbin/init; fi
if [ "$INIT" = "" ]; then fatal "Can't find executable init command"; fi
mkdir -p mnt/live
mount -n -o remount,ro aufs .
pivot_root . mnt/live
exec $CHROOT . $INIT < dev/console > dev/console 2>&1
}