#!/bin/sh
#
# bootcdwrite 
#

isoneword()
{
  [ $# -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 ---" | 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"
  rm -rf "$VAR/input_dir"
  rm -rf "$VAR/compressed_dir"
  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 -a ! -f $VAR/cdimage.iso ] && rmdir "$VAR"
}

oneline()
{
  if [ $# -gt 0 ]; 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()
{
  ERR=0
  if [ $# -gt 0 ]; then
    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
        ERR=1
        continue
      fi
    done | oneline
  fi
  return $ERR
}
# example: 
#echo "p ////home/../etc/passwd //usr//lib// -> /etc/passwd /usr/lib ="
#echo "$(p ////home/../etc/passwd //usr/lib//)"
#exit 0

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

# du_dir - How much space do given dirs need togehter
du_dir()
{
  if [ $# -gt 0 ]; then
    LIST1="$(for i in $(p $*); do echo $i; done | sort)"
    LAST=""; LIST2=""
    for i in $LIST1; do
      if [ "$LAST" ]; then
        if [ "$LAST" = "/" ]; then 
          [ "$(echo "$i" | grep "^/")" ] && i=""
        else
          [ "$(echo "$i" | grep "^$LAST\>")" ] && i=""
        fi
      fi
      if [ "$i" ]; then
        LIST2="$LIST2 $i"
        LAST="$i"
      fi
    done
    LIST3=$(ex_proc "$LIST2")
    echo "du -klsc $LIST3" >> $ERRLOG
    du -klsc $LIST3 | tee -a $ERRLOG | tail -1 | awk '{print $1}'
  fi
}
#ERRLOG=/var/log/errlog
#echo "du_dir /etc; du_dir /tmp; du_dir /etc /tmp -> A + B = C"
#du_dir /etc; du_dir /tmp; du_dir /etc /tmp
#exit 0
#echo "du_dir /etc; du_dir /etc /etc/network -> A = B"
#du_dir /etc; du_dir /etc /etc/network
#exit 0

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


mk_grep()
{
  if [ $# -gt 0 ]; 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

# mk_bootcdram <SRCDISK> <NOT_TO_RAM>
mk_bootcdram()
{
  CHNG=$(chnglist -add_ro -no_mnt "$1" "$2")
  CHNGGREP=$(mk_grep $CHNG)
  cat /usr/share/bootcd/S12bootcdram.sh | 
    sed "s|<CHNG>|$CHNG|" |
    sed "s|<CHNGGREP>|$CHNGGREP|" 
}
#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

do_syslinux()
{
  if [ "$SYSLINUX_SAVE" = "yes" ]; then
    SYSLINUX_SAVE="-s"
  elif [ "$SYSLINUX_SAVE" = "no" ]; then
    SYSLINUX_SAVE=""
  else
    SYSLINUX_SAVE=""
    warn 'SYSLINUX_SAVE is not defined as "yes" or "no".' \
         'It will be treated as "no".'
  fi
  
  # Build cdboot.img 
  # do not use /usr/lib/syslinux/img1440k.gz, to be able to use other
  # syslinux options

  ignore "^1440+0 records"
  run dd bs=1024 count=1440 if=/dev/zero of=/$CHANGES/cdboot.img

  ignore "^mkfs.vfat" # mkfs.vfat 2.8 (28 Feb 2001)
  run mkfs -t vfat /$CHANGES/cdboot.img

  run syslinux $SYSLINUX_SAVE /$CHANGES/cdboot.img

  run mount -o loop /$CHANGES/cdboot.img $VAR/mnt -t msdos
  run cp $KERNEL $VAR/mnt/vmlinuz.img

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

  for i in $CDDEVR; do
    echo "label $(basename $i)"
    echo "  kernel vmlinuz.img"
    echo "  append root=$i ramdisk_size=$RAMDISK_SIZE $APPEND"
  done >>$VAR/mnt/syslinux.cfg

  if [ "$DISPLAY" ]; then 

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
}

do_isolinux()
{
  run mkdir /$CHANGES/isolinux
  run cp /usr/lib/syslinux/isolinux.bin /$CHANGES/isolinux
  run cp $KERNEL /$CHANGES/isolinux/vmlinuz
  LILOINITRD=""
  if [ "$INITRD" ]; then 
    run cp $INITRD /$CHANGES/isolinux/initrd
    LILOINITRD="initrd=/isolinux/initrd"
  fi

cat <<END >/$CHANGES/isolinux/isolinux.cfg
default linux
timeout 50
prompt 1
label linux
  kernel /isolinux/vmlinuz
  append $LILOINITRD root=$CDDEV1 ramdisk_size=$RAMDISK_SIZE $APPEND
END

  for i in $CDDEVR; do
    echo "label $(basename $i)"
    echo "  kernel /isolinux/vmlinuz"
    echo "  append $LILOINITRD root=$i ramdisk_size=$RAMDISK_SIZE $APPEND"
  done >>$CHANGES/isolinux/isolinux.cfg

  if [ "$DISPLAY" ]; then 

cat <<END >>/$CHANGES/isolinux/isolinux.cfg
display display.txt
END

    run cp $DISPLAY /$CHANGES/isolinux/display.txt
  fi
}

blank_cd()
{
  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"
  ignore "^Supported modes:"
  if [ "$BLANKING" = "auto" ]; then
    stdout "Cannot blank disk"
    ignore ".*"
  fi
  run cdrecord blank=fast speed=$CDSPEED dev=$CDSCSI
}

write_cd()
{
  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..."
  ignore "^Supported modes:"
  ignore "^..1T speed low:"
  ignore "^..2T speed low:"
  ignore "^..A1 values:"
  stdout "^Average write speed"
  stdout "^Min drive buffer fill was"
  run cdrecord -v -eject speed=$CDSPEED dev=$CDSCSI $VAR/cdimage
}

compress_dir()
{
  if [ "$EXCLUDE" -o "$MKISO_NOT" ]; then
    ZFTREEEX="$(echo $EXCLUDE $MKISO_NOT | sed "s/-x/-e/g")"
  fi
  echo "--- Building input_dir for compression ---" | tee -a $ERRLOG
  run "cd $SRCDISK; rm -rf $VAR/input_dir; mkdir $VAR/input_dir; 
    find $(ex_proc $SRCDISK) |
    grep -v -e $VAR -e $ERRLOG -e $SRCDI/tmp $ZFTREEEX |
    sed \"s|^$SRCDI/||\" |
    cpio --quiet -pdum $VAR/input_dir/"

  run mv $VAR/input_dir/home $VAR/input_dir/home.ro
  run mv $VAR/input_dir/root $VAR/input_dir/root.ro
  run mv $VAR/input_dir/var $VAR/input_dir/var.ro
  run mv $VAR/input_dir/etc $VAR/input_dir/etc.ro
  run mv $VAR/input_dir/dev $VAR/input_dir/dev.ro
  run "cd $CHANGES; find . | cpio --quiet -pdum $VAR/input_dir/"
  [ "$DEVFS" = "yes" ] && run rm -r $VAR/input_dir/dev.ro

  echo "--- Compressing input_dir to compressed_dir ---" | tee -a $ERRLOG
  run "rm -rf $VAR/compressed_dir; mkzftree $VAR/input_dir $VAR/compressed_dir"
  run rm -r $VAR/input_dir
}

mkisofs_ignore()
{
  stdout "Warning: using transparent compression"
  stdout "The resulting filesystem can only be transparently"
  stdout "On other operating systems you need to call"
  stdout "mkzftree by hand to decompress the files"
  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"
  stdout "Unable to open directory .*/dev/pts"
}

uncompress_files()
{
  if [ $# -gt 0 ]; then
    for i in $*; do
      F="-F"
      [ -d $VAR/compressed_dir/$i ] && F=""
      run mkzftree -u $F $VAR/compressed_dir/$i $VAR/uncompress.tmp
      run rm -rf $VAR/compressed_dir/$i
      run mv $VAR/uncompress.tmp $VAR/compressed_dir/$i
    done
  fi
}

cdimage_compressed_isolinux()
{
  compress_dir
  uncompress_files isolinux
  mkisofs_ignore
  run mkisofs -z -R -b isolinux/isolinux.bin -c isolinux/boot.cat \
    -o $VAR/cdimage \ -no-emul-boot -boot-load-size 4 -boot-info-table \
    $VAR/compressed_dir
  run rm -r $VAR/compressed_dir
}

cdimage_compressed_normal()
{
  compress_dir
  uncompress_files cdboot.img
  mkisofs_ignore
  run mkisofs -z -R -b cdboot.img -c cdboot.catalog -o $VAR/cdimage \
    $VAR/compressed_dir
  run rm -r $VAR/compressed_dir
}

cdimage_compressed_hppa()
{
  compress_dir
  uncompress_files /usr/share/palo/iplboot $KERNEL
  mkisofs_ignore
  run mkisofs -z -R -o $VAR/cdimage $VAR/compressed_dir
  run rm -r $VAR/compressed_dir

  ignore "^palo version "
  ignore "^ELF32 executable"
  ignore "^ELF64 executable"
  ignore "^ipl: addr "
  ignore "^ ko 0x"
  ignore "^<0/boot/vmlinux root=$CDDEV1 ramdisk_size=$RAMDISK_SIZE $APPEND>"
  ignore "^<>$"
  run palo -k $KERNEL \
    -f /dev/null \
    -b $SRCDI/usr/share/palo/iplboot \
    -c \"0/boot/vmlinux root=$CDDEV1 ramdisk_size=$RAMDISK_SIZE $APPEND\" \
    -C $VAR/cdimage
}

cdimage_isolinux()
{
  mkisofs_ignore
  run mkisofs $GRAFTPOINTS $MKISO_NOT \
    -R -b isolinux/isolinux.bin -c isolinux/boot.cat -o $VAR/cdimage \
    -no-emul-boot -boot-load-size 4 -boot-info-table \
    -x $SRCDI/proc -x $VAR -x $ERRLOG \
    -x $SRCDI/etc -x $SRCDI/var -x $SRCDI/tmp \
    -x $SRCDI/dev -x $SRCDI/home -x $SRCDI/root $EXCLUDE \
    /=$SRCDI/ /=$CHANGES \
    /home.ro/=$SRCDI/home /root.ro/=$SRCDI/root /var.ro/=$SRCDI/var \
    /etc.ro/=$SRCDI/etc $MKISODEVFS
}

cdimage_normal()
{
  mkisofs_ignore
  run mkisofs $GRAFTPOINTS $MKISO_NOT \
    -R -b cdboot.img -c cdboot.catalog -o $VAR/cdimage \
    -x $SRCDI/proc -x $VAR -x $ERRLOG \
    -x $SRCDI/etc -x $SRCDI/var -x $SRCDI/tmp \
    -x $SRCDI/dev -x $SRCDI/home -x $SRCDI/root $EXCLUDE \
    /=$SRCDI/ /=$CHANGES \
    /home.ro/=$SRCDI/home /root.ro/=$SRCDI/root /var.ro/=$SRCDI/var \
    /etc.ro/=$SRCDI/etc $MKISODEVFS
}

cdimage_hppa()
{
  mkisofs_ignore
  run mkisofs $GRAFTPOINTS $MKISO_NOT \
    -R -o $VAR/cdimage \
    -x $SRCDI/proc -x $VAR -x $ERRLOG \
    -x $SRCDI/etc -x $SRCDI/var -x $SRCDI/tmp \
    -x $SRCDI/dev -x $SRCDI/home -x $SRCDI/root $EXCLUDE \
    /=$SRCDI/ /=$CHANGES \
    /home.ro/=$SRCDI/home /root.ro/=$SRCDI/root /var.ro/=$SRCDI/var \
    /etc.ro/=$SRCDI/etc $MKISODEVFS

  ignore "^palo version "
  ignore "^ELF32 executable"
  ignore "^ELF64 executable"
  ignore "^ipl: addr "
  ignore "^ ko 0x"
  ignore "^<0/boot/vmlinux root=$CDDEV1 ramdisk_size=$RAMDISK_SIZE $APPEND>"
  ignore "^<>$"
  run palo -k $KERNEL \
    -f /dev/null \
    -b $SRCDI/usr/share/palo/iplboot \
    -c \"0/boot/vmlinux root=$CDDEV1 ramdisk_size=$RAMDISK_SIZE $APPEND\" \
    -C $VAR/cdimage
}

CONFDIR="/etc/bootcd"
ONLY_FLOPPY=""
while [ $# -gt 0 ]; do
  if [ "$1" = "-only_floppy" ]; then
    shift
    ONLY_FLOPPY="yes"
  elif [ "$1" = "-c" -a $# -gt 1 ]; then
    CONFDIR=$2
    shift 2
  else
    echo "Usage: bootcdwrite [-only_floppy] [-c <config directory>]"
    echo "  use man bootcdwrite to get help"
    echo "  and see $CONFDIR/bootcdwrite.conf"
    exit 1
  fi
done

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

if [ ! -f $CONFDIR/bootcdwrite.conf  ]; then
  echo "No file $CONFDIR/bootcdwrite.conf" >&2
  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 ISO_ONLY SYSLINUX_SAVE ISOLINUX ARCH INITRD DEVFS TO_FSTAB TYP
COMPRESS"

unset $CONFVARS
. $CONFDIR/bootcdwrite.conf
. /usr/share/bootcd/bootcd-run.lib
. /usr/share/bootcd/bootcd-check.lib

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

if [ "$TYP" = "DVDPLUS" ]; then
  PROBLEM="You have defined TYP=DVDPLUS, but /usr/share/bootcd/bootcd-dvdplus.lib
  is not installed. Please apt-get bootcd-dvdplus."
  [ -f /usr/share/bootcd/bootcd-dvdplus.lib ] || err "$PROBLEM"
  . /usr/share/bootcd/bootcd-dvdplus.lib
fi

if [ "$ARCH" = "HPPA" ]; then
  PROBLEM="You have defined ARCH=HPPA, but /usr/share/bootcd/bootcd-hppa.lib is 
not installed. Please apt-get bootcd-hppa."
  [ -f /usr/share/bootcd/bootcd-hppa.lib ] || err "$PROBLEM"
  . /usr/share/bootcd/bootcd-hppa.lib
fi

CHANGES=$VAR/changes

if [ -e $VAR/cdimage.iso ] ; then
    echo "The image destination $VAR/cdimage.iso exists." | tee -a $ERRLOG
    echo "Delete $VAR/cdimage.iso and try again!" | tee -a $ERRLOG
    exit 1
fi

trap trapfunc 0 2

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

# Write Debug Information to Logfile
VERSION=$(COLUMNS=200 dpkg -l bootcd | tail -1 | awk '{print $3}')
echo "bootcd Version $VERSION" >>$ERRLOG
for i in $CONFVARS; do
  eval "echo $i \$$i" >>$ERRLOG 
done

warn_user
check_config
# We have to get the sizes (get_sizes) before before the final 
# check (check_sizes), because some variables with the value "auto"
# need the information to become either "yes" or "no".
get_sizes
check_arch
check_file_rc
check_compress
check_not2ram
check_cdfiles
check_kernel
check_initrd
[ "$ARCH" = "HPPA" ] && check_hppa
check_sizes
  
echo "--- Building Modifications ---" | tee -a $ERRLOG
run mkdir -p $VAR/mnt $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 mkdir $CHANGES/dev.ro
run chmod 755 $CHANGES/dev.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/share/bootcd
run cp /usr/share/bootcd/bootcd2disk $CHANGES/usr/bin/
run cp /usr/share/bootcd/bootcdflopcp $CHANGES/usr/bin/
run "cat /usr/share/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/share/bootcd/bootcd2disk.conf $CHANGES/etc.ro/bootcd/
run cp /usr/share/bootcd/bootcd-run.lib $CHANGES/usr/share/bootcd/

echo "KERNEL=$REL_KERNEL" >$CHANGES/etc.ro/bootcd/thisbootcd.conf
echo "INITRD=$REL_INITRD" >>$CHANGES/etc.ro/bootcd/thisbootcd.conf

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

if [ ! "$ONLY_FLOPPY" ]; then
  if [ "$SSHHOSTKEY" = "yes" ]; then
    # each CD gets a unique hostkey"

    # create_host_keys will only recreate keys, if they already exist.
    # So keys will be touched in new dir, if they existed in old dir.
    for i in ssh_host_key ssh_host_rsa_key ssh_host_dsa_key
    do
      if [ -f $SRCDI/etc/ssh/$i ]; then
        run mkdir -p $CHANGES/etc.ro/ssh
	touch $CHANGES/etc.ro/ssh/$i
      fi
    done

    create_host_keys $CHANGES/etc.ro/ssh

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

if [ "$ARCH" != "HPPA" -a "$ISOLINUX" = "no" ]; then
  do_syslinux
fi

if [ "$ISOLINUX" != "no" ]; then
  do_isolinux
fi

# only create fastboot file, if there are no additional mount points
if [ ! "$TO_FSTAB" ]; then
	run touch $CHANGES/fastboot
fi

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

  if [ "$DEVFS" = "yes" ]; then 
    CPIODIR="home root etc"
  else
    CPIODIR="home root etc dev"
  fi
  for i in $CPIODIR; do 
    run "cd $SRCDISK; find $i | $FG | cpio --quiet -pdum $VAR/ram1"

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

  ignore "cpio: .*: truncating inode number"
  run "cd $VAR/ram1
       find . |cpio --quiet --format=crc -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 -pdum $VAR/ram2"

  ignore "cpio: .*: truncating inode number"
  run "cd $VAR/ram2
       find . |cpio --quiet --format=crc -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
  
  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
  
  # Are there Files in $SRCDI 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 $SRCDI$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

  if [ "$DEVFS" = "yes" ]; then
    MKISODEVFS=""
  else
    MKISODEVFS="/dev.ro/=$SRCDI/dev"
  fi

  if [ "$COMPRESS" = "no" ]; then
    if [ "$ISOLINUX" = "yes" ]; then
      cdimage_isolinux
    elif [ "$ARCH" = "HPPA" ]; then
      cdimage_hppa
    else
      cdimage_normal
    fi
  else
    if [ "$ISOLINUX" = "yes" ]; then
      cdimage_compressed_isolinux
    elif [ "$ARCH" = "HPPA" ]; then
      cdimage_compressed_hppa
    else
      cdimage_compressed_normal
    fi  
  fi
  
  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 [ "$ISO_ONLY" = "no" ]; then
    if [ "$BLANKING" != "no" ]; then
      if [ "$TYP" = "DVDPLUS" ]; then
        blank_dvdplus
      else
        blank_cd
      fi
    fi
  fi
  
  if [ "$ISO_ONLY" = "no" ]; then
    if [ "$TYP" = "DVDPLUS" ]; then
      write_dvdplus
    else
      write_cd
    fi
  else
    mv $VAR/cdimage $VAR/cdimage.iso
  fi

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
