#!/bin/sh # Functions library :: for Linux Live Kit scripts # Author: Tomas M. # # ================================================================= # debug and output functions # ================================================================= debug_start() { if grep -q debug /proc/cmdline; then DEBUG_IS_ENABLED=1 set -x else DEBUG_IS_ENABLED= fi } 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 setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1' 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 setsid sh -c 'exec sh < /dev/tty1 >/dev/tty1 2>&1' } # get value of commandline parameter $1 # $1 = parameter to search for # cmdline_value() { cat /proc/cmdline | egrep -o "(^|[[:space:]])$1=[^[:space:]]+" | tr -d " " | cut -d "=" -f 2- | tail -n 1 } # get value of config parameter $2 # $1 = config file name # $2 = parameter to search for # config_value() { cat $1 | egrep -o "(^|[[:space:]])$2=[^[:space:]]+" | tr -d " " | cut -d "=" -f 2- | tail -n 1 } # 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 1024K -always-use-fragments $3 $4 $5 $6 $7 $8 $9 >/dev/null } # Move entire initramfs tree to tmpfs 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 tmpfs -o size="100%" tmpfs $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 "init_proc_sysfs" "$*" mkdir -p /proc /sys /etc $MEMORY 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 } # modprobe_cloud() { modprobe virtio 2>/dev/null modprobe virtio_ring 2>/dev/null modprobe virtio_pci 2>/dev/null modprobe virtio_blk 2>/dev/null modprobe virtio_scsi 2>/dev/null modprobe vmw_pvscsi 2>/dev/null } # modprobe all modules found in initial ramdisk # $1 = -e for match, -v for negative match # $2 = regex pattern # modprobe_everything() { debug_log "modprobe_everything" "$*" echo_green_star >&2 echo "Probing for hardware" >&2 find /lib/modules/ | fgrep .ko | egrep $1 $2 | sed -r "s:^.*/|[.]ko\$::g" | xargs -n 1 modprobe 2>/dev/null refresh_devs } refresh_devs() { debug_log "refresh_devs" "$*" if [ -r /proc/sys/kernel/hotplug ]; then echo /sbin/mdev >/proc/sys/kernel/hotplug fi mdev -s } # make sure some devices are there init_devs() { debug_log "init_devs" "$*" modprobe zram 2>/dev/null modprobe loop 2>/dev/null modprobe squashfs 2>/dev/null modprobe fuse 2>/dev/null refresh_devs } # 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 if available" if [ -r /sys/block/zram0/disksize ]; then echo 536870912 >/sys/block/zram0/disksize # 512MB mkswap /dev/zram0 >/dev/null swapon /dev/zram0 echo 100 >/proc/sys/vm/swappiness fi } aufs_is_supported() { cat /proc/filesystems | grep aufs } # load the AUFS kernel driver. If not found, # load overlayfs instead. # init_aufs() { debug_log "init_aufs" "$*" modprobe aufs 2>/dev/null if ! aufs_is_supported >/dev/null; then modprobe overlay 2>/dev/null fi refresh_devs } # Setup empty aufs union, or create overlayfs union # $1 = changes directory (ramfs or persistent changes) # $2 = union directory where to mount the union # $3 = bundles directory # init_union() { debug_log "init_union" "$*" mkdir -p "$1" mkdir -p "$2" if aufs_is_supported >/dev/null; then echo_green_star echo "Setting up empty union using aufs" mount -t aufs -o xino="/.xino",trunc_xino,br="$1" aufs "$2" else echo_green_star echo "Setting up union using overlayfs" mkdir -p "$1/changes" mkdir -p "$1/workdir" mount -t overlay overlay -o lowerdir=$(find "$3" -mindepth 1 -maxdepth 1 | sortmod | tac | tr '\n' ':' | sed -r 's/:$//'),upperdir=$1/changes,workdir=$1/workdir $2 fi } # Return device mounted for given directory # $1 = directory # mounted_device() { debug_log "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 } # Return mounted dir for given directory # $1 = directory # mounted_dir() { debug_log "mounted_dir" "$*" local MNT MNT="$1" while [ "$MNT" != "/" -a "$MNT" != "." -a "$MNT" != "" ]; do if mountpoint -q "$MNT" 2>/dev/null; then echo "$MNT" return fi MNT="$(dirname "$MNT")" done } # Get device tag. # $1 = device # $2 = tag name, such as TYPE, LABEL, UUID, etc # device_tag() { blkid -s $2 "$1" | sed -r "s/^[^=]+=//" | tr -d '"' } # Make sure to mount FAT12/16/32 using vfat # in order to support long filenames # $1 = device # $2 = prefix to add, like -t # device_bestfs() { debug_log "device_bestfs" "$*" local FS FS="$(device_tag "$1" TYPE | tr [A-Z] [a-z])" if [ "$FS" = "msdos" -o "$FS" = "fat" -o "$FS" = "vfat" ]; then FS="vfat" elif [ "$FS" = "ntfs" ]; then FS="ntfs-3g" fi if [ "$2" != "" ]; then echo -n "$2" fi echo "$FS" } # Filesystem options for initial mount # $1.. = filesystem # fs_options() { debug_log "fs_options" "$*" if [ "$1" != "ntfs-3g" ]; then echo -n "-t $1 " fi echo -n "-o rw" if [ "$1" = "vfat" ]; then echo ",check=s,shortname=mixed,iocharset=utf8" fi } # Mount command for given filesystem # $1.. = filesystem # mount_command() { debug_log "mount_command" "$*" if [ "$1" = "ntfs-3g" ]; then echo "@mount.ntfs-3g" else echo "mount" fi } # echo first network device known at the moment of calling, eg. eth0 # network_device() { debug_log "network_device" "$*" cat /proc/net/dev | grep : | grep -v lo: | cut -d : -f 1 | tr -d " " | head -n 1 } # Modprobe network kernel modules until a working driver is found. # These drivers are (or used to be) probed in Slackware's initrd. # The function returns the first device found, yet it doesn't have # to be a working one, eg. if the computer has two network interfaces # and ethernet cable is plugged only to one of them. # init_network_dev() { debug_log "init_network_dev" "$*" local MODULE ETH for MODULE in 3c59x acenic e1000 e1000e e100 epic100 hp100 ne2k-pci \ pcnet32 8139too 8139cp tulip via-rhine r8169 atl1e yellowfin tg3 \ dl2k ns83820 atl1 b44 bnx2 skge sky2 tulip forcedeth sb1000 sis900 \ vmxnet3 virtio_net; do modprobe $MODULE 2>/dev/null ETH="$(network_device)" if [ "$ETH" != "" ]; then echo $ETH return 0 fi rmmod $MODULE 2>/dev/null done # If we are here, none of the above specified modules worked. # As a last chance, try to modprobe everything else modprobe_everything -e /drivers/net/ echo $(network_device) } # Initialize network IP address # either static from ip=bootparameter, or from DHCP # init_network_ip() { debug_log "init_network_ip" "$*" local IP ETH SCRIPT CLIENT SERVER GW MASK SCRIPT=/tmp/dhcpscript ETH=$(init_network_dev) IP=$(cmdline_value ip) echo "* Setting up network" >&2 if [ "$IP" != "" ]; then # set IP address as given by boot paramter echo "$IP" | while IFS=":" read CLIENT SERVER GW MASK; do ifconfig $ETH "$CLIENT" netmask "$MASK" route add default gw "$GW" echo nameserver "$GW" >>/etc/resolv.conf echo nameserver "$SERVER" >>/etc/resolv.conf done else # if client ip is unknown, try to get a DHCP lease ifconfig $ETH up echo -e '#!/bin/sh\nif [ "$1" != "bound" ]; then exit; fi\nifconfig $interface $ip netmask $subnet\nroute add default gw $router\necho nameserver $dns >>/etc/resolv.conf' >$SCRIPT chmod a+x $SCRIPT udhcpc -i $ETH -n -s $SCRIPT -q >/dev/null fi } # Mount data from http using httpfs # $1 = from URL # $2 = target mount_data_http() { debug_log "mount_data_http" "$*" local CACHE echo_green_star >&2 echo "Load data from $1" >&2 CACHE=$(cmdline_value cache | sed -r "s/[^0-9]//g" | sed -r "s/^0+//g") if [ "$CACHE" != "" ]; then CACHE="-C /tmp/httpfs.cache -S "$(($CACHE * 1024 * 1024)) fi init_network_ip if [ "$(network_device)" != "" ]; then echo "* Mounting remote file..." >&2 mkdir -p "$2" @mount.httpfs2 -r 9999 -t 5 $CACHE -c /dev/null "$1" "$2" -o ro >/dev/null 2>/dev/null mount -o loop "$2"/* "$2" # self mount echo "$2/$LIVEKITNAME" fi } # stdin = files to get # $1 = server # $2 = destination directory # tftp_mget() { while read FNAME; do echo "* $FNAME ..." >&2 tftp -b 1486 -g -r "$FNAME" -l "$2/$FNAME" "$1" done } # Download data from tftp # $1 = target (store downloaded files there) # download_data_pxe() { debug_log "download_data_pxe" "$*" local IP CMD CLIENT SERVER GW MASK PORT PROTOCOL JOBS mkdir -p "$1/$LIVEKITNAME" IP="$(cmdline_value ip)" echo "$IP" | while IFS=":" read CLIENT SERVER GW MASK PORT; do echo_green_star >&2 echo "Contacting PXE server $SERVER" >&2 if [ "$PORT" = "" ]; then PORT="7529"; fi init_network_ip echo "* Downloading PXE file list" >&2 PROTOCOL=http wget -q -O "$1/PXEFILELIST" "http://$SERVER:$PORT/PXEFILELIST?$(uname -r):$(uname -m)" if [ $? -ne 0 ]; then echo "Error downloading from http://$SERVER:$PORT, trying TFTP" >&2 PROTOCOL=tftp echo PXEFILELIST | tftp_mget "$SERVER" "$1" fi echo "* Downloading files from the list" >&2 if [ "$PROTOCOL" = "http" ]; then cat "$1/PXEFILELIST" | while read FILE; do wget -O "$1/$LIVEKITNAME/$(basename $FILE)" "http://$SERVER:$PORT/$FILE" done else JOBS=3 for i in $(seq 1 $JOBS); do awk "NR % $JOBS == $i-1" "$1/PXEFILELIST" | tftp_mget "$SERVER" "$1/$LIVEKITNAME" & done wait fi done echo "$1/$LIVEKITNAME" } # Find LIVEKIT data by mounting all devices # If found, keep mounted, else unmount # $1 = data directory target (mount here) # $2 = data directory which contains compressed bundles # find_data_try() { debug_log "find_data_try" "$*" local DEVICE FS FROM OPTIONS MOUNT mkdir -p "$1" # patch from Jeff Baitis: Problem is that livekitlib's blkid command cannot detect /dev/nvme devices. blkid /dev/* | sort | cut -d: -f 1 | grep -E -v "/loop|/ram|/zram" | while read DEVICE; do #blkid | sort | cut -d: -f 1 | grep -E -v "/loop|/ram|/zram" | while read DEVICE; do FROM="$2" FS="$(device_bestfs "$DEVICE")" OPTIONS="$(fs_options $FS)" MOUNT="$(mount_command $FS)" $MOUNT "$DEVICE" "$1" $OPTIONS 2>/dev/null # if the FROM parameter is actual file, mount it again as loop (eg. iso) if [ -f "$1/$FROM" ]; then mkdir -p "$1/../iso" mount -o loop,ro "$1/$FROM" "$1/../iso" 2>/dev/null FROM="../iso/$LIVEKITNAME" fi # search for bundles in the mounted directory if [ "$(find "$1/$FROM" -maxdepth 1 -name "*.$BEXT" 2>/dev/null)" != "" ]; then # we found at least one bundle/module here echo "$1/$FROM" | tr -s "/" | sed -r "s:/[^/]+/[.][.]/:/:g" return fi # unmount twice, since there could be mounted ISO as loop too. If not, it doesn't hurt umount "$1" 2>/dev/null 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 FROM FROM="$(cmdline_value from)" # boot parameter specified as from=http://server.com/file.iso if [ "$(echo $FROM | grep 'http://')" != "" ]; then mount_data_http "$FROM" "$2" return fi # if we got IP address as boot parameter, it means we booted over PXE if [ "$(cmdline_value ip)" != "" ]; then download_data_pxe "$2" return fi if [ "$FROM" = "" ]; then FROM="$LIVEKITNAME"; fi echo_green_star >&2 echo -n "Looking for $LIVEKITNAME data in /$FROM .." | tr -s "/" >&2 for timeout in $(seq 1 $1); do echo -n "." >&2 refresh_devs DATA="$(find_data_try "$2" "$FROM")" if [ "$DATA" != "" ]; then echo "" >&2 echo "* Found on $(mounted_device "$2")" >&2 echo "$DATA" return fi sleep 1 done echo "" >&2 } # Check if data is found and exists # $1 = data directory # check_data_found() { if [ "$1" = "" -o ! -d "$1" ]; then fatal "Could not locate $LIVEKITNAME data" fi } # Activate persistent changes # $1 = data directory # $2 = target changes directory # persistent_changes() { debug_log "persistent_changes" "$*" local CHANGES T1 T2 EXISTS CHANGES_SIZE CHANGES="$1/$(basename "$2")" T1="$CHANGES/.empty" T2="$T1"2 # Setup the directory anyway, it will be used in all cases mkdir -p "$2" # If persistent changes are not requested, end here if grep -vq perch /proc/cmdline; then return fi # check if changes directory exists and is writable touch "$T1" 2>/dev/null && rm -f "$T1" 2>/dev/null # if not, simply return back if [ $? -ne 0 ]; then echo "* Persistent changes not writable or not used" return fi echo_green_star echo "Testing persistent changes for posix compatibility" touch "$T1" && ln -sf "$T1" "$T2" 2>/dev/null && chmod +x "$T1" 2>/dev/null && test -x "$T1" && chmod -x "$T1" 2>/dev/null && test ! -x "$T1" && rm "$T1" "$T2" 2>/dev/null if [ $? -eq 0 ]; then echo "* Activating native persistent changes" mount --bind "$CHANGES" "$2" return fi if grep -vq remove_changes /proc/cmdline; then if [ -e "$CHANGES/changes.dat" ]; then echo "* Restoring persistent changes" EXISTS="true" else echo "* Creating new persistent changes" EXISTS="" fi else if [ -f "$CHANGES/changes.dat" ]; then rm -f "$CHANGES/changes.dat" fi echo "* Creating new persistent changes" EXISTS="" fi CHANGES_SIZE=$(cmdline_value changes_size) if [ ! "$CHANGES_SIZE" ]; then @mount.dynfilefs "$CHANGES/changes.dat" 4000 "$2" else @mount.dynfilefs "$CHANGES/changes.dat" $CHANGES_SIZE "$2" fi if [ ! "$EXISTS" ]; then mke2fs -F "$2/loop.fs" >/dev/null 2>&1 fi mount -o loop,sync "$2/loop.fs" "$2" # if test failed at any point, we may have temp files left behind rm "$T1" "$T2" 2>/dev/null rmdir "$2/lost+found" 2>/dev/null } # Copy content of rootcopy directory to union # $1 = data directory # $2 = union directory copy_rootcopy_content() { debug_log "copy_rootcopy_content" "$*" if [ "$(ls -1 "$1/rootcopy/" 2>/dev/null)" != "" ]; then echo_green_star echo "Copying content of rootcopy directory..." cp -a "$1"/rootcopy/* "$2" fi } # Copy data to RAM if requested # $1 = live data directory # $2 = changes directory # copy_to_ram() { debug_log "copy_to_ram" "$*" local MDIR MDEV RAM CHANGES if grep -vq toram /proc/cmdline; then echo "$1" return fi echo "* Copying $LIVEKITNAME data to RAM..." >&2 RAM="$(dirname "$2")"/toram mkdir -p "$RAM" cp -a "$1"/* "$RAM" echo "$RAM" MDIR="$(mounted_dir "$1")" MDEV="$(mounted_device "$1")" MDEV="$(losetup $MDEV 2>/dev/null | cut -d " " -f 3)" umount "$MDIR" 2>/dev/null if [ "$MDEV" ]; then # iso was mounted here, try to unmount the FS it resides on too MDEV="$(mounted_device "$MDEV")" umount "$MDEV" 2>/dev/null fi } # load filter # filter_load() { local FILTER FILTER=$(cmdline_value load) if [ "$FILTER" = "" ]; then cat - else cat - | egrep "$FILTER" fi } # noload filter # filter_noload() { local FILTER FILTER=$(cmdline_value noload) if [ "$FILTER" = "" ]; then cat - else cat - | egrep -v "$FILTER" fi } # sort modules by number even if they are in subdirectory # sortmod() { cat - | sed -r "s,(.*/(.*)),\\2:\\1," | sort -n | cut -d : -f 2- } # Mount squashfs filesystem bundles # $1 = directory where to search for bundles # $2 = directory where to mount bundles mount_bundles() { echo_green_star echo "Mounting bundles" ( ls -1 "$1" | sort -n cd "$1" find modules/ 2>/dev/null | sortmod | filter_load ) | grep '[.]'$BEXT'$' | filter_noload | while read BUNDLE; do echo "* $BUNDLE" BUN="$(basename "$BUNDLE")" mkdir -p "$2/$BUN" mount -o loop,ro -t squashfs "$1/$BUNDLE" "$2/$BUN" done } # Add mounted bundles to aufs union # $1 = directory where bundles are mounted # $2 = directory where union is mounted # union_append_bundles() { debug_log "union_append_bundles" "$*" if aufs_is_supported >/dev/null; then echo_green_star echo "Adding bundles to union" find "$1" -mindepth 1 -maxdepth 1 | sortmod | while read BUNDLE; do mount -o remount,add:1:"$BUNDLE" aufs "$2" done fi } # Create empty fstab properly # $1 = root directory # $2 = directory where boot disk is mounted # fstab_create() { debug_log "fstab_create" "$*" local FSTAB DEVICE FS LABEL BOOTDEVICE OPTS 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 if grep -vq automount /proc/cmdline; then return fi BOOTDEVICE=$(df "$2" | tail -n 1 | cut -d " " -f 1) echo >>$FSTAB # patch from Jeff Baitis: Problem is that livekitlib's blkid command cannot detect /dev/nvme devices. blkid /dev/* | grep -v "^/dev/loop" | grep -v "^/dev/zram" | cut -d: -f 1 | while read DEVICE; do #blkid | grep -v "^/dev/loop" | grep -v "^/dev/zram" | cut -d: -f 1 | while read DEVICE; do FS="$(device_bestfs $DEVICE)" LABEL="$(basename $DEVICE)" OPTS="defaults,noatime,nofail,x-systemd.device-timeout=10" if [ "$FS" != "" -a "$FS" != "swap" -a "$FS" != "squashfs" -a "$DEVICE" != "$BOOTDEVICE" ]; then mkdir -p "$1/media/$LABEL" echo "$DEVICE" "/media/$LABEL" $FS $OPTS 0 0 >>$FSTAB fi done } minios_configure() { debug_log "minios_configure" "$*" local WRITABLE cp /bin/minios-configure $1/ cat /proc/cmdline >$1/cmdline touch "$2/$LIVEKITNAME/.empty" 2>/dev/null && rm -f "$2/$LIVEKITNAME/.empty" 2>/dev/null if [ $? -ne 0 ]; then WRITABLE="false" #echo "* Directory $2/$LIVEKITNAME not writable" else WRITABLE="true" if [ -d $2/$LIVEKITNAME ]; then if [ -f $2/$LIVEKITNAME/$LIVEKITNAME.conf ] && [ -f $1/etc/$LIVEKITNAME.conf ]; then if [ "$2/$LIVEKITNAME/$LIVEKITNAME.conf" -nt "$1/etc/$LIVEKITNAME.conf" ]; then cp -fp $2/$LIVEKITNAME/$LIVEKITNAME.conf $1/etc/$LIVEKITNAME.conf elif [ "$2/$LIVEKITNAME/$LIVEKITNAME.conf" -ot "$1/etc/$LIVEKITNAME.conf" ]; then cp -fp $1/etc/$LIVEKITNAME.conf $2/$LIVEKITNAME/$LIVEKITNAME.conf fi elif [ -f $2/$LIVEKITNAME/$LIVEKITNAME.conf ]; then cp -fp $2/$LIVEKITNAME/$LIVEKITNAME.conf $1/etc/$LIVEKITNAME.conf elif [ -f $1/etc/$LIVEKITNAME.conf ]; then cp -fp $1/etc/$LIVEKITNAME.conf $2/$LIVEKITNAME/$LIVEKITNAME.conf fi fi fi echo "LIVEKITNAME=$LIVEKITNAME" >$1/livekit.conf if grep -q minios_modules /proc/cmdline; then cp /opt/minios-modules.tar.xz $1/minios-modules.tar.xz fi chroot $1 /bin/bash -c "/minios-configure" >/dev/null 2>&1 if [ "$WRITABLE" = "true" ]; then if [ -f $1/etc/$LIVEKITNAME.conf ]; then cp -fp $1/etc/$LIVEKITNAME.conf $2/$LIVEKITNAME/$LIVEKITNAME.conf fi fi rm -f $1/cmdline mv -f $1/minios-configure $1/usr/bin/minios-configure chmod 755 $1/usr/bin/minios-configure rm -f $1/livekit.conf } # Change root and execute init # $1 = where to change root # change_root() { debug_log "change_root" "$*" # if we are booting over httpfs, we need to copyup some files so they are # accessible on union without any further lookup down, else httpfs locks if [ "$(network_device)" != "" ]; then touch "/net.up.flag" touch "$1/etc/resolv.conf" touch "$1/etc/hosts" touch "$1/etc/gai.conf" fi umount /proc umount /sys cd "$1" # make sure important device files and directories are in union mkdir -p boot dev proc sys tmp media mnt run chmod 1777 tmp if [ ! -e dev/console ]; then mknod dev/console c 5 1; fi if [ ! -e dev/tty ]; then mknod dev/tty c 5 0; fi if [ ! -e dev/tty0 ]; then mknod dev/tty0 c 4 0; fi if [ ! -e dev/tty1 ]; then mknod dev/tty1 c 4 1; fi if [ ! -e dev/null ]; then mknod dev/null c 1 3; fi if [ ! -e sbin/fsck.aufs ]; then ln -s /bin/true sbin/fsck.aufs; fi # find chroot and init if [ -x bin/chroot -o -L bin/chroot ]; then CHROOT=bin/chroot; fi if [ -x sbin/chroot -o -L sbin/chroot ]; then CHROOT=sbin/chroot; fi if [ -x usr/bin/chroot -o -L usr/bin/chroot ]; then CHROOT=usr/bin/chroot; fi if [ -x usr/sbin/chroot -o -L usr/sbin/chroot ]; then CHROOT=usr/sbin/chroot; fi if [ "$CHROOT" = "" ]; then fatal "Can't find executable chroot command"; fi if [ -x bin/init -o -L bin/init ]; then INIT=bin/init; fi if [ -x sbin/init -o -L sbin/init ]; then INIT=sbin/init; fi if [ "$INIT" = "" ]; then fatal "Can't find executable init command"; fi mkdir -p run mount -t tmpfs tmpfs run mkdir -p run/initramfs mount -n -o remount,ro aufs . pivot_root . run/initramfs exec $CHROOT . $INIT dev/console 2>&1 }