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

. ../config || exit 1

# rcopy is a recursive cp, which copies also symlink's real source
# $1 = source (may be a regular file or symlink)
# $2 = target PARENT
#
rcopy()
{
   if [ -L "$1" ]; then
      REALPATH="`readlink -f \"$1\"`"
      cp --parent -R "$REALPATH" "$2"
      ln -sf "$REALPATH" "$2/$1"
   else
      cp --parent -R "$1" "$2"
   fi
   if [ "$?" -ne 0 ]; then
      echo "---------------------------"
      echo "Error occured while trying to copy \"$1\" to \"$2\""
      echo "nevertheless your LiveCD may still work."
      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 "---------------------------"
   fi
}

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

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

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

MOUNTDIR=/tmp/initrd_mountdir_$$
INITRD_TREE=/tmp/initrd_tree_$$

if [ ! -d "kernel-modules/$KERNEL" ]; then
   echo "The directory `pwd`/kernel-modules/$KERNEL doesn't exist."
   echo "Please create it and copy squashfs.ko and unionfs.ko modules"
   echo "for your kernel ($KERNEL) to this directory."
   exit 1
fi

if [ "`ls -1 rootfs/lib`" = "" ]; then
   echo "cannot find essential libc libraries."
   echo "please add ld-linux and libc.so to `pwd`./rootfs/lib"
   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/null c 1 3
mknod $INITRD_TREE/dev/ram b 1 1
mknod $INITRD_TREE/dev/systty c 4 0
mknod $INITRD_TREE/dev/tty c 5 0
for i in 1 2 3 4 5 6; do
  mknod $INITRD_TREE/dev/tty$i c 4 $i;
done

loops=255
while [ $loops -ge 0 ]; do
   mknod $INITRD_TREE/dev/loop$loops b 7 $loops
   loops=$(($loops-1))
done

debug "copying files to the rootdisk"
touch $INITRD_TREE/etc/{m,fs}tab
cp {linuxrc,cleanup,liblinuxlive} $INITRD_TREE # symlink will be copied as original file
chmod a+x $INITRD_TREE/linuxrc
chmod a+x $INITRD_TREE/cleanup

cp -R rootfs/* $INITRD_TREE
ln -s busybox $INITRD_TREE/bin/ash
ln -s busybox $INITRD_TREE/bin/sh
ln -s busybox $INITRD_TREE/bin/bash
ln -s busybox $INITRD_TREE/bin/[
ln -s busybox $INITRD_TREE/bin/mount
ln -s busybox $INITRD_TREE/bin/umount
ln -s busybox $INITRD_TREE/bin/poweroff
ln -s busybox $INITRD_TREE/bin/halt
ln -s busybox $INITRD_TREE/bin/reboot
ln -s busybox $INITRD_TREE/bin/ld
ln -s busybox $INITRD_TREE/bin/ls
ln -s busybox $INITRD_TREE/bin/head
ln -s busybox $INITRD_TREE/bin/cat
ln -s busybox $INITRD_TREE/bin/grep
ln -s busybox $INITRD_TREE/bin/sleep
ln -s bin $INITRD_TREE/sbin

LMK="lib/modules/$KERNEL"

#necessary modules and dependency files
mkdir -p $INITRD_TREE/$LMK/kernel/fs
cp kernel-modules/$KERNEL/unionfs.ko* $INITRD_TREE/$LMK/kernel/fs
cp kernel-modules/$KERNEL/squashfs.ko* $INITRD_TREE/$LMK/kernel/fs

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

rcopy_ex /$LMK/kernel/fs/isofs $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/fs/fat $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/fs/vfat $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/fs/ntfs $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/fs/ext3 $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/fs/reiserfs $INITRD_TREE 2>>$DEBUG

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

#usb modules
rcopy_ex /$LMK/kernel/drivers/usb/storage $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/drivers/usb/host/ehci-hcd* $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/drivers/usb/host/ohci-hcd* $INITRD_TREE 2>>$DEBUG
rcopy_ex /$LMK/kernel/drivers/usb/host/uhci-hcd* $INITRD_TREE 2>>$DEBUG

#disk (scsi, ide, raid, pcmcia) modules
#rcopy_ex /$LMK/kernel/drivers/scsi $INITRD_TREE
#rcopy_ex /$LMK/kernel/drivers/ide $INITRD_TREE
#rcopy_ex /$LMK/kernel/drivers/pcmcia $INITRD_TREE

if [ "$COMPRESS" = 1 ]; then
   debug "gzipping kernel modules"
   find $INITRD_TREE -name "*.ko" | xargs -r gzip --best
fi

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

debug "creating empty image file $INITRDIMG"
dd if=/dev/zero of=$INITRDIMG bs=1024 count=$RAM0SIZE >>$DEBUG 2>&1

debug "making filesystem"
mkfs -t ext2 -F -m 0 -b 1024 -i 1024 $INITRDIMG >>$DEBUG 2>&1

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

debug "mounting $INITRDIMG to it"
modprobe loop 2>>$DEBUG
mount -o loop $INITRDIMG $MOUNTDIR
if [ "$?" -ne 0 ]; then
   echo "Error mounting initrd! Not enough free loop devices?"
   exit 1
fi

debug "copying content of $INITRD_TREE to $MOUNTDIR"
rmdir $MOUNTDIR/lost+found
cp -R --preserve $INITRD_TREE/* $MOUNTDIR

debug "unmounting $MOUNTDIR"
umount $MOUNTDIR

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

debug "deleting directory $MOUNTDIR"
rmdir $MOUNTDIR

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

debug "$INITRDIMG.gz created"
