#!/bin/sh
#
# bootcdwrite 
#

isoneword()
{
  [ $(echo "$*" | wc -w) -eq 1 ] && return 0
  return 1
}
#for i in "a b" "a" "a
#b"; do
#if isoneword "$i"; then echo "<$i> ok"; else echo "<$i> nok"; fi
#done
#exit 1

cleanup()
{
  echo "--- Cleanup / Undo Source Disk Modifications ---" | tee -a $ERRLOG

  # Be sure that VAR and SRCDISK have no spaces 
  # to not accidently remove anything (for example VAR="/ /var")
  if ! isoneword "$VAR"; then
    echo "Error in VAR <$VAR>" >&2
    exit 1
  fi

  if ! isoneword "$SRCDISK"; then
    echo "Error in SRCDISK <$SRCDISK>" >&2
    exit 1
  fi

  rm -f "$VAR/cdimage"
  umount "$VAR/mnt" 2>/dev/null
  [ -d $VAR/mnt ] && rmdir "$VAR/mnt"

  # do not use "rm -r $VAR"
  rm -f "$ERRLOG.tmp"
  rm -rf "$CHANGES" "$VAR/ram1" "$VAR/ram2"
  [ -d $VAR ] && rmdir "$VAR"

  rm -rf "$SRCDISK/rr_moved"
}

oneline()
{
  if [ "$*" ]; then
    echo "$*"
  else
    cat
  fi | awk '{printf("%s ",$1)} END {printf("\n")}' | sed "s/ *$//"
}

# df_file - How much free space has the filesystem on which file $1 resides ?
df_file()
{
  df -k | awk '{printf("%s %s\n",$4,$6)}' |
  while read size filesys
  do
    if [ "`echo $1 | grep ^$filesys`" ]; then
      namelen=`echo $filesys | wc -c` 
      echo "$namelen $filesys $size"
    fi
  done |
  sort -n | tail -1 | awk '{print $3}'
}

# p - simplify path 
p()
{
  for i in $*; do
    if [ -d $i ]; then
      ( cd $i; /bin/pwd )
    elif [ -f $i ]; then
      ( cd $(dirname $i); echo "$(/bin/pwd)/$(basename $i)" )
    else
      echo "$i does not exist." >> $ERRLOG
      return 1
    fi
  done | oneline
}

# example: 
#echo "p ////home/../etc/passwd //usr//lib// -> /etc/passwd /usr/lib ="
#echo "$(p ////home/../etc/passwd //usr/lib//)"
#exit 0

# ex_proc - exclude SRCDISK/proc
ex_proc()
{
  for i in $*; do
    if [ "$(p $i)" = "$SRCDISK" ]; then
      find $SRCDISK -maxdepth 1 | 
        grep -v -e "^$SRCDISK$" -e "^$(p $SRCDISK/proc)$"
    else
      p $i
    fi
  done | oneline
}
#echo "SRCDISK=/; ex_proc / -> /home /etc /bin ... (without /proc)"
#SRCDISK=/; ex_proc /
#echo "SRCDISK=/; ex_proc /tmp /etc -> /tmp /etc"
#SRCDISK=/; ex_proc /tmp /etc
#exit 0

# du_dir - How much space do given dirs need togehter
du_dir()
{
  du -ksc $(ex_proc "$*") | tail -1 | awk '{print $1}'
}
#echo "ERRLOG=/tmp/t; du_dir /etc; du_dir /tmp; du_dir /etc /tmp -> A + B = C"
#ERRLOG=/tmp/t; du_dir /etc; du_dir /tmp; du_dir /etc /tmp
#exit 0

trapfunc()
{
  echo "trap" >> $ERRLOG
  trap "" EXIT SIGINT # Ignore Traps
  cleanup
  exit 1
}

# kernel_checks - Try to make some kernel checks
kernel_checks()
{
  PROBLEM="
  If you install a kernel from a .deb package the kernel will be named
  /boot/vmlinuz<version> and there will be a kernel config file named
  /boot/config<version>. Bootcdwrite could not find the config file and 
  therefore no further kernel checks could be done. This is not critical 
  but you could build your kernel with make-kpkg to solve the problem.
  Please read the FAQ to check if you have build erverything necessary in
  your kernel.
  "

  KCONF=`echo $KERNEL | sed "s/vmlinuz/config/"`
  if [ "$KCONF" = "$KERNEL" -o ! -f "$KCONF" ]; then
    warn "Could not calculate Kernelconfig to make further checks.$PROBLEM"
    return
  fi

  PROBLEM="
  To run bootcd some features have to be compiled in the kernel.
  Please read the FAQ and check if all necessary features are enabled.
  "
  for i in \
    "CONFIG_BLK_DEV_RAM=y" \
    "CONFIG_BLK_DEV_INITRD=y" \
    "CONFIG_ISO9660_FS=y" \
    "CONFIG_EXT2_FS=y" \
    "CONFIG_BLK_DEV_LOOP=[m|y]"
  do
    grep -q "^$i" $KCONF
    [ $? != 0 ] && warn "$i seems not to be configured in $KERNEL$PROBLEM"
  done

  if [ "$BOOTFLOPPY" = "yes" ]; then
    PROBLEM="
    You have configured BOOTFLOPPY=yes.
    To boot from floppy with syslinux you need some additional features
    compiled in the kernel. Please read the FAQ and check if all necessary
    features are enabled."

    for i in \
      "CONFIG_FAT_FS=y" \
      "CONFIG_MSDOS_FS=y" \
      "CONFIG_VFAT_FS=y"
    do
      grep -q "^$i" $KCONF
      [ $? != 0 ] && warn "$i seems not to be configured in $KERNEL$PROBLEM"
    done
  fi
}

check_config()
{
  if [ "$ONLY_FLOPPY" -a ! "$FLOPPY_CREATE_DEV" ]; then
    err "You have called bootcdwrite with option -only_floppy.
    This makes only sence if you define FLOPPY_CREATE_DEV in conffile."
  fi

  SRCDISK=$(p $SRCDISK)
  [ $? -ne 0 ] && err "Wrong Definition of SRCDISK: See $ERRLOG"

  NOT_TO_CD=$(p $NOT_TO_CD) 
  [ $? -ne 0 ] && err "Wrong Definition of NOT_TO_CD: See $ERRLOG"

  NOT_TO_RAM=$(p $NOT_TO_RAM)
  [ $? -ne 0 ] && err "Wrong Definition of NOT_TO_RAM: See $ERRLOG"
}

check_sizes()
{
  echo "--- Sizes in KByte (du -ksc ) ---" | tee -a $ERRLOG

  S_NOT_TO_CD=0 
  [ "$NOT_TO_CD" ] && S_NOT_TO_CD=$(du_dir $NOT_TO_CD)
  echo -n "NOT_TO_CD =  . . . . . . . . . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_NOT_TO_CD" | tee -a $ERRLOG

  S_CD_ALL=$(du_dir $SRCDISK $NOT_TO_CD)
  echo -n "CD_ALL (SRCDISK V NOT_TO_CD) = . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_CD_ALL" | tee -a $ERRLOG

  let S_NEED_CD="$S_CD_ALL - $S_NOT_TO_CD"
  echo -n "Needed = CD_ALL - NOT_TO_CD  . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_NEED_CD" | tee -a $ERRLOG

  let S_CD="1024 * 650"
  echo -n "CD (650 MB) =  . . . . . . . . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_CD" | tee -a $ERRLOG
  if [ $S_NEED_CD -gt $S_CD ]; then 
    warn "SRCDISK does not fit on CD (Needed > CD)"
  else
    echo "OK - SRCDISK does fit on CD (Needed <= CD)" | tee -a $ERRLOG 
  fi

  S_VAR=$(df_file $VAR)
  echo -n "VAR =  . . . . . . . . . . . . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_VAR" | tee -a $ERRLOG
  if [ $S_NEED_CD -gt $S_VAR ]; then
    warn "Not enough space in $VAR (Needed > VAR)"
  else
    echo "OK - enough space in $VAR (Needed <= VAR)"  | tee -a $ERRLOG 
  fi

  S_NOT_TO_RAM=0 
  [ "$NOT_TO_RAM" ] && S_NOT_TO_RAM=$(du_dir $NOT_TO_RAM)
  echo -n "NOT_TO_RAM = . . . . . . . . . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_NOT_TO_RAM"  | tee -a $ERRLOG

  S_NOT_TO_RAMCD=0 
  [ "$NOT_TO_RAM$NOT_TO_CD" ] && S_NOT_TO_RAMCD=$(du_dir $NOT_TO_RAM $NOT_TO_CD)
  echo -n "NOT_TO_RAMCD (NOT_TO_RAM V NOT_TO_CD) =  . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_NOT_TO_RAMCD"| tee -a $ERRLOG

  S_RAM_ALL=$(du_dir $SRCDISK/etc $SRCDISK/home $SRCDISK/root $NOT_TO_RAM \
    $NOT_TO_CD)
  echo -n "RAM_ALL (etc V home V root V NOT_TO_RAM V NOT_TO_" | tee -a $ERRLOG
  echo "CD) = . . . . . . $S_RAM_ALL" | tee -a $ERRLOG

  let S_NEED_RAM="$S_RAM_ALL-2*$S_NOT_TO_RAMCD+$S_NOT_TO_CD+$S_NOT_TO_RAM"
  echo -n "Needed RAM (RAM_ALL + NOT_TO_CD - 2 * NOT_TO_RAMC" | tee -a $ERRLOG
  echo "D + NOT_TO_RAM) = $S_NEED_RAM" | tee -a $ERRLOG

  let S_RAM="$RAMDISK_SIZE * 9 / 10"
  echo -n "90 % of RAM =  . . . . . . . . . . . . . . . . . " | tee -a $ERRLOG
  echo ". . . . . . . . . $S_RAM" | tee -a $ERRLOG
  if [ $S_NEED_RAM -gt $S_RAM ]; then  
    warn "Not enough RAM (Needed RAM > 90 % of RAM)"
  else
    echo "OK - enough RAM (Needed RAM <= 90 % of RAM)" | tee -a $ERRLOG 
  fi
}

mk_grep()
{
  if [ "$*" ]; then
    echo "$*" | 
    sed 's/\(^\| \)*\([^ ]*\)/-e ^\2 /g' | 	# Insert all "-e"
    sed "s/[[:space:]]*$//" |			# Delete trailing spaces
    sed "s/^/grep -v /"				# Insert "grep -v"
  else
    echo "cat"
  fi
}
#echo "mk_grep /usr/lib /usr/share -> grep -v -e ^/usr/lib\> -e ^/usr/share\>"
#echo "<$(mk_grep /usr/lib /usr/share)>"
#echo "mk_grep "" -> cat"
#echo "<$(mk_grep "")>"
#exit 0
#
#t=$(mk_grep /x)
#echo "t=<$t>"
#echo "a/x/b: $(echo "a/x/b" | $t)"
#echo "/xb: $(echo "/xb" | $t)"
#echo "/x/b: $(echo "/xb" | $t)"
#exit 0

# chnglist [-add_ro] [-no_mnt] <MNT> <LIST>
#   -add_ro = add ".ro" to directory following <MNT>
#   -no_mnt = path without <MNT>
#   -rel    = start without /
chnglist()
{
  ADD_RO=""
  NO_MNT=""
  REL=""
  OPT="1"
  while [ "$OPT" ]; do
    if [ "$1" = "-no_mnt" ]; then
      NO_MNT="1"
      shift
    elif [ "$1" = "-add_ro" ]; then
      ADD_RO="1"
      shift
    elif [ "$1" = "-rel" ]; then
      REL="1"
      shift
    else
      OPT=""
    fi
  done
  [ $# -ne 2 ] && err "Internal Error calling Function chnglist"
    
  S="$1"; [ "$S" = "/" ] && S=""
  echo " $2" |
  if [ "$ADD_RO" ]; then
    if [ "$NO_MNT" ]; then
      sed "s|[[:space:]]$S/\([^/]*\)\>| \1.ro|g" | sed "s/[[:space:]]*//"
    else
      sed "s|[[:space:]]$S\(/[^/]*\)\>| $S\1.ro|g" | sed "s/[[:space:]]*//"
    fi
  else
    if [ "$NO_MNT" ]; then
      sed "s|[[:space:]]$S/\([^/]*\)\>| \1|g"
    else
      cat
    fi
  fi |  
  sed 's|[^[:graph:]]/\+\([[:graph:]]\+\)| \1|g' | # without leading /
  if [ "$REL" ]; then
    cat 
  else
    sed 's|\([[:graph:]]\+\)|/\1|g'
  fi |
  sed "s/[[:space:]]*//" # remove leading space
}
#echo 'chnglist -add_ro "/" "/etc/a /etc/b /root" -> /etc.ro/a /etc/.ro/b /root.ro'
#echo "  <$(chnglist -add_ro "/" "/etc/a /etc/b /root")>"
#echo 'chnglist -add_ro "/mnt" "/mnt/etc/a /mnt/root" -> /mnt/etc.ro/a /mnt/root.ro'
#echo "  <$(chnglist -add_ro "/mnt" "/mnt/etc/a /mnt/root")>"
#echo 'chnglist -add_ro -no_mnt "/" "/home/a /root" -> /home.ro/a /root.ro'
#echo "  <$(chnglist -add_ro -no_mnt "/" "/home/a /root")>"
#echo 'chnglist -add_ro -no_mnt "/mnt" "/mnt/home/b /mnt/root" -> /home.ro/b /root.ro'
#echo "  <$(chnglist -add_ro -no_mnt "/mnt" "/mnt/home/b /mnt/root")>"
#echo 'chnglist -no_mnt "/" "/etc/a /etc/b /root" -> /etc/a /etc/b /root'
#echo "  <$(chnglist -no_mnt "/" "/etc/a /etc/b /root")>"
#echo 'chnglist -no_mnt "/mnt" "/mnt/etc/a /mnt/root" -> /etc/a /root'
#echo "  <$(chnglist -no_mnt "/mnt" "/mnt/etc/a /mnt/root")>"
#echo 'chnglist -rel -no_mnt "/" "/etc/a /etc/b /root" -> etc/a etc/b root'
#echo "  <$(chnglist -rel -no_mnt "/" "/etc/a /etc/b /root")>"
#echo 'chnglist -no_mnt -rel "/mnt" "/mnt/etc/a /mnt/root" -> etc/a root'
#echo "  <$(chnglist -no_mnt -rel "/mnt" "/mnt/etc/a /mnt/root")>"
#exit 0

#
# ck_not2ram - Check Variable NOT_TO_RAM
#
ck_not2ram()
{
  S=$SRCDISK; [ "$S" = "/" ] && S=""

  PROBLEM="
  Only files from $S/home, $S/var, $S/etc, 
  $S/dev, $S/tmp or $S/root will be copied
  to ram. It makes only sence to exclude files from that directories."

  for i in $NOT_TO_RAM; do
    echo "$i" | grep -q \
      -e "^$S/home\>" -e "^$S/var\>" \
      -e "^$S/etc\>"  -e "^$S/dev\>" \
      -e "^$S/tmp\>"  -e "^$S/root\>"
    [ $? = 0 ] || warn "NOT_TO_RAM consists of $i.$PROBLEM"
  done
}

# mk_bootcdram <PRE> <LIST>
mk_bootcdram()
{
  A=$(chnglist -add_ro -no_mnt "$1" "$2")
  B=$(mk_grep $A)

cat <<END
#!/bin/sh
# cdboot.sh	Necessary steps to boot diskless from cd
# at Boottime /etc -> /ram1/etc -> /etc.ro (also dev, tmp, var, home, root)
echo 'Creating /ram'

mke2fs -q -i 1024 /dev/ram1 # Size is defined by ramdisk_size at boottime
mount /dev/ram1 /ram1 -o defaults,rw
if [ -f /ram1.cpio.gz ]; then
  echo 'Extracting /ram1.cpio.gz'
  cd /ram1; zcat /ram1.cpio.gz | cpio -idu
else
  mkdir /ram1/tmp; chmod 777 /ram1/tmp
  for i in home root etc dev; do find /\$i.ro | $B | cpio -pd /ram1; done
  for i in home root etc dev; do mv /ram1/\$i.ro /ram1/\$i; done
fi

mke2fs -q -i 1024 /dev/ram2 # Size is defined by ramdisk_size at boottime
mount /dev/ram2 /ram2 -o defaults,rw
if [ -f /ram2.cpio.gz ]; then
  echo 'Extracting /ram2.cpio.gz'
  cd /ram2; zcat /ram2.cpio.gz | cpio -idu
else
  find /var.ro -type d | $B | cpio -pd /ram2
  for i in var; do mv /ram2/\$i.ro /ram2/\$i; done
fi
END

[ "$A" ] &&
cat <<END

for i in $A; do
  j=\`echo \$i | sed 's/.ro//'\`
  mkdir -p \`dirname \$j\`; ln -s \$i \$j
done
END

  return 0 # is needed, because we would return 1 when A=""
}
#echo 'mk_bootcdram "/mnt" "/mnt/root /mnt/home/a" -> skript with:'
#echo '...| grep -v -e /root.ro -e /home.ro/a |...'
#mk_bootcdram "/mnt" "/mnt/root /mnt/home/a"
#exit 0

#echo 'mk_bootcdram "/" "/root /home/a" -> skript with:'
#echo '...| grep -v -e /root.ro -e /home.ro/a |...'
#mk_bootcdram "/" "/root /home/a"
#exit 0

#echo 'mk_bootcdram "/" "" -> skript with: "...| cat |..." and without "ln -s"'
#mk_bootcdram "/" ""
#exit 0

ONLY_FLOPPY=""
if [ "$1" = "-only_floppy" ]; then
  shift
  ONLY_FLOPPY="yes"
fi

if [ "$#" != "0" ]; then
  echo "Usage: bootcdwrite -only_floppy"
  echo "  use man bootcdwrite to get help"
  echo "  and see /etc/bootcd/bootcdwrite.conf"
  exit 1
fi

if [ "`whoami`" != "root" ]; then
  echo "You have to run bootcdwrite as root"
  exit 1
fi

CONFVARS="SRCDISK KERNEL APPEND NOT_TO_CD NOT_TO_RAM SSHHOSTKEY RAMDISK_SIZE \
ERRLOG VAR DO_CHECK BLANKING CDSCSI CDSPEED CDDEV DISPLAY FASTBOOT \
FLOPPY_RUNTIME_DEV FLOPPY_CREATE_DEV BOOTFLOPPY BOOT_ONLY_WITH_FLOPPY \
CLEAN_VAR"

unset $CONFVARS
. /etc/bootcd/bootcdwrite.conf
. /usr/lib/bootcd/bootcd.lib

for i in $CONFVARS; do
  [ "`set | grep ^$i=`" ] || err "$i is not set in /etc/bootcd/bootcdwrite.conf"
done
CHANGES=$VAR/changes

trap trapfunc EXIT SIGINT

date "+--- $0 %d.%m.%Y ---" > $ERRLOG
echo "To see full output: tail -f $ERRLOG" | tee -a $ERRLOG
cleanup

check_config
ck_not2ram

echo ""
A=""
while [ "$A" != "y" -a "$A" != "n" ]
do
  [ "$ONLY_FLOPPY" ] ||
  echo "  SCSI Device $CDSCSI will be burned !" | tee -a $ERRLOG

  [ "$FLOPPY_CREATE_DEV" ] && 
  echo "  Floppy $FLOPPY_CREATE_DEV will be formatted !" | tee -a $ERRLOG

  [ "$CLEAN_VAR" = "yes" -a ! "$ONLY_FLOPPY" ] &&
  echo "  /var will be cleaned (apt-get clean) !" | tee -a $ERRLOG

  echo ""
  echo -n "Ok to continue? (y/n) " | tee -a $ERRLOG
  read A; echo "$A" >> $ERRLOG
done
if [ "$A" == "n" ]; then
  exit 1
fi
echo ""

if [ "$DO_CHECK" == "yes" ]; then
  echo "--- Checking for possible Problems ---" | tee -a $ERRLOG
  PROBLEM="
  This file will be created in the next step by bootcdwrite. 
  Please remove the actual file."
  for i in cdboot.img cdboot.catalog usr/bin/bootcd2disk \
    usr/bin/bootcdflopcp usr/bin/bootcdflopcp etc/rcS.d/S13bootcdflop.sh \
    etc/bootcd/bootcd2disk.conf 
  do
    [ -f $SRCDISK/$i ] && warn "found $SRCDISK/$i$PROBLEM"
  done
  
  check_sizes

  [ "$DISPLAY" ] && ( [ -f $DISPLAY ] || warn "DISPLAY ($DISPLAY) not found." )

  kernel_checks # Try to make some kernel checks

elif [ "$DO_CHECK" != "no" ]; then
  warn 'DO_CHECK is not defined as "yes" or "no".' \
       'It will be treated as "no".'
fi
  
echo "--- Building Modifications ---" | tee -a $ERRLOG
run mkdir $VAR
run mkdir $VAR/mnt
run mkdir -p $CHANGES/proc $CHANGES/ram1 $CHANGES/ram2

# at Boottime /etc -> /ram1/etc -> /etc.ro
for i in etc tmp dev home root; do run ln -sf /$i.ro $CHANGES/ram1/$i; done
for i in var; do run ln -sf /$i.ro $CHANGES/ram2/$i; done
for i in etc tmp dev home root; do  run ln -sf /ram1/$i $CHANGES/$i; done
for i in var; do  run ln -sf /ram2/$i $CHANGES/$i; done

if [ "$CLEAN_VAR" = "yes" -a ! "$ONLY_FLOPPY" ]; then
  run apt-get clean # to clear some diskspace in /var 
fi

# build etc.ro var.ro dev.ro tmp.ro home.ro root.ro
run mkdir $CHANGES/tmp.ro
run chmod 777 $CHANGES/tmp.ro
run mkdir $CHANGES/etc.ro
run chmod 755 $CHANGES/etc.ro

run ln -sf /proc/mounts $CHANGES/etc.ro/mtab
mkdir -p $CHANGES/etc.ro/rcS.d
run "mk_bootcdram \"$SRCDISK\" \"$NOT_TO_RAM\" >$CHANGES/etc.ro/rcS.d/S12bootcdram.sh"

run "chmod 755 $CHANGES/etc.ro/rcS.d/S12bootcdram.sh"

run mkdir -p $CHANGES/usr/bin $CHANGES/etc.ro/bootcd $CHANGES/usr/lib/bootcd
run cp /usr/lib/bootcd/bootcd2disk $CHANGES/usr/bin/
run cp /usr/lib/bootcd/bootcdflopcp $CHANGES/usr/bin/
run "cat /usr/lib/bootcd/S13bootcdflop.sh |
  sed \"s|^\(BOOT_ONLY_WITH_FLOPPY=\).*$|\1$BOOT_ONLY_WITH_FLOPPY|\" |
  sed \"s|^FLOPPY=.*$|FLOPPY=$FLOPPY_RUNTIME_DEV|\" |
  cat >$CHANGES/etc.ro/rcS.d/S13bootcdflop.sh"
run chmod 755 $CHANGES/etc.ro/rcS.d/S13bootcdflop.sh

run cp /usr/lib/bootcd/bootcd2disk.conf $CHANGES/etc.ro/bootcd/
run cp /usr/lib/bootcd/bootcd.lib $CHANGES/usr/lib/bootcd/

run "cat <<END > $CHANGES/etc.ro/fstab
$CDDEV / iso9660 defaults,ro 0 1
proc /proc proc defaults 0 0
END"

if [ ! "$ONLY_FLOPPY" ]; then
  if [ "$SSHHOSTKEY" == "yes" ]; then
    # each CD gets a unique hostkey"
    run mkdir -p $CHANGES/etc.ro/ssh

    # just controlling exitcode for ssh-keygen, because there are different 
    # versions of ssh-keygen running and each one makes different output on
    # stdout and stderr
    run "ssh-keygen -b 1024 -f $CHANGES/etc.ro/ssh/ssh_host_key -N '' >>$ERRLOG 2>&1"

  elif [ "$SSHHOSTKEY" != "no" ]; then
    warn 'SSHHOSTKEY is not defined as "yes" or "no".' \
         'It will be treated as "no".'
  fi
fi

# Build cdboot.img
run cp /usr/lib/syslinux/img1440k.gz $CHANGES/cdboot.img.gz
run gunzip $CHANGES/cdboot.img.gz
run mount -o loop /$CHANGES/cdboot.img $VAR/mnt -t msdos
run cp $KERNEL $VAR/mnt/vmlinuz.img

run "cat <<END >$VAR/mnt/syslinux.cfg
default linux
label linux
timeout 50
kernel vmlinuz.img
append root=$CDDEV ramdisk_size=$RAMDISK_SIZE $APPEND
prompt 1
END"

if [ "$DISPLAY" ]; then 

run "cat <<END >>$VAR/mnt/syslinux.cfg
display display.txt
END"

  run cp $DISPLAY $VAR/mnt/display.txt
fi

run umount $VAR/mnt
losetup -d /dev/loop0 2>/dev/null
run touch $CHANGES/fastboot

if [ "$FASTBOOT" == "yes" ]; then
  echo "--- Creating /ram[1|2].cpio.gz for FASTBOOT ---" | tee -a $ERRLOG

  run mkdir $VAR/ram1
  mkdir $VAR/ram1/tmp; chmod 777 $VAR/ram1/tmp
  FG=$(mk_grep $(chnglist -rel -no_mnt "$SRCDISK" "$NOT_TO_RAM $NOT_TO_CD"))
  echo "FG (FASTBOOT GREP) = <$FG>" >>$ERRLOG

  for i in home root etc dev; do 
    run "cd $SRCDISK; find $i | $FG | cpio --quiet -pdu $VAR/ram1"

    if [ -d $CHANGES/$i.ro ]; then 
      run "cd $CHANGES/$i.ro
           find . | 
	   cut -c3- | grep -v '^$' | 		# ./file -> file
	   $FG | cpio --quiet -pdu $VAR/ram1/$i"
    fi
  done

  ignore "cpio: .*: truncating inode number"
  run "cd $VAR/ram1
       find . | cpio --quiet -o | gzip -c -9 >$CHANGES/ram1.cpio.gz"
  run "rm -r $VAR/ram1"
  
  run mkdir $VAR/ram2
  run "cd $SRCDISK/
       find var -type d | $FG | cpio --quiet -pdu $VAR/ram2"

  ignore "cpio: .*: truncating inode number"
  run "cd $VAR/ram2
       find . | cpio --quiet -o | gzip -c -9 >$CHANGES/ram2.cpio.gz"
  run "rm -r $VAR/ram2"

elif [ "$FASTBOOT" != "no" ]; then
  warn 'FASTBOOT is not defined as "yes" or "no".' \
       'It will be treated as "no".'
fi

if [ ! "$ONLY_FLOPPY" ]; then

  echo "--- Creating CD-Image ---" | tee -a $ERRLOG
  ignore "^Using .* for"
  ignore "^Total "
  ignore "estimate finish"
  ignore "^Path table size"
  ignore "^Max brk space used"
  ignore "^$"
  stdout "^Size of boot image is"
  stdout "extents written"
  
  MKISO_NOT=""
  if [ "$NOT_TO_CD" != "" ]; then
    MKISO_NOT=`echo "$NOT_TO_CD" | sed "s/\(^\| \)*\([^ ]*\)/-x \2 /g"`
    echo "NOT_TO_CD arguments for mkisofs = <$MKISO_NOT>" >>$ERRLOG
  fi
  
  S="$SRCDISK"; [ "$S" = "/" ] && S=""

  # Are there Files in $S that we have in $CHANGES too
  # If so we have to exclude them
  EXCLUDE=""
  for i in `(cd $CHANGES; find . ! -type d)`; do
                                 # i=./etc.ro/mtab
    j=`echo $i|sed "s|^\.||"`    # j=/etc.ro/mtab
    k=`echo $j|sed "s|\.ro/|/|"` # k=/etc/mtab
    if [ -f $k ]; then
      EXCLUDE="$EXCLUDE -x $S$k"
    fi
  done

  # since mkisofs 1.13 we have to use the option -graft-points
  GRAFTPOINTS=`mkisofs --version | awk '{if($2>1.12) {print "-graft-points"}}'`
  echo "GRAFTPOINTS=<$GRAFTPOINTS>" >>$ERRLOG

  stdout "Unable to open directory .*/dev/pts"
  run mkisofs $GRAFTPOINTS $MKISO_NOT \
    -R -b cdboot.img -c cdboot.catalog -o $VAR/cdimage \
    -x $S/proc -x $VAR -x $ERRLOG \
    -x $S/etc -x $S/var -x $S/tmp \
    -x $S/dev -x $S/home -x $S/root $EXCLUDE \
    /=$S/ /=$CHANGES \
    /dev.ro/=$S/dev /home.ro/=$S/home /root.ro/=$S/root \
    /var.ro/=$S/var /etc.ro/=$S/etc
  
  echo "--- Testing CD-Image ---" | tee -a $ERRLOG
  run mount $VAR/cdimage $VAR/mnt -o loop -t iso9660
  ignore ".*"
  run ls -l $VAR/mnt
  run umount $VAR/mnt
  losetup -d /dev/loop0 2>/dev/null
  
  if [ "$BLANKING" == "yes" ]; then
    echo "--- Blanking CD ---" | tee -a $ERRLOG
    ignore "Drive needs to reload the media to return to proper status"
    ignore "Copyright (C)"
    ignore "^scsidev:"
    ignore "^scsibus:"
    ignore "^Using libscg version"
    ignore "^Device type"
    ignore "^Version"
    ignore "^Response Format"
    ignore "^Capabilities"
    stdout "^Vendor_info"
    stdout "^Identifikation"
    stdout "^Revision"
    ignore "^Device seems to be:"
    ignore "^Using"
    ignore "^Driver flags"
    stdout "^Starting to write CD/DVD"
    ignore "^Last chance to quit"
    ignore "^Blocks total: .* Blocks current: .* Blocks remaining: .*"
    ignore "^Linux sg driver version:"
    stdout "^Blanking"
    run cdrecord blank=fast speed=$CDSPEED dev=$CDSCSI
  elif [ "$BLANKING" != "no" ]; then
    run echo 'BLANKING is not defined as "yes" or "no"'
    run echo 'it will be treated as "no".'
  fi
  
  echo "--- Writing CD ---" | tee -a $ERRLOG
  ignore "Copyright (C)"
  ignore "^Vendor_info"
  ignore "^Identifikation"
  ignore "^Revision"
  ignore "^FIFO size"
  ignore "^Linux sg driver version:"
  ignore "^Lout start:"
  ignore "^Waiting for reader process to fill input buffer"
  stdout "^Starting new track at sector"
  stdout ".* of .* MB written"
  stdout "^Writing..time:"
  stdout "^Fixating"
  ignore "fifo had .* puts and .* gets"
  ignore "fifo was 0 times empty and .* times full"
  ignore "^Device seems to be:"
  ignore "^Using"
  ignore "^Driver flags"
  ignore "^Drive buf size :"
  ignore "^Total size:"
  ignore "^Current Secsize:"
  ignore "^ATIP info from disk:"
  ignore "^..Indicated writing power:"
  ignore "^..Reference speed:"
  ignore "^..Is not unrestricted"
  ignore "^..Is erasable"
  ignore "^..Is not erasable"
  ignore "^..Disk sub type:"
  ignore "^..ATIP start of lead in:"
  ignore "^..ATIP start of lead out:"
  ignore "^..speed low: .* speed high:"
  ignore "^..power mult factor:"
  ignore "^..recommended erase/write power:"
  ignore "^..A2 values:"
  ignore "^Disk type:"
  ignore "^Manuf. index:"
  ignore "^Manufacturer:"
  ignore "Blocks total:.*Blocks current:.*Blocks remaining:"
  ignore "^Starting to write CD/DVD at speed"
  ignore "^Last chance to quit, starting real write in"
  ignore "^TOC Type:"
  ignore "^scsidev:"
  ignore "^scsibus:"
  ignore "^atapi:"
  ignore "^Device type"
  ignore "^Version"
  ignore "^Response Format"
  ignore "^Capabilities"
  ignore "^Track .*: data .* MB"
  ignore "^Track .*: Total bytes read/written:"
  ignore "^Performing OPC..."
  run cdrecord -v speed=$CDSPEED dev=$CDSCSI $VAR/cdimage

fi

if [ "$FLOPPY_CREATE_DEV" ]; then
  echo "--- Writing Floppy ---" | tee -a $ERRLOG
  stdout "Formatting cylinder"
  ignore "^mformat"
  run superformat $FLOPPY_CREATE_DEV

  if [ "$BOOTFLOPPY" = "yes" ]; then
    ignore 
    run dd if=/$CHANGES/cdboot.img of=$FLOPPY_CREATE_DEV bs=1024
    
    # it works without the next line, but it is very slow then
    run syslinux $FLOPPY_CREATE_DEV

  elif [ "$BOOTFLOPPY" != "no" ]; then
    warn 'BOOTFLOPPY is not defined as "yes" or "no".' \
         'It will be treated as "no".'
  fi
fi
