#!/bin/bash
# initrd_create:  make initrd rootdisk by using busybox
#
# Author:	  Tomas M. <http://www.linux-live.org>

. /etc/linux-live/config || exit 1

# You may override some variables by your own config
[ -f $HOME/.linux-live/config  ] && . $HOME/.linux-live/config

if [ "$1" != "" ]; then
   LIVECDNAME="$1"
fi

if [ "$2" != "" ]; then
   ADDLOCALE="$2"
fi

if [ "$3" != "" ]; then
   ROOT="$3"
fi

# rcopy is a recursive cp, which copies also symlink's real source
# $1 = source (may be a regular file or symlink)
# $2 = target PARENT
# $3 = optional PREFIX to strip from $1
#
rcopy()
{
   debug "rcopy $1 $2"
   CWD=$(pwd)
   if [ "$ROOT" = "" ]; then cd /; else cd $ROOT; fi
   SOURCE="./${1:${#ROOT}}"
   echo $SOURCE
   DEST="$2"
   if [ -L "$SOURCE" ]; then
      REALPATH=$(readlink -f "$SOURCE")
      cp --parent -a "$REALPATH" "$DEST"
      ln -sf "$REALPATH" "$DEST/$SOURCE"
   else
      if [ "$3" ]; then
          tar ${3:+-C "$3"} -cf - "${1#$3/}" | tar -C "$DEST" -xf -
      else
          cp --parent -a "$SOURCE" "$DEST"
      fi
   fi
   if [ "$?" -ne 0 ]; then
      echo ""
      echo "---------------------------"
      echo "Error occured while trying to copy \"$SOURCE\""
      echo "Possible reason: not enough free space in initrd OR source doesn't exist."
      echo "If space is your issue, see '.config' file to increase size of initrd."
      echo "If source file doesn't exist, it's a big problem. See DOC/requirements.txt"
      echo "---------------------------"
      exit 1
   fi
   cd $CWD
}

# copy file/dir only if it exists, else skip with no error
# $1 = source (may not exist)
# $2 = target PARENT
# $3 = optional PREFIX to strip from $1
#
rcopy_ex()
{
   debug "rcopy_ex $1 $2"
   if [ -a "$1" ]; then
      rcopy "$1" "$2" "$3"
   fi
}

debug()
{
   echo "$@" >>$DEBUG
   return 0
}

##################################################
# Create INITRD image now:

MOUNTDIR=$(mktemp -d || echo /tmp/initrd_mountdir_$$)
INITRD_TREE=$(mktemp -d || echo /tmp/initrd_tree_$$)
INITRDIMG=initrd

if [ ! -d $ROOT/$LMK ]; then
   echo "cannot find your kernel modules (*.ko) in $ROOT/$LMK"
   exit 1
fi

debug "creating empty directory $INITRD_TREE"
rm -Rf $INITRD_TREE
mkdir $INITRD_TREE

debug "creating directories"
mkdir -p $INITRD_TREE/{etc,dev,bin,mnt,proc,lib,sys,tmp,var/log}

debug "creating some essential devices in rootdisk"
mknod $INITRD_TREE/dev/console c 5 1
mknod $INITRD_TREE/dev/fb0 c 29 0
mknod $INITRD_TREE/dev/null c 1 3
mknod $INITRD_TREE/dev/zero c 1 5
mknod $INITRD_TREE/dev/ram b 1 1
mknod $INITRD_TREE/dev/systty c 4 0
mknod $INITRD_TREE/dev/tty c 5 0
mknod $INITRD_TREE/dev/fuse c 10 229
for i in 1 2 3 4 5 6; do
  mknod $INITRD_TREE/dev/tty$i c 4 $i;
done

debug "copying files to the rootdisk"
touch $INITRD_TREE/etc/{m,fs}tab
cat liblinuxlive | sed -r 's/^LIVECDNAME=.*/LIVECDNAME="'$LIVECDNAME'"/' > $INITRD_TREE/liblinuxlive
cp {linuxrc,cleanup} $INITRD_TREE
chmod ago+x $INITRD_TREE/{linuxrc,cleanup}

#cp -a bootsplash/* $INITRD_TREE

# handle the fuse filesystems here
#
cp -a fuse/* $INITRD_TREE
cp -a httpfs/* $INITRD_TREE

if [ "$USEPOSIXOVL" = "yes" ]; then
   cp -a posixovl/* $INITRD_TREE
fi

if [ "$USENTFS3G" = "yes" ]; then
   cp -a ntfs-3g/* $INITRD_TREE
fi

cp -a rootfs/* $INITRD_TREE

# build links to busybox's functions from busybox's own help text
for i in $(rootfs/bin/busybox --help | grep -v Copyright | grep , | tr , " "); do
   ln -s busybox $INITRD_TREE/bin/$i
done

ln -sf bin $INITRD_TREE/sbin

# necessary modules and dependency files
mkdir -p $INITRD_TREE/$LMK/kernel/fs
rcopy $ROOT/$LMK/kernel/fs/aufs $INITRD_TREE
rcopy $ROOT/$LMK/kernel/fs/squashfs $INITRD_TREE

# copy filesystem modules, if not directly copied into kernel
rcopy_ex $ROOT/$LMK/kernel/lib/zlib_inflate $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/zlib_deflate $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/block/loop.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/fuse/fuse.* $INITRD_TREE 2>>$DEBUG

rcopy_ex $ROOT/$LMK/kernel/fs/isofs $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/fat $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/vfat $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/ntfs $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/jbd $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/mbcache.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/exportfs $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/ext3 $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/reiserfs $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/fs/xfs $INITRD_TREE 2>>$DEBUG

# add language support for filesystems
rcopy_ex $ROOT/$LMK/kernel/fs/nls $INITRD_TREE 2>>$DEBUG

# usb modules
rcopy_ex $ROOT/$LMK/kernel/drivers/usb/storage $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/usb/host/ehci-hcd.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/usb/host/ohci-hcd.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/usb/host/uhci-hcd.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/usb/core $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/hid $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/input/ff-memless.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/crc16.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/crc7.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/crc-ccit.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/crc-itu-t.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/crc-t10dif.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/lib/libcrc32c.* $INITRD_TREE 2>>$DEBUG

# pci modules
rcopy_ex $ROOT/$LMK/kernel/drivers/scsi $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/acpi $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/cdrom $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/ide $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/ata $INITRD_TREE 2>>$DEBUG

# pcmcia modules
rcopy_ex $ROOT/$LMK/kernel/drivers/pcmcia/pcmcia_core.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/pcmcia/pcmcia.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/pcmcia/rsrc_nonstatic.* $INITRD_TREE 2>>$DEBUG
rcopy_ex $ROOT/$LMK/kernel/drivers/pcmcia/yenta_socket.* $INITRD_TREE 2>>$DEBUG

# network modules
for mod in $(list_network_drivers); do
   cat $ROOT/$LMK/modules.dep | fgrep /$mod.ko | while read LINE; do
      for dep in $(echo $LINE | tr -d ":"); do
         rcopy_ex $ROOT/$dep $INITRD_TREE 2>>$DEBUG
      done
   done
done

if [ "$ADDLOCALE" != "" ]; then
   . ./addlocaleslib
   debug "copylocales $ROOT/ $INITRD_TREE $ADDLOCALE"
   copylocales $ROOT/ $INITRD_TREE $ADDLOCALE
fi

debug "unpacking all kernel modules for initrd"
find $INITRD_TREE -noleaf -name "*.ko.gz" | xargs -r gunzip

debug "generating module dependency files"
depmod -b $INITRD_TREE $KERNEL

debug "compressing usr in initrd"
mksquashfs $INITRD_TREE/usr $INITRD_TREE/usr.lzm >/dev/null 2>&1
chmod ago-x $INITRD_TREE/usr.lzm
rm -Rf $INITRD_TREE/usr/*

debug "compressing net in initrd"
mksquashfs $INITRD_TREE/$LMK/kernel/drivers $INITRD_TREE/drivers.lzm >/dev/null 2>&1
chmod ago-x $INITRD_TREE/drivers.lzm
#preserve loop.ko from beeing removed
mv $INITRD_TREE/$LMK/kernel/drivers/block $INITRD_TREE/$LMK/kernel
rm -Rf $INITRD_TREE/$LMK/kernel/drivers/*
mv $INITRD_TREE/$LMK/kernel/block $INITRD_TREE/$LMK/kernel/drivers

debug "creating empty directory $MOUNTDIR"
rm -Rf $MOUNTDIR
mkdir $MOUNTDIR

debug "copying content of $INITRD_TREE to $MOUNTDIR"
cp -R --preserve $INITRD_TREE/* $MOUNTDIR 2>/dev/null
if [ $? -ne 0 ]; then
   debug "error copying data to mounted initrd. Increase RAM0SIZE"
   echo "Not enough free space in initrd. Edit .config and increase RAM0SIZE !"
   exit 1
fi

debug "building $MOUNTDIR"
CUR=$(pwd)
cd $MOUNTDIR
cp linuxrc init
find . | cpio -H newc -o > "$CUR/$INITRDIMG"
cd $CUR

debug "gzipping $INITRDIMG"
gzip --best $INITRDIMG

debug "deleting directory $MOUNTDIR"
rm -rf $MOUNTDIR

debug "deleting directory $INITRD_TREE"
rm -Rf $INITRD_TREE

debug "$INITRDIMG.gz created"
