#!/bin/bash

# This file is part of Mkat
#
# Copyright (C) 2004, 2005 Dmitry Maksyoma <ledestin at amur.ru>.
#
# Mkat is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
# USA.

#1. Make iso
#2. Burn iso
#3. Add the burned CD to the catalog
#4. Compare files on the CD with the original files

RCFILE=mkatrc 
[ -f /etc/$RCFILE ] && source /etc/$RCFILE
[ -f ~/.$RCFILE ] && source ~/.$RCFILE

#construct lockfile name following this template: ".$FILE.lock"
ISO_DIR="${ISO_IMAGE%/*}"
[ "$ISO_IMAGE" = "$ISO_DIR" ] && ISO_DIR=
LOCKFILE="${ISO_DIR:+$ISO_DIR/}.${ISO_IMAGE##*/}.lock"

#define constants
RET='
'

function usage {
  echo "usage: $0 [options] <label> <file>..."
  echo "  -n		    print estimated image size, exit"
  echo "  -sSPEED	    add 'speed=SPEED' to cdrecord parameters"
  echo "  -c		    add 'blank=fast' to cdrecord parameters"
  echo "  -o		    add '-overburn -dao' to cdrecord parameters"
  echo "  -rCDREC_OPTS	    pass parameters to cdrecord"
  echo "  -iMKIMG_OPTS	    pass parameters to image making program"
  echo "  -mMKAT_OPTS       pass parameters to mkat"
  echo "      --noimg	    don't create image, just burn"
  echo "      --nocat	    skip catalog"
  echo "      --nocheck	    skip afterburn check"
  echo "      --dbcheck	    check if the files are in mkat db"
  echo "  -y, --yes	    don't ask questions"
  echo "      --simulate    print only, --debug implied"
  echo "      --debug	    how stuff works"
  echo "  -h, --help	    print this help"
  exit $1
}

function debug {
  [ -z $DEBUG ] || echo "$@"
}

found=1
while [ $found ]; do
  case "$1" in
    "-h"|"--help") usage 0 ;;
    "-n") PRINT_ONLY=1 ;;
    "-o") CDREC_OPTS="$CDREC_OPTS -overburn -dao" ;;
    "--noimg") SKIP_MKIMAGE=1 ;;
    "--nocat") SKIP_CATALOG=1 ;;
    "--nocheck") SKIP_CHECK=1 ;;
    "--dbcheck") DB_CHECK=1 ;;
    "-y"|"--yes") NO_QUESTIONS=1 ;;
    "--simulate") SIMULATE=1; DEBUG=1 ;;
    "--debug") DEBUG=1 ;;
    "-c") CDREC_OPTS="$CDREC_OPTS blank=fast" ;;
       *) unset found ;;
  esac
  [ "${1:0:2}" = "-r" ] && { CDREC_OPTS="$CDREC_OPTS ${1:2}"; found=1; }
  [ "${1:0:2}" = "-m" ] && { MKAT_OPTS="${1:2}"; found=1; }
  [ "${1:0:2}" = "-i" ] && { MKISO_OPTS="$MKISO_OPTS ${1:2}"; found=1; }
  [ "${1:0:2}" = "-s" ] && { CDREC_OPTS="$CDREC_OPTS speed=${1:2}"; found=1; }
  [ $found ] && shift;
done

#label and files must be provided
if [ -z $SKIP_MKIMAGE ]; then
  [ "$#" -lt 2 ] && {
    echo >&2 "not enough parameters"
    usage 1
  }
  #vars needed for $MKIMAGE_CMD
  LABEL="$1"; shift; FILES=("$@")
fi

#Check if files you're about to write are already archived (i.e. exist
#in mkat database)
if [ $DB_CHECK ]; then
  echo "Checking if the files are in mkat db"
  for f in "${FILES[@]}"; do
    mkat -m "$f"
    [ $? -eq 0 ] && ALREADY_IN_DB=1
  done
  if [ $ALREADY_IN_DB ]; then
    echo "Some files you are about to write are already in the mkat database." 
    read -p "Press Enter to write anyway or Control-C to abort"
    [ $? -ne 0 ] && exit
  fi
fi

set -e

#MAKE ISO IMAGE
if [ $PRINT_ONLY ]; then
  str=`mkisofs -print-size $MKISO_OPTS "${FILES[@]}"`
  echo "$str"
  size=`echo $str | tail -1`
  echo $(($size*2048/1024**2))Mb
  exit
elif [ -z $SKIP_MKIMAGE ]; then
  echo "making ISO image"
  eval "debug $MKIMAGE_CMD"
  if [ -z $SIMULATE ]; then
    [ -d "$TMP" ] || mkdir -p "$TMP"
    debug "checking for lockfile $LOCKFILE"
    set +e
    dotlockfile -c $LOCKFILE
    if [ $? -eq 0 ]; then
      echo "$ISO_IMAGE is locked, probably being burned now"
      exit 1
    fi
    set -e

    #possible security issue when using existing directory
    #I check that current UID is the owner and the directory isn't world
    #writable
    if [ -d "$TMP" ]; then
      stat=(`stat -c '%u %A' "$TMP"`)
      [ ${stat[0]} = $EUID ] || \
	{ echo >&2 "error: $TMP isn't owned by current UID: $UID"; exit 1;}
      [ ${stat[1]:$((-2)):1} = "-" ] || \
        { echo >&2 "error: $TMP is world writable"; exit 1;}
    else
      #set umask=0022 only if $TMP resides in /tmp
      saved_umask=`umask`
      expr match "$TMP" /tmp
      [ $? -eq 0 ] && umask 0022
      mkdir "$TMP"
      umask $saved_umask
    fi
    eval "$MKIMAGE_CMD"
  fi
fi

#BURN
if [ -z $NO_QUESTIONS ] && [ -z $SKIP_MKIMAGE ]; then
  read -p "Press Enter to proceed to burn or Control-C to abort"
fi
echo "BURN!"
unset IFS
cmd="cdrecord $CDREC_OPTS $ISO_IMAGE"; debug "$cmd"
if [ -z $SIMULATE ]; then
  debug "creating lock file before burning"
  dotlockfile $LOCKFILE && trap "dotlockfile -u $LOCKFILE" EXIT
  $cmd
  debug "releasing lock file"
  dotlockfile -u $LOCKFILE && trap - EXIT
fi

#CATALOG
if [ ! $SKIP_CATALOG ] && [ $CD ]; then
  echo "Catalog..."
  if [ $SIMULATE ]; then
    echo "mkat $MKAT_OPTS"
  else
    mkat $MKAT_OPTS
  fi
fi

IFS=$RET
#AFTERBURN CHECK
if [ ! $SKIP_CHECK ] && [ $CD ]; then
  set +e
  echo "Afterburn check..."
  if [ -z $SIMULATE ]; then
    for f in "${FILES[@]}"; do
      cmp "$f" "$CD/`basename "$f"`"
    done
  fi
fi

debug "going to sleep for $AUTOFS_DELAY seconds and eject"
[ -z $SIMULATE ] && sleep $AUTOFS_DELAY && eject
