#!/bin/sh
#-------------------------------------------------------------------------------
# saveUpgradeFiles.sh
# 
# This shell script is invoked to perform a save upgrade data of the HSC in
# preparation of an EC upgrade process. This script will be executed one time
# for each component implementing the 'Saveupgrade' Java interface.  See
# the file /com/ibm/hsc/websm/launch/hscmgt/SaveUpgradeData.Java for the 
# hardcoded list of classes which require data to be preserved between system
# upgrades.
#
# Note: The log generated by this script will always concatenate to itself.  It
#       should be erased by the 'restore' script on system boot.
# 
# Usage: saveUpgradeFiles <media type> <filename containing list of files to save>
#               <output archive filename>
#
# Return Codes:
# 1 - Error accessing required save update data logging directory
# 2 - Media is write-protected
# 3 - Error copying tar file to removable media
# 4 - Error mounting the media
# 5 - Error encountered executing the 'tar' command
# 6 - Error unmounting the media
# 7 - Error mounting protected hard disk partition (/mnt/upgrade)
# 8 - archive file does not exist on /mnt/upgrade prior to DVD copy
# 9 - checksum miscompare between file on /mnt/upgrade and file on DVD media

#---------------------------------------------------------------------------------
# directory and filename which records the save upgrade data actions.
#---------------------------------------------------------------------------------
LOGDIR=/var/hsc/log
LOG=$LOGDIR/saveUpgradeFiles.log

LOG_ERROR_LOG=/tmp/saveUpgradeFiles.log

# STDOUT directed to /tmp/mount_output + PID
MOUNT_OUTPUT=/tmp/mount_output$$
      
# common exit point for script
exit_cleanup() {
    rm -f $MOUNT_OUTPUT
    echo "saveUpgradeFiles script exiting, rc = $1." >> $LOG
    exit $1
}  

#-------------------------------------------------------------------------------
# calculate the checksum of the original archive file on harddisk and the one on
# the remote (DVD) media
#-------------------------------------------------------------------------------
function verifyDVDChecksum {

    LOCAL_ARCHIVE=$1
    REMOTE_ARCHIVE=$2
    funcRC=0
        
    # assume the (DVD) media is still mounted...
    echo "calculating checksum of local archive file, $1 ..." >> $LOG
    x=`/usr/bin/sum $1`
    echo "...local file checksum complete, value is --> <$x>, timestamp is `date`." >> $LOG
    
    echo "calculating checksum of remote archive file, $2 ..." >> $LOG
    y=`/usr/bin/sum $2`
    echo "...remote file checksum complete, value is --> <$y>, timestamp is `date`." >> $LOG
    
    if [ "$x" == "$y" ]; then
        # all is well, files match
        funcRC=0;
    else
        # miscompare, return anything non-zero
        funcRC=9;
    fi
    
    echo "Exiting verifyDVDChecksum, funcRC = $funcRC." >> $LOG
    return $funcRC
}  

#-------------------------------------------------------------------------------
# the target output media for saved data - 0=hard drive, 1=DVD-RAM
#-------------------------------------------------------------------------------
MEDIA_TYPE=$1

#-------------------------------------------------------------------------------
# the filename of the list of files to be saved for this subsystem.
#-------------------------------------------------------------------------------
INPUT_LIST=$2

#-------------------------------------------------------------------------------
# the output filename of the save upgrade data archive (tar file)
#-------------------------------------------------------------------------------
OUTPUT_ARCHIVE=$3

#-------------------------------------------------------------------------------
# the (hard drive) media mount point to which the save upgrade data is to be
# stored.  There should be an entry for this mountpoint in /etc/fstab
#-------------------------------------------------------------------------------
FIXED_MOUNTPOINT=/mnt/upgrade

#-------------------------------------------------------------------------------
# the mount point for the media to which the save upgrade data is to be stored.
# A corresponding device entry should exist for this mount point in /etc/fstab
# Note: even though we're using the DVD, the 'auto' option in /etc/fstab will
#       figure out that it's not a CDROM device, but actually a DVD
#-------------------------------------------------------------------------------
REMOVABLE_MOUNTPOINT=/media/cdrom

#
# Just in case we have NLS troubles reading system information...
#
LANG=en_US
export LANG


#-------------------------------------------------------------------------------
# Check if the directory for the log file exists.
#-------------------------------------------------------------------------------
if [ ! -d $LOGDIR ] ; then
   echo "=================================================================" > $LOG_ERROR_LOG
   echo -e "Save upgrade data log for `date`." >> $LOG_ERROR_LOG
   echo "Save upgrade data log directory, <$LOGDIR>, does not exist. Program exiting" >> $LOG_ERROR_LOG
   exit_cleanup 1
fi


#-------------------------------------------------------------------------------
# Start a new log to record save upgrade data actions.
#-------------------------------------------------------------------------------
echo "=================================================================" >> $LOG
echo -e "Save Upgrade Data log for `date`." >> $LOG
echo -e "   Processing $INPUT_LIST..." >> $LOG
echo >> $LOG
echo "Input parameters are: $1, $2, and $3" >> $LOG


#-------------------------------------------------------------------------------
# Query the save upgrade "option" and process accordingly
#-------------------------------------------------------------------------------
if [ $MEDIA_TYPE -eq 0 ]; then

   #
   # First, check if list of files to save ($INPUT_LIST) is null. If so,
   # exit this processing with 0 return code.  We'll assume there are
   # just no files to save and an exception would have been generated
   # prior to calling this script if there actually was a problem
   # generating this list.
   #
   if [ ! -s $INPUT_LIST ]; then
      echo "List of files to save, $INPUT_LIST, is empty. Exiting script" >> $LOG
      exit_cleanup 0
   fi

   #
   # Save to hard disk
   #
   MOUNTPOINT=$FIXED_MOUNTPOINT

   #----------------------------------------------------------------------------
   # Mount the media. Fixed disk in this case, /dev/hda2 possibly.
   #----------------------------------------------------------------------------
   mount -v $MOUNTPOINT > $MOUNT_OUTPUT 2>&1
   MNTRC=$?
   if [ $MNTRC -ne 0 ] ; then

      #-------------------------------------------------------------------------
      # write protect errors? Should never see this against the hard disk
      #-------------------------------------------------------------------------
      if grep "write-protected" $MOUNT_OUTPUT; then
         echo "The mountpoint, $MOUNTPOINT, is write protected" >> $LOG
         exit_cleanup 2
      fi

      #-------------------------------------------------------------------------
      # already mounted?  Not an error, but a non-zero return code.  Continue
      #-------------------------------------------------------------------------
      if grep "already mounted" $MOUNT_OUTPUT; then
         echo "The mountpoint, $MOUNTPOINT, is already mounted.  Continuing..." >> $LOG

      #-------------------------------------------------------------------------
      # other errors?
      #-------------------------------------------------------------------------
      else
         echo "The mountpoint, $MOUNTPOINT, cannot be mounted.  Error is $MNTRC" >> $LOG
         exit_cleanup 7
      fi
      
   fi
   echo "Media mounted at $MOUNTPOINT." >> $LOG

   #----------------------------------------------------------------------------
   # Form the name of the archive file
   #----------------------------------------------------------------------------
   ARCHIVE="$MOUNTPOINT/$OUTPUT_ARCHIVE"
   echo "archive file is $ARCHIVE." >> $LOG

   #----------------------------------------------------------------------------
   # This is it. Do the actual 'tar' of the file list and create the archive
   # file (written to an ext2 filesystem)
   #----------------------------------------------------------------------------
   echo "command issued is 'tar -cvPf $ARCHIVE --files-from $INPUT_LIST --ignore-failed-read >> $LOG'" >> $LOG
   tar -cvPf $ARCHIVE --files-from $INPUT_LIST --ignore-failed-read >> $LOG

   TARRC=$?
   if [ $TARRC -ne 0 ] ; then
      #-------------------------------------------------------------------------
      #  Error during 'tar' processing.  Clean up and exit with rc.
      #-------------------------------------------------------------------------
      echo "An error occurred while executing the 'tar' command, rc=$TARRC" >>$LOG
      umount -v $MOUNTPOINT > $MOUNT_OUTPUT 2>&1
      if [ $? -ne 0 ] ; then
         echo "'tar' error. Couldn't unmount the media, rc = $?." >> $LOG
      fi

      exit_cleanup 5
   else
      #-------------------------------------------------------------------------
      #  Hurray! 'tar' processing succeeded.  Clean up and exit.
      #-------------------------------------------------------------------------
      echo "'tar' processing successfully completed, rc=$TARRC" >>$LOG
      umount $MOUNTPOINT
      if [ $? -ne 0 ] ; then
         echo "No 'tar' error, but can't unmount the media, rc = $?." >> $LOG
         exit_cleanup 6
      else
         echo "Successful completion. Save Upgrade Data archived to fixed disk." >> $LOG
         exit_cleanup 0
      fi
   fi

else
   #----------------------------------------------------------------------------
   # Output to DVD
   #----------------------------------------------------------------------------
   MOUNTPOINT=$REMOVABLE_MOUNTPOINT

   #----------------------------------------------------------------------------
   # Mount the (DVD_RAM) media and check for errors.
   #----------------------------------------------------------------------------
#   mount -v $MOUNTPOINT > $MOUNT_OUTPUT 2>&1
   # specifically use UDF, do not rely on filesystem "guessing" or /etc/fstab content
   mount -t udf -v /dev/cdrom /mnt/cdrom > $MOUNT_OUTPUT 2>&1
   
   MNTRC=$?
   if [ $MNTRC -ne 0 ]; then

      #-------------------------------------------------------------------------
      # write protect errors?
      #-------------------------------------------------------------------------
      if grep "write-protected" $MOUNT_OUTPUT; then
         echo "The mountpoint, $MOUNTPOINT, is write protected" >> $LOG
         exit_cleanup 2
      fi

      #-------------------------------------------------------------------------
      # already mounted?  Not an error, but a non-zero return code.  Continue
      #-------------------------------------------------------------------------
      if grep "already mounted" $MOUNT_OUTPUT; then
         echo "The mountpoint, $MOUNTPOINT, is already mounted.  Continuing..." >> $LOG

      #-------------------------------------------------------------------------
      # other error?  Game over.
      #-------------------------------------------------------------------------
      else
         echo "The mountpoint, $MOUNTPOINT, cannot be mounted.  Error is $MNTRC" >> $LOG
         exit_cleanup 4
      fi
      
   fi
   echo "Media mounted at $MOUNTPOINT." >> $LOG

   #----------------------------------------------------------------------------
   # Form the name of the archive file
   #----------------------------------------------------------------------------
   ARCHIVE="$MOUNTPOINT/$OUTPUT_ARCHIVE"
   echo "archive file is $ARCHIVE." >> $LOG


   #----------------------------------------------------------------------------
   # If executing in "PE" mode, the option to save upgrade data to DVD-RAM is
   # available. Since this script will be called twice when the 'Save to DVD'
   # button is selected, simply copy the files from the hard drive that were
   # created during the first pass.
   #
   # re-mount the fixed disk where the data is already stored
   #----------------------------------------------------------------------------
   mount -v $FIXED_MOUNTPOINT
   if [ $? -ne 0 ] ; then
      echo "Couldn't re-mount the media $FIXED_MOUNTPOINT for DVD copy. Error is $?" >> $LOG
      exit_cleanup 7
   fi

   #----------------------------------------------------------------------------
   # copy the data to DVD - assume it's been formatted
   #----------------------------------------------------------------------------
   if [ ! -f $FIXED_MOUNTPOINT/$OUTPUT_ARCHIVE ]; then
      echo "Archive file, $FIXED_MOUNTPOINT/$OUTPUT_ARCHIVE, does not exist on HMC hard drive." >> $LOG
      umount -v $REMOVABLE_MOUNTPOINT >> $LOG 2>&1
      umount -v $FIXED_MOUNTPOINT >> $LOG 2>&1
#      exit_cleanup 8
      exit_cleanup 0
   fi

   cp -fv $FIXED_MOUNTPOINT/$OUTPUT_ARCHIVE $ARCHIVE >> $LOG 2>&1

   if [ $? -ne 0 ] ; then
      echo "Error $? occurred while copying the save upgrade data archives to DVD." >> $LOG
      umount -v $REMOVABLE_MOUNTPOINT >> $LOG 2>&1
      umount -v $FIXED_MOUNTPOINT >> $LOG 2>&1
      exit_cleanup 3
   else
      # Verify the data was copied correctly. This is potentially an issue since the
      # device may not be mounted synchronously and media errors could occur when the
      # I/O buffers are flushed. 'sync', then do a checksum to be sure.
      echo "data copy to remote media complete..." >> $LOG
      /bin/sync
      echo "data sync complete, beginning to calculate checksums now... timestamp is `date`." >> $LOG

      verifyDVDChecksum $FIXED_MOUNTPOINT/$OUTPUT_ARCHIVE $ARCHIVE
      if [ $? -ne 0 ]; then
          # checksum miscompare
          echo "checksum miscompare!" >> $LOG
          umount -v $FIXED_MOUNTPOINT >> $LOG 2>&1
          umount -v $REMOVABLE_MOUNTPOINT >> $LOG 2>&1
          exit_cleanup 9
      fi

      #-------------------------------------------------------------------------
      #  Hurray! 'cp' processing succeeded.  Clean up and exit.
      #-------------------------------------------------------------------------
      umount -v $REMOVABLE_MOUNTPOINT >> $LOG 2>&1
      if [ $? -ne 0 ] ; then
         echo "No 'cp' error, but can't unmount the DVD, rc = $?." >> $LOG
         umount -v $FIXED_MOUNTPOINT >> $LOG 2>&1
         exit_cleanup 6
      fi

      umount -v $FIXED_MOUNTPOINT >> $LOG 2>&1
      if [ $? -ne 0 ] ; then
         echo "No 'cp' error, but can't unmount the source, $FIXED_MOUNTPOINT, rc = $?." >> $LOG
         exit_cleanup 0
      else
         echo "Successful completion - Save Upgrade Data copied to DVD." >> $LOG
         exit_cleanup 0
      fi
   fi
fi
