slitaz-modular rev 175

initramfs: Add new linux-live scripts support.
author Christopher Rogers <slaxemulator@gmail.com>
date Wed Mar 13 17:07:55 2013 +0000 (2013-03-13)
parents 0b68eab7409c
children 06775c59c666
files initramfs/init initramfs/lib/.config initramfs/lib/livekitlib
line diff
     1.1 --- a/initramfs/init	Thu Jul 19 12:14:30 2012 +0000
     1.2 +++ b/initramfs/init	Wed Mar 13 17:07:55 2013 +0000
     1.3 @@ -1,216 +1,76 @@
     1.4  #!/bin/sh
     1.5 +# Initial script for Linux Live Kit
     1.6 +# Author: Tomas M <http://www.linux-live.org/>
     1.7  
     1.8 -success()
     1.9 -{
    1.10 -	cat > /run/init
    1.11 -	[ -d /proc/sys ] && umount /proc
    1.12 -	echo -e "\\033[70G[ \\033[1;32mOK\\033[0;39m ]"
    1.13 -	exit
    1.14 -}
    1.15 +export PATH=.:/:/usr/sbin:/usr/bin:/sbin:/bin
    1.16  
    1.17 -launch_init()
    1.18 -{
    1.19 -	mount --move /run /mnt/run
    1.20 -	success <<EOT
    1.21 -exec /sbin/switch_root mnt /sbin/init
    1.22 -EOT
    1.23 -}
    1.24 +source /lib/.config
    1.25 +source /lib/livekitlib
    1.26  
    1.27 -failed()
    1.28 -{
    1.29 -	[ -d /proc/sys ] && umount /proc
    1.30 -	echo -e "\\033[70G[ \\033[1;31mFailed\\033[0;39m ]"
    1.31 -}
    1.32 +transfer_initramfs
    1.33  
    1.34 -launch_init_modular()
    1.35 -{
    1.36 -	echo -e "\\033[70G[ \\033[1;32mOK\\033[0;39m ]"
    1.37 -	[ -d /mnt/initramfs ] || mkdir -p /mnt/initramfs
    1.38 -	SYS_DIR="dev bin etc boot lib sbin home root run usr var"
    1.39 -	for dir in $SYS_DIR; do
    1.40 -		cp -a /$dir /mnt/initramfs
    1.41 -	done
    1.42 -	MK_DIR="sys proc tmp media mnt"
    1.43 -	for dir1 in $MK_DIR; do
    1.44 -		mkdir -p /mnt/initramfs/$dir1
    1.45 -	done
    1.46 -	mount --move /dev /mnt/dev
    1.47 -	[ -f /mnt/dev/sdc ] || mknod /mnt/dev/sdc b 8 32
    1.48 -	[ -f /mnt/dev/sdc1 ] || mknod /mnt/dev/sdc1 b 8 33
    1.49 -	mount --move /run /mnt/run
    1.50 -	mkdir -p /mnt/dev/pts
    1.51 -	mount --move /dev/pts /mnt/dev/pts
    1.52 -	mkdir -p /mnt/dev/shm
    1.53 -	mount --move /dev/shm /mnt/dev/shm
    1.54 -	success <<EOT
    1.55 -exec /sbin/switch_root mnt /linuxrc
    1.56 -EOT
    1.57 -}
    1.58 +MEMORY=/memory
    1.59 +CHANGES=$MEMORY/changes
    1.60 +UNION=$MEMORY/union
    1.61 +DATAMNT=$MEMORY/data
    1.62 +BUNDLES=$MEMORY/bundles
    1.63  
    1.64 -try_init()
    1.65 -{
    1.66 -	if [ ! -d /mnt/etc ] && grep -q cryptoroot= /proc/cmdline; then
    1.67 -		modprobe dm-mod
    1.68 -		modprobe dm-crypt
    1.69 -		modprobe aes-i586
    1.70 -		root="$(sed 's/.*cryptoroot=\([^ ]*\).*/\1/' < /proc/cmdline)"
    1.71 -		dev=${root#/dev/}
    1.72 -		dmlabel=crypto-$dev
    1.73 -		if cryptsetup isLuks $root 2> /dev/null; then
    1.74 -			cryptsetup luksOpen $root $dmlabel
    1.75 -		else
    1.76 -			read -s -t 60 -p "Pass phrase : " passphrase
    1.77 -			key=$(echo $passphrase | hashalot -x -n 32 sha512)
    1.78 -			blocks=$(cat $(find /sys/block | grep /$dev/size))
    1.79 -			echo 0 $blocks crypt aes-plain $key 0 $root 0 | \
    1.80 -				dmsetup create $dmlabel
    1.81 -		fi
    1.82 -		mount /dev/mapper/$dmlabel /mnt
    1.83 -	fi
    1.84 -	grep -q subroot= /proc/cmdline && return
    1.85 -	grep -q loopfs= /proc/cmdline && return
    1.86 -	if [ -d /mnt/etc ]; then
    1.87 -		umount /sys
    1.88 -		[ -n "$1" ] && for i in $@ ; do
    1.89 -			cp -a $i /mnt$(dirname $i)
    1.90 -		done
    1.91 -		mount /mnt -o remount,ro
    1.92 -		launch_init
    1.93 -	fi
    1.94 -	failed
    1.95 -}
    1.96 +header "Live Kit init <http://www.linux-live.org/>"
    1.97  
    1.98 -mount_mapper()
    1.99 -{
   1.100 -	mount $root /mnt
   1.101 -	try_init /dev/mapper $@
   1.102 -}
   1.103 +init_proc_sysfs
   1.104  
   1.105 -lvmsetup()
   1.106 -{
   1.107 -	grep -q lvmroot= /proc/cmdline || return 1
   1.108 -	modprobe dm-mod
   1.109 -	vgscan --ignorelockingfailure
   1.110 -	vgchange -ay --ignorelockingfailure
   1.111 -	root="/dev/mapper/$(sed 's/.*lvmroot=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.112 -	return 0
   1.113 -}
   1.114 +debug_start
   1.115 +debug_shell
   1.116  
   1.117 -load_raid()
   1.118 -{
   1.119 -while read line; do
   1.120 -	case "$line" in
   1.121 -	*raid10*)	modprobe raid10 ;;
   1.122 -	*raid0*)	modprobe raid0 ;;
   1.123 -	*raid1*)	modprobe raid1 ;;
   1.124 -	*raid[456]*)	modprobe raid456 ;;
   1.125 -	*mirror*)	modprobe dm-mirror ;;
   1.126 -	esac
   1.127 -done
   1.128 -}
   1.129 +init_devs
   1.130 +init_aufs
   1.131 +init_zram
   1.132  
   1.133 -if [ "$1" != "logged" ]; then
   1.134 -	mount -t devpts devpts /dev/pts
   1.135 -	mount -t tmpfs tmpfs /dev/shm
   1.136 -	mount -t tmpfs tmpfs /run
   1.137 -	script -qc '/init logged' /run/boot.log
   1.138 -	. /run/init
   1.139 -else
   1.140 -mount -t proc proc /proc
   1.141 -mount -t sysfs sysfs /sys
   1.142 -if grep -q dmraid= /proc/cmdline; then
   1.143 -	root="$(sed 's/.*dmraid=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.144 -	echo -n "Switching / to dmraid $root..."
   1.145 -	dmraid -s | grep ^type | awk '{ print $3 }' | load_raid
   1.146 -	case "$root" in
   1.147 -	/dev/*);;
   1.148 -	*) root=/dev/mapper/$(dmraid -s|grep ^name|awk '{print $3}')p${root#p};;
   1.149 -	esac
   1.150 -	dmraid -ay
   1.151 -	lvmsetup 
   1.152 -	mount_mapper
   1.153 +# find data dir with filesystem bundles
   1.154 +DATA="$(find_data 60 "$DATAMNT")"
   1.155 +debug_shell
   1.156 +
   1.157 +# setup persistent changes, if possible
   1.158 +persistent_changes "$DATA" "$CHANGES"
   1.159 +debug_shell
   1.160 +
   1.161 +# copy to RAM if needed
   1.162 +DATA="$(copy_to_ram "$DATA" "$CHANGES")"
   1.163 +debug_shell
   1.164 +
   1.165 +# init aufs union
   1.166 +init_union "$CHANGES" "$UNION"
   1.167 +debug_shell
   1.168 +
   1.169 +echo "Copying initramfs to /initramfs"
   1.170 +copy_initramfs /initramfs
   1.171 +
   1.172 +# setup initramfs if it exist
   1.173 +if [ -d /initramfs ]; then
   1.174 +	echo "Setup initramfs for first module..."
   1.175 +	mount -n -o remount,add:1:/initramfs=ro aufs $UNION
   1.176  fi
   1.177 -if grep -q softraid= /proc/cmdline; then
   1.178 -	root="$(sed 's/.*softraid=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.179 -	echo -n "Switching / to softraid $root..."
   1.180 -	mdadm --examine --scan --config=partitions > /etc/mdadm.conf
   1.181 -	grep -qs " $root " /etc/mdadm.conf ||
   1.182 -		root=$(awk '/dev.md/ { print $2; exit }' < /etc/mdadm.conf)
   1.183 -	grep level=raid /etc/mdadm.conf | load_raid
   1.184 -	for i in 1 2 3 4 5 6 7 8 9; do
   1.185 -		sleep $i
   1.186 -		mdadm --assemble --scan
   1.187 -		grep -qs ': active' /proc/mdstat && break
   1.188 -	done
   1.189 -	lvmsetup 
   1.190 -	mount_mapper /etc/mdadm.conf
   1.191 +debug_shell
   1.192 +
   1.193 +# add data to union
   1.194 +union_append_bundles "$DATA" "$BUNDLES" "$UNION"
   1.195 +debug_shell
   1.196 +
   1.197 +# rootcopy
   1.198 +copy_rootcopy_content "$DATA" "$UNION"
   1.199 +
   1.200 +# create empty fstab
   1.201 +fstab_create "$UNION"
   1.202 +debug_shell
   1.203 +
   1.204 +if [ -d $DATAMNT/mirror ]; then
   1.205 +	echolog "Setup repo for mirror iso..."
   1.206 +	mount -n -o remount,add:1:/$DATAMNT/mirror=ro aufs $UNION
   1.207  fi
   1.208 -if lvmsetup; then
   1.209 -	echo -n "Switching / to lvm $root..."
   1.210 -	mount_mapper
   1.211 -fi
   1.212 -if grep -q mount= /proc/cmdline; then
   1.213 -	root="$(sed 's/.*mount=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.214 -	dev=$(blkid | grep $root | sed 's/:.*//;q')
   1.215 -	echo "Mounting $dev ($root) ..."
   1.216 -	if ! mount $dev /mnt; then
   1.217 -		if echo $dev | grep -q "/dev/sd"; then
   1.218 -			delay=`cat /sys/module/usb_storage/parameters/delay_use`
   1.219 -			delay=$((1+$delay))
   1.220 -			echo -n "sleep for $delay seconds..."
   1.221 -			sleep $delay
   1.222 -		fi
   1.223 -		mount $dev /mnt
   1.224 -	fi
   1.225 -	grep -q posixovl /proc/cmdline && mount.posixovl /mnt
   1.226 -fi
   1.227 -if grep -q loopfs= /proc/cmdline; then
   1.228 -	loopfs="$(sed 's/.*loopfs=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.229 -	echo -n "Into loop file $loopfs..."
   1.230 -	losetup /dev/loop0 /mnt/$loopfs
   1.231 -	mount /dev/loop0 /mnt 2> /dev/null
   1.232 -fi
   1.233 -if grep -q bindfs= /proc/cmdline; then
   1.234 -	bind="$(sed 's/.*bindfs=\([^ ]*\).*/\1/' < /proc/cmdline)"
   1.235 -	echo "Binding ${bind/,/ to } ..."
   1.236 -	mount --bind /mnt/${bind%,*} /mnt/${bind%,*}/${bind#*,}
   1.237 -fi
   1.238 -grep -q cryptoroot= /proc/cmdline && try_init
   1.239 -umount /sys
   1.240 -if grep -q subroot= /proc/cmdline; then
   1.241 -	subroot="/$(sed 's/.*subroot=\([^ ]*\).*/\1/' < /proc/cmdline)" &&
   1.242 -	echo -n "Chrooting to $subroot..."
   1.243 -	mount --move /dev/pts /mnt$subroot/dev/pts
   1.244 -	run=$subroot/run
   1.245 -	mount --move /run /mnt$run
   1.246 -	cp $(LD_TRACE_LOADED_OBJECTS=1 /lib/ld*.so /usr/sbin/chroot | sed \
   1.247 -	     's|.*=> \(/lib/l[^ ]*\).*|\1|;/^\//!d') /usr/sbin/chroot /mnt$run
   1.248 -	success <<EOT
   1.249 -export LD_LIBRARY_PATH=$run:/lib
   1.250 -exec /sbin/switch_root mnt $run/$(cd /mnt$run ; ls ld-*) $run/chroot $subroot /sbin/init
   1.251 -EOT
   1.252 -fi
   1.253 -echo -n "Switching / to tmpfs"
   1.254 -size="$(grep rootfssize= < /proc/cmdline | \
   1.255 -	sed 's/.*rootfssize=\([0-9]*[kmg%]\).*/-o size=\1/')"
   1.256 -free=$(busybox free | busybox awk '/Mem:/ { print int(($4*100)/$3) }')
   1.257 -umount /proc
   1.258 -[ -n "$size" ] || size="-o size=90%"
   1.259 -echo "exec /sbin/init" > /run/init
   1.260 -if [ $free -lt 100 ] || ! mount -t tmpfs $size tmpfs /mnt; then
   1.261 -	echo -e "\\033[70G[ \\033[1;33mSkipped\\033[0;39m]"
   1.262 -	exit
   1.263 -fi
   1.264 -for i in $(ls -ar /); do
   1.265 -	case "$i" in
   1.266 -	.|..)	;;
   1.267 -	mnt)	mkdir /mnt/mnt;;
   1.268 -	*)	if ! cp -a /$i /mnt 2> /dev/null; then
   1.269 -			failed
   1.270 -			umount /mnt
   1.271 -			exec /sbin/init
   1.272 -		fi;;
   1.273 -	esac
   1.274 -done
   1.275 -launch_init_modular
   1.276 -fi
   1.277 +
   1.278 +header "Live Kit done, starting $LIVEKITNAME"
   1.279 +
   1.280 +change_root "$UNION"
   1.281 +
   1.282 +header "!!ERROR occured, you shouldn't be here.!!"
   1.283 +/bin/sh
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/initramfs/lib/.config	Wed Mar 13 17:07:55 2013 +0000
     2.3 @@ -0,0 +1,35 @@
     2.4 +#!/bin/bash
     2.5 +# This is a config file for Linux Live Kit build script.
     2.6 +# You shouldn't need to change anything expect LIVEKITNAME
     2.7 +
     2.8 +# Live Kit Name. Defaults to 'mylinux';
     2.9 +# For example, Slax changes it to 'slax'
    2.10 +# Must not contain any spaces.
    2.11 +# If you change it, you must run ./tools/isolinux.bin.update script
    2.12 +# in order to update isolinux.bin for CD booting.
    2.13 +LIVEKITNAME="slitaz"
    2.14 +
    2.15 +# Kernel file, will be copied to your Live Kit
    2.16 +VMLINUZ=/boot/vmlinuz
    2.17 +
    2.18 +# Kernel version. Change it to "3.2.28" for example, if you are building
    2.19 +# Live Kit with a different kernel than the one you are actually running
    2.20 +KERNEL=$(uname -r)
    2.21 +
    2.22 +# List of directories which will be modularized
    2.23 +# No subdirectories are allowed, no slashes,
    2.24 +# so You can't use /var/tmp here for example
    2.25 +# Exclude directories like proc sys tmp
    2.26 +MKMOD="bin etc home lib lib64 opt root sbin srv usr var"
    2.27 +
    2.28 +# List of files and directories you'd like to exclude from your Live Kit
    2.29 +EXCLUDE="/etc/fstab /etc/mtab"
    2.30 +
    2.31 +# Temporary directory to store livekit filesystem
    2.32 +LIVEKITDATA=/tmp/$LIVEKITNAME-data-$$
    2.33 +
    2.34 +# Bundle extension, for example 'sb' for .sb extension
    2.35 +BEXT=xz
    2.36 +
    2.37 +# Directory with kernel .ko modules, can be different in some distros
    2.38 +LMK="lib/modules/$KERNEL"
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/initramfs/lib/livekitlib	Wed Mar 13 17:07:55 2013 +0000
     3.3 @@ -0,0 +1,662 @@
     3.4 +#!/bin/sh
     3.5 +
     3.6 +# Functions library :: for Linux Live Kit scripts
     3.7 +# Author: Tomas M. <http://www.linux-live.org>
     3.8 +#
     3.9 +
    3.10 +# =================================================================
    3.11 +# debug and output functions
    3.12 +# =================================================================
    3.13 +
    3.14 +debug_start()
    3.15 +{
    3.16 +   if grep -q debug /proc/cmdline; then
    3.17 +      DEBUG_IS_ENABLED=1
    3.18 +   else
    3.19 +      DEBUG_IS_ENABLED=
    3.20 +   fi
    3.21 +}
    3.22 +
    3.23 +debug_log()
    3.24 +{
    3.25 +   if [ "$DEBUG_IS_ENABLED" ]; then
    3.26 +      echo "- debug: $*" >&2
    3.27 +      log "- debug: $*"
    3.28 +   fi
    3.29 +}
    3.30 +
    3.31 +# header
    3.32 +# $1 = text to show
    3.33 +#
    3.34 +header()
    3.35 +{
    3.36 +   echo """$@"""
    3.37 +}
    3.38 +
    3.39 +
    3.40 +# echo green star
    3.41 +#
    3.42 +echo_green_star()
    3.43 +{
    3.44 +   echo -ne """* """
    3.45 +}
    3.46 +
    3.47 +# log - store given text in /var/log/livedbg
    3.48 +log()
    3.49 +{
    3.50 +   echo "$@" 2>/dev/null >>/var/log/livedbg
    3.51 +}
    3.52 +
    3.53 +echolog()
    3.54 +{
    3.55 +   echo "$@"
    3.56 +   log "$@"
    3.57 +}
    3.58 +
    3.59 +# show information about the debug shell
    3.60 +show_debug_banner()
    3.61 +{
    3.62 +   echo
    3.63 +   echo "====="
    3.64 +   echo ": Debugging started. Here is the root shell for you."
    3.65 +   echo ": Type your desired commands or hit Ctrl+D to continue booting."
    3.66 +   echo
    3.67 +}
    3.68 +
    3.69 +# debug_shell
    3.70 +# executed when debug boot parameter is present
    3.71 +#
    3.72 +debug_shell()
    3.73 +{
    3.74 +   if [ "$DEBUG_IS_ENABLED" ]; then
    3.75 +      show_debug_banner
    3.76 +      setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1'
    3.77 +      echo
    3.78 +   fi
    3.79 +}
    3.80 +
    3.81 +fatal()
    3.82 +{
    3.83 +   echolog
    3.84 +   header "Fatal error occured - $1"
    3.85 +   echolog "Something went wrong and we can't continue. This should never happen."
    3.86 +   echolog "Please reboot your computer with Ctrl+Alt+Delete ..."
    3.87 +   echolog
    3.88 +   setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1'
    3.89 +}
    3.90 +
    3.91 +# get value of commandline parameter $1
    3.92 +# $1 = parameter to search for
    3.93 +#
    3.94 +cmdline_value()
    3.95 +{
    3.96 +   cat /proc/cmdline | egrep -o "(^|[[:space:]])$1=[^[:space:]]+" | tr -d " " | cut -d "=" -f 2- | tail -n 1
    3.97 +}
    3.98 +
    3.99 +
   3.100 +# test if the script is started by root user. If not, exit
   3.101 +#
   3.102 +allow_only_root()
   3.103 +{
   3.104 +  if [ "0$UID" -ne 0 ]; then
   3.105 +     echo "Only root can run $(basename $0)"; exit 1
   3.106 +  fi
   3.107 +}
   3.108 +
   3.109 +# Create bundle
   3.110 +# call mksquashfs with apropriate arguments
   3.111 +# $1 = directory which will be compressed to squashfs bundle
   3.112 +# $2 = output file
   3.113 +# $3..$9 = optional arguments like -keep-as-directory or -b 123456789
   3.114 +#
   3.115 +create_bundle()
   3.116 +{
   3.117 +   debug_log "create_module" "$*"
   3.118 +   rm -f "$2" # overwrite, never append to existing file
   3.119 +   mksquashfs "$1" "$2" -comp xz -b 512K $3 $4 $5 $6 $7 $8 $9>/dev/null
   3.120 +}
   3.121 +
   3.122 +
   3.123 +# Move entire initramfs tree to tmpfs mount.
   3.124 +# It's a bit tricky but is necessray to enable pivot_root
   3.125 +# even for initramfs boot image
   3.126 +#
   3.127 +transfer_initramfs()
   3.128 +{
   3.129 +   if [ ! -r /lib/initramfs_escaped ]; then
   3.130 +      echo "switch root from initramfs to ramfs"
   3.131 +      SWITCH=/m # one letter directory
   3.132 +      mkdir -p $SWITCH
   3.133 +      mount -t tmpfs -o size="100%" tmpfs $SWITCH
   3.134 +      cp -a /??* $SWITCH 2>/dev/null # only copy two-and-more-letter directories
   3.135 +      cd $SWITCH
   3.136 +      echo "This file indicates that we successfully escaped initramfs" > $SWITCH/lib/initramfs_escaped
   3.137 +      exec switch_root -c /dev/console . $0
   3.138 +   fi
   3.139 +}
   3.140 +
   3.141 +copy_initramfs()
   3.142 +{
   3.143 +   SWITCH=$1 # one letter directory
   3.144 +   mkdir -p $SWITCH
   3.145 +   SYS_DIR="dev bin etc boot lib sbin home root run usr var"
   3.146 +   for dir in $SYS_DIR; do
   3.147 +      cp -a /$dir /$SWITCH
   3.148 +   done
   3.149 +   
   3.150 +}
   3.151 +
   3.152 +# mount virtual filesystems like proc etc
   3.153 +#
   3.154 +init_proc_sysfs()
   3.155 +{
   3.156 +   debug_log "init_proc_sysfs" "$*"
   3.157 +   mkdir -p /proc /sys /etc $MEMORY
   3.158 +   mount -n -t proc proc /proc
   3.159 +   echo "0" >/proc/sys/kernel/printk
   3.160 +   mount -n -t sysfs sysfs /sys
   3.161 +   mount -n -o remount,rw rootfs /
   3.162 +   ln -sf /proc/mounts /etc/mtab
   3.163 +}
   3.164 +
   3.165 +# make sure some devices are there
   3.166 +init_devs()
   3.167 +{
   3.168 +   debug_log "init_devs" "$*"
   3.169 +   echo /sbin/mdev > /proc/sys/kernel/hotplug
   3.170 +   mdev -s
   3.171 +   modprobe zram 2>/dev/null
   3.172 +   modprobe loop 2>/dev/null
   3.173 +   modprobe squashfs 2>/dev/null
   3.174 +   modprobe fuse 2>/dev/null
   3.175 +}
   3.176 +
   3.177 +# Activate zram (auto-compression of RAM)
   3.178 +# Compressed RAM consumes 1/2 or even 1/4 of original size
   3.179 +# Setup static size of 500MB
   3.180 +#
   3.181 +init_zram()
   3.182 +{
   3.183 +   debug_log "init_zram" "$*"
   3.184 +   echo_green_star
   3.185 +   echo "Setting dynamic RAM compression using ZRAM"
   3.186 +   echo 536870912 > /sys/block/zram0/disksize # 512MB
   3.187 +   mkswap /dev/zram0 >/dev/null
   3.188 +   swapon /dev/zram0 -p 32767
   3.189 +   echo 100 > /proc/sys/vm/swappiness
   3.190 +}
   3.191 +
   3.192 +# load the AUFS kernel module if needed
   3.193 +#
   3.194 +init_aufs()
   3.195 +{
   3.196 +   debug_log "init_aufs" "$*"
   3.197 +   # TODO maybe check here if aufs support is working at all
   3.198 +   # and procude useful error message if user has no aufs
   3.199 +   modprobe aufs brs=1 2>/dev/null
   3.200 +}
   3.201 +
   3.202 +# Setup empty union
   3.203 +# $1 = changes directory (ramfs or persistent changes)
   3.204 +# $2 = union directory where to mount the union
   3.205 +#
   3.206 +init_union()
   3.207 +{
   3.208 +   debug_log "init_union" "$*"
   3.209 +
   3.210 +   echo_green_star
   3.211 +   echo "Setting up union using AUFS 3"
   3.212 +   mkdir -p "$1"
   3.213 +   mkdir -p "$2"
   3.214 +   mount -t aufs -o nowarn_perm,xino="/.xino",trunc_xino,br="$1" aufs "$2"
   3.215 +   if [ $? -ne 0 ]; then dmesg | tail -n 1; fatal "can't setup union (aufs)"; fi
   3.216 +}
   3.217 +
   3.218 +# Return device mounted for given directory
   3.219 +# $1 = directory
   3.220 +#
   3.221 +mounted_device()
   3.222 +{
   3.223 +   debug_log "mounted_device" "$*"
   3.224 +
   3.225 +   local MNT TARGET
   3.226 +   MNT="$1"
   3.227 +   while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do
   3.228 +      TARGET="$(grep -F " $MNT " /proc/mounts | cut -d " " -f 1)"
   3.229 +      if [ "$TARGET" != "" ]; then
   3.230 +         echo "$TARGET"
   3.231 +         return
   3.232 +      fi
   3.233 +      MNT="$(dirname "$MNT")"
   3.234 +   done
   3.235 +}
   3.236 +
   3.237 +# Return mounted dir for given directory
   3.238 +# $1 = directory
   3.239 +#
   3.240 +mounted_dir()
   3.241 +{
   3.242 +   debug_log "mounted_dir" "$*"
   3.243 +
   3.244 +   local MNT
   3.245 +   MNT="$1"
   3.246 +   while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do
   3.247 +      if mountpoint -q "$MNT" 2>/dev/null; then
   3.248 +         echo "$MNT"
   3.249 +         return
   3.250 +      fi
   3.251 +      MNT="$(dirname "$MNT")"
   3.252 +   done
   3.253 +}
   3.254 +
   3.255 +# Make sure to mount FAT12/16/32 using vfat
   3.256 +# in order to support long filenames
   3.257 +# $1 = device
   3.258 +#
   3.259 +device_bestfs()
   3.260 +{
   3.261 +   debug_log "device_bestfs" "$*"
   3.262 +   local FS
   3.263 +
   3.264 +   FS="$(blkid "$1" | sed -r "s/.* TYPE=//" | sed -r 's/ .*//' | tr -d '"' | tr [A-Z] [a-z])"
   3.265 +   if [ "$FS" = "msdos" -o "$FS" = "fat" -o "$FS" = "vfat" ]; then
   3.266 +      FS="vfat"
   3.267 +   elif [ "$FS" = "ntfs" ]; then
   3.268 +      FS="ntfs-3g"
   3.269 +   elif [ "$1" = "iso9660" -o "$1" = "udf" ]; then
   3.270 +      echo -n ",ro"
   3.271 +   else
   3.272 +      echo "-t $FS"
   3.273 +   fi
   3.274 +}
   3.275 +
   3.276 +# Filesystem options for mount
   3.277 +# $1 = filesystem or '-t filesystem'
   3.278 +#
   3.279 +fs_options()
   3.280 +{
   3.281 +   debug_log "fs_options" "$*"
   3.282 +
   3.283 +   if [ "$1" = "-t" ]; then
   3.284 +      shift
   3.285 +   fi
   3.286 +   if [ "$1" = "vfat" ]; then
   3.287 +      echo "-o check=s,shortname=mixed,iocharset=utf8"
   3.288 +   fi
   3.289 +}
   3.290 +
   3.291 +
   3.292 +# Modprobe network kernel modules until a working driver is found.
   3.293 +# These drivers are (or used to be) probed in Slackware's initrd.
   3.294 +# The function returns the first device found, yet it doesn't have
   3.295 +# to be a working one, eg. if the computer has two network interfaces
   3.296 +# and ethernet cable is plugged only to one of them.
   3.297 +#
   3.298 +init_network_dev()
   3.299 +{
   3.300 +   debug_log "init_network_dev" "$*"
   3.301 +   local MODULE ETH
   3.302 +
   3.303 +   for MODULE in 3c59x acenic de4x5 e1000 e1000e e100 epic100 hp100 \
   3.304 +   ne2k-pci pcnet32 8139too 8139cp tulip via-rhine r8169 atl1e yellowfin \
   3.305 +   tg3 dl2k ns83820 atl1 b44 bnx2 skge sky2 tulip depca 3c501 3c503 \
   3.306 +   3c505 3c507 3c509 3c515 ac3200 at1700 cosa cs89x0 de600 de620 e2100 \
   3.307 +   eepro eexpress eth16i ewrk3 forcedeth hostess_sv11 hp-plus hp ni52 \
   3.308 +   ni65 sb1000 sealevel smc-ultra sis900 smc9194 wd; do
   3.309 +      modprobe $MODULE 2>/dev/null
   3.310 +      ETH="$(cat /proc/net/dev | grep : | grep -v lo: | cut -d : -f 1 | tr -d " " | head -n 1)"
   3.311 +      if [ "$ETH" != "" ]; then
   3.312 +         echo $ETH
   3.313 +         return 0
   3.314 +      fi
   3.315 +      rmmod $MODULE 2>/dev/null
   3.316 +   done
   3.317 +
   3.318 +   # If we are here, none of the above specified modules worked.
   3.319 +   # As a last chance, try to modprobe everything.
   3.320 +   find /lib/modules/ | xargs -n 1 modprobe
   3.321 +   cat /proc/net/dev | grep : | grep -v lo: | cut -d : -f 1 | tr -d " " | head -n 1
   3.322 +}
   3.323 +
   3.324 +
   3.325 +# Download data from tftp
   3.326 +# $1 = target (store downloaded files there)
   3.327 +#
   3.328 +download_data_pxe()
   3.329 +{
   3.330 +   debug_log "download_data_pxe" "$*"
   3.331 +   local CMD CLIENT SERVER GW MASK PORT ETH PROTOCOL
   3.332 +
   3.333 +   mkdir -p "$1/$LIVEKITNAME"
   3.334 +
   3.335 +   cmdline_value ip | while IFS=":" read CLIENT SERVER GW MASK PORT; do
   3.336 +      echo_green_star >&2
   3.337 +      echo "Downloading files from $SERVER ..." >&2
   3.338 +
   3.339 +      ETH=$(init_network_dev)
   3.340 +      if [ "$PORT" = "" ]; then PORT="7529"; fi
   3.341 +
   3.342 +      # set IP address as given by boot paramter
   3.343 +      if [ "$CLIENT" != "" -a "$MASK" != "" ]; then
   3.344 +         ifconfig $ETH "$CLIENT" netmask "$MASK"
   3.345 +         route add default gw "$GW"
   3.346 +      else
   3.347 +         # if client ip is unknown, try to get a DHCP lease
   3.348 +         udhcpc -i $ETH -f -q
   3.349 +      fi
   3.350 +
   3.351 +      # well known IP address of Google public DNS service
   3.352 +      echo nameserver 8.8.8.8 >> /etc/resolv.conf
   3.353 +
   3.354 +      PROTOCOL=http
   3.355 +      wget -q -O "$1/PXEFILELIST" "http://$SERVER:$PORT/PXEFILELIST?$(uname -r):$(uname -m)"
   3.356 +      if [ $? -ne 0 ]; then
   3.357 +         echo "Error downloading from http://$SERVER:$PORT, trying TFTP" >&2
   3.358 +         PROTOCOL=tftp
   3.359 +         tftp -g -r PXEFILELIST -l "$1/PXEFILELIST" $SERVER
   3.360 +      fi
   3.361 +
   3.362 +      cat "$1/PXEFILELIST" | while read FILE; do
   3.363 +         if [ "$PROTOCOL" = "http" ]; then
   3.364 +            wget -O "$1/$LIVEKITNAME/$FILE" "http://$SERVER:$PORT/$FILE"
   3.365 +         else
   3.366 +            echo "* $FILE ..." >&2
   3.367 +            tftp -g -r $FILE -l "$1/$LIVEKITNAME/$FILE" $SERVER
   3.368 +         fi
   3.369 +      done
   3.370 +   done
   3.371 +
   3.372 +   echo "$1/$LIVEKITNAME"
   3.373 +}
   3.374 +
   3.375 +# Find LIVEKIT data by mounting all devices
   3.376 +# If found, keep mounted, else unmount
   3.377 +# $1 = data directory target (mount here)
   3.378 +# $2 = data directory which contains compressed bundles
   3.379 +#
   3.380 +find_data_try()
   3.381 +{
   3.382 +   debug_log "find_data_try" "$*"
   3.383 +
   3.384 +   local DEVICE FS FROM OPTIONS
   3.385 +
   3.386 +   mkdir -p "$1"
   3.387 +   blkid | sort | cut -d: -f 1 | grep -E -v "/loop|/ram|/zram" | while read DEVICE; do
   3.388 +      FROM="$2"
   3.389 +      FS="$(device_bestfs "$DEVICE")"
   3.390 +      OPTIONS="$(fs_options $FS)"
   3.391 +      mount -r "$DEVICE" "$1" $FS $OPTIONS 2>/dev/null
   3.392 +
   3.393 +      # if the FROM parameter is actual file, mount it again as loop (eg. iso)
   3.394 +      if [ -f "$1/$FROM" ]; then
   3.395 +         mount -o remount,rw "$DEVICE" "$1" 2>/dev/null
   3.396 +         mkdir -p "$1/../iso"
   3.397 +         mount -o loop,ro "$1/$FROM" "$1/../iso" 2>/dev/null
   3.398 +         FROM="../iso/$LIVEKITNAME"
   3.399 +      fi
   3.400 +
   3.401 +      # search for bundles in the mounted directory
   3.402 +      if [ "$(find "$1/$FROM" -maxdepth 2 -name "*.$BEXT" 2>/dev/null)" != "" ]; then
   3.403 +         # we found at least one bundle/module here
   3.404 +         mount -o remount,rw "$DEVICE" "$1" 2>/dev/null
   3.405 +         echo "$1/$FROM" | tr -s "/" | sed -r "s:/[^/]+/[.][.]/:/:g"
   3.406 +         return
   3.407 +      fi
   3.408 +
   3.409 +      # unmount twice, since there could be mounted ISO as loop too. If not, it doesn't hurt
   3.410 +      umount "$1" 2>/dev/null
   3.411 +      umount "$1" 2>/dev/null
   3.412 +   done
   3.413 +}
   3.414 +
   3.415 +# Retry finding LIVEKIT data several times,
   3.416 +# until timeouted or until data is found
   3.417 +# $1 = timeout
   3.418 +# $2 = data directory target (mount here)
   3.419 +#
   3.420 +find_data()
   3.421 +{
   3.422 +   debug_log "find_data" "$*"
   3.423 +
   3.424 +   local DATA FROM
   3.425 +
   3.426 +   if [ "$(cmdline_value ip)" != "" ]; then
   3.427 +      download_data_pxe "$2"
   3.428 +      return
   3.429 +   fi
   3.430 +
   3.431 +   FROM="$(cmdline_value from)"
   3.432 +   if [ "$FROM" = "" ]; then FROM="$LIVEKITNAME"; fi
   3.433 +
   3.434 +   echo_green_star >&2
   3.435 +   echo -n "Looking for $LIVEKITNAME data in /$FROM .." | tr -s "/" >&2
   3.436 +   for timeout in $(seq 1 $1); do
   3.437 +      echo -n "." >&2
   3.438 +      DATA="$(find_data_try "$2" "$FROM")"
   3.439 +      if [ "$DATA" != "" ]; then
   3.440 +         echo "" >&2
   3.441 +         echo "* Found on $(mounted_device "$2")" >&2
   3.442 +         echo "$DATA"
   3.443 +         return
   3.444 +      fi
   3.445 +      sleep 1
   3.446 +   done
   3.447 +   echo "" >&2
   3.448 +
   3.449 +   if [ "$DATA" = "" ]; then
   3.450 +      fatal "$LIVEKITNAME data not found"
   3.451 +   fi
   3.452 +
   3.453 +}
   3.454 +
   3.455 +# Activate persistent changes
   3.456 +# $1 = data directory
   3.457 +# $2 = target changes directory
   3.458 +#
   3.459 +persistent_changes()
   3.460 +{
   3.461 +   debug_log "persistent_changes" "$*"
   3.462 +
   3.463 +   local CHANGES T1 T2
   3.464 +
   3.465 +   CHANGES="$1/$(basename "$2")"
   3.466 +   T1="$CHANGES/.empty"
   3.467 +   T2="$T1"2
   3.468 +
   3.469 +   # Setup the directory anyway, it will be used in all cases
   3.470 +   mkdir -p "$2"
   3.471 +
   3.472 +   # If persistent changes are not requested, end here
   3.473 +   if grep -vq perch /proc/cmdline; then
   3.474 +      return
   3.475 +   fi
   3.476 +
   3.477 +   # check if changes directory exists and is writable
   3.478 +   touch "$T1" 2>/dev/null && rm -f "$T1" 2>/dev/null
   3.479 +
   3.480 +   # if not, simply return back
   3.481 +   if [ $? -ne 0 ]; then
   3.482 +      echo "* Persistent changes not writable or not used"
   3.483 +      return
   3.484 +   fi
   3.485 +
   3.486 +   echo_green_star
   3.487 +   echo "Testing persistent changes for posix compatibility"
   3.488 +   touch "$T1" && ln -sf "$T1" "$T2" 2>/dev/null && \
   3.489 +   chmod +x "$T1" 2>/dev/null && test -x "$T1" && \
   3.490 +   chmod -x "$T1" 2>/dev/null && test ! -x "$T1" && \
   3.491 +   rm "$T1" "$T2" 2>/dev/null
   3.492 +
   3.493 +   if [ $? -ne 0 ]; then
   3.494 +      echo "* Activating dynamic sized storage for persistent changes"
   3.495 +      rm "$T1" "$T2" 2>/dev/null
   3.496 +
   3.497 +      mount.dynfilefs "$CHANGES/changes.dat" 4000 "$2"
   3.498 +      if [ "$(device_bestfs "$2/loop.fs" | tr -d " ")" = "-t" ]; then
   3.499 +         mke2fs -F "$2/loop.fs" >/dev/null
   3.500 +      fi
   3.501 +      mount -o loop,sync "$2/loop.fs" "$2"
   3.502 +      rmdir "$2/lost+found" 2>/dev/null
   3.503 +   else
   3.504 +      echo "* Activating native persistent changes"
   3.505 +      mount --bind "$CHANGES" "$2"
   3.506 +   fi
   3.507 +}
   3.508 +
   3.509 +# Copy content of rootcopy directory to union
   3.510 +# $1 = data directory
   3.511 +# $2 = union directory
   3.512 +copy_rootcopy_content()
   3.513 +{
   3.514 +   debug_log "copy_rootcopy_content" "$*"
   3.515 +
   3.516 +   if [ "$(ls -1 "$1/rootcopy/" 2>/dev/null)" != "" ]; then
   3.517 +      echo_green_star
   3.518 +      echo "Copying content of rootcopy directory..."
   3.519 +      cp -a "$1"/rootcopy/* "$2"
   3.520 +   fi
   3.521 +}
   3.522 +
   3.523 +# Copy data to RAM if requested
   3.524 +# $1 = live data directory
   3.525 +# $2 = changes directory
   3.526 +#
   3.527 +copy_to_ram()
   3.528 +{
   3.529 +   debug_log "copy_to_ram" "$*"
   3.530 +
   3.531 +   local MDIR MDEV RAM CHANGES
   3.532 +
   3.533 +   if grep -vq toram /proc/cmdline; then
   3.534 +      echo "$1"
   3.535 +      return
   3.536 +   fi
   3.537 +
   3.538 +   echo "* Copying $LIVEKITNAME data to RAM..." >&2
   3.539 +   RAM="$(dirname "$2")"/toram
   3.540 +   mkdir  -p "$RAM"
   3.541 +   cp -a "$1"/* "$RAM"
   3.542 +   echo "$RAM"
   3.543 +
   3.544 +   MDIR="$(mounted_dir "$1")"
   3.545 +   MDEV="$(mounted_device "$1")"
   3.546 +   MDEV="$(losetup $MDEV 2>/dev/null | cut -d " " -f 3)"
   3.547 +   umount "$MDIR" 2>/dev/null
   3.548 +
   3.549 +   if [ "$MDEV" ]; then # iso was mounted here, try to unmount the FS it resides on too
   3.550 +      MDEV="$(mounted_device "$MDEV")"
   3.551 +      umount "$MDEV" 2>/dev/null
   3.552 +   fi
   3.553 +}
   3.554 +
   3.555 +# load filter
   3.556 +#
   3.557 +filter_load()
   3.558 +{
   3.559 +   local FILTER
   3.560 +   FILTER=$(cmdline_value load)
   3.561 +   if [ "$FILTER" = "" ]; then
   3.562 +      cat -
   3.563 +   else
   3.564 +      cat - | egrep "$FILTER"
   3.565 +   fi
   3.566 +}
   3.567 +
   3.568 +# noload filter
   3.569 +#
   3.570 +filter_noload()
   3.571 +{
   3.572 +   local FILTER
   3.573 +   FILTER=$(cmdline_value load)
   3.574 +   if [ "$FILTER" = "" ]; then
   3.575 +      cat -
   3.576 +   else
   3.577 +      cat - | egrep -v "$FILTER"
   3.578 +   fi
   3.579 +}
   3.580 +
   3.581 +# sort modules by number even if they are in subdirectory
   3.582 +#
   3.583 +sortmod()
   3.584 +{
   3.585 +   cat - | sed -r "s,(.*/(.*)),\\2:\\1," | sort -n | cut -d : -f 2-
   3.586 +}
   3.587 +
   3.588 +# Mount squashfs filesystem bundles
   3.589 +# and add them to union
   3.590 +# $1 = directory where to search for bundles
   3.591 +# $2 = directory where to mount bundles
   3.592 +# $3 = directory where union is mounted
   3.593 +#
   3.594 +union_append_bundles()
   3.595 +{
   3.596 +   debug_log "union_append_bundles" "$*"
   3.597 +
   3.598 +   local BUN
   3.599 +
   3.600 +   echo_green_star
   3.601 +   echo "Adding bundles to union"
   3.602 +   ( ls -1 "$1" | sort -n ; cd "$1" ; find base/ 2>/dev/null ; find modules/ 2>/dev/null | sortmod | filter_load) | grep '[.]'$BEXT'$' | filter_noload | while read BUNDLE; do
   3.603 +      echo "* $BUNDLE"
   3.604 +      BUN="$(basename "$BUNDLE")"
   3.605 +      mkdir -p "$2/$BUN"
   3.606 +      mount -o loop -t squashfs "$1/$BUNDLE" "$2/$BUN"
   3.607 +      mount -n -o remount,add:1:$2/$BUN=rr aufs $3
   3.608 +   done
   3.609 +}
   3.610 +
   3.611 +# Create empty fstab properly
   3.612 +# $1 = root directory
   3.613 +#
   3.614 +fstab_create()
   3.615 +{
   3.616 +   debug_log "fstab_create" "$*"
   3.617 +
   3.618 +   local FSTAB
   3.619 +   FSTAB="$1/etc/fstab"
   3.620 +   echo aufs / aufs defaults 0 0 > $FSTAB
   3.621 +   echo proc /proc proc defaults 0 0 >> $FSTAB
   3.622 +   echo sysfs /sys sysfs defaults 0 0 >> $FSTAB
   3.623 +   echo devpts /dev/pts devpts gid=5,mode=620 0 0 >> $FSTAB
   3.624 +   echo tmpfs /dev/shm tmpfs defaults 0 0 >> $FSTAB
   3.625 +}
   3.626 +
   3.627 +
   3.628 +# Change root and execute init
   3.629 +# $1 = where to change root
   3.630 +#
   3.631 +change_root()
   3.632 +{
   3.633 +   debug_log "change_root" "$*"
   3.634 +
   3.635 +   umount /proc
   3.636 +   umount /sys
   3.637 +
   3.638 +   cd "$1"
   3.639 +
   3.640 +   # make sure important device files and directories are in union
   3.641 +   mkdir -p boot dev proc sys tmp mnt run
   3.642 +   chmod 1777 tmp
   3.643 +   if [ ! -e dev/console ]; then mknod dev/console c 5 1; fi
   3.644 +   if [ ! -e dev/tty ]; then mknod dev/tty c 5 0; fi
   3.645 +   if [ ! -e dev/tty0 ]; then mknod dev/tty0 c 4 0; fi
   3.646 +   if [ ! -e dev/tty1 ]; then mknod dev/tty1 c 4 1; fi
   3.647 +   if [ ! -e dev/null ]; then mknod dev/null c 1 3; fi
   3.648 +   if [ ! -e sbin/fsck.aufs ]; then ln -s /bin/true sbin/fsck.aufs; fi
   3.649 +
   3.650 +   # find chroot and init
   3.651 +   if [ -x bin/chroot ]; then  CHROOT=bin/chroot; fi
   3.652 +   if [ -x sbin/chroot ]; then  CHROOT=sbin/chroot; fi
   3.653 +   if [ -x usr/bin/chroot ]; then  CHROOT=usr/bin/chroot; fi
   3.654 +   if [ -x usr/sbin/chroot ]; then CHROOT=usr/sbin/chroot; fi
   3.655 +   if [ "$CHROOT" = "" ]; then fatal "Can't find executable chroot command"; fi
   3.656 +
   3.657 +   if [ -x bin/init ]; then INIT=bin/init; fi
   3.658 +   if [ -x sbin/init ]; then INIT=sbin/init; fi
   3.659 +   if [ "$INIT" = "" ]; then fatal "Can't find executable init command"; fi
   3.660 +
   3.661 +   mkdir -p mnt/live
   3.662 +   mount -n -o remount,ro aufs .
   3.663 +   pivot_root . mnt/live
   3.664 +   exec $CHROOT . $INIT < dev/console > dev/console 2>&1
   3.665 +}