#!/bin/sh
#-------------------------------------------------------------------------------
# backuphdr.sh
# 
# This shell script is invoked to perform a backup of the HMC hard drive for Disaster
# Recovery purposes. All of the files that have changed since the code was installed
# on the hard disk will be placed into a compressed tar file.
#
# Based on the arguements passed into this program, the output file will either
# be written to DVD media, copied to a mounted remote server resource, or ftp'd
# to a remote FTP server.
#
# 
# Usage: backuphdr <archive name>  (in the format: <optional directory>/HMCBackup_yyyyMMdd.HHmmss.tgz)
#                  <backup type>   (0=DVD, 1=remote mount, 2=ftp, 5=none)
#
#                  if type 1...
#                  <server>        (remote server name)
#                  <resource>      (remote server resource)
#                  <fstype>        (file system type)
#                  <options>       (other 'mount' command options)
#
#                  if type 2...
#                  <server>        (remote ftp server)
#                  <userID>        (userID for ftp access)
#                  <password>      (password for ftp access)
#                   
#                  if type 5...    reset backup task lock
#
# Return Codes:
# 1 - error locating required backup directory
# 2 - unable to start portmap
# 3 - error unmounting DVD media
# 4 - media is write-protected
# 5 - error mounting DVD media
# 6 - other errors ('tar' command error)
# 7 - file could not be written to DVD
# 8 - invalid backup type (not 0, 1, or 2)
# 9 - checksum miscompare between local archive file and DVD copy
# 10 - NFS error mounting remote filesystem
# 11 - NFS error, file could not be written to mounted filesystem
# 12 - NFS error, could not switch to target directory for file copy
# 21 - ftp, not logged in
# 22 - ftp, generic login failed
# 23 - ftp, connection refused
# 24 - ftp, unknown remote host
# 25 - ftp, not connected
# 26 - ftp, permission denied
# 27 - ftp, other error(s)
# 28 - ftp, could not switch to target directory for file transfer
# 29 - ftp, disk full
# 30 - backup task already in progress
# 31 - could not create task lock
# 32 - could not remove expired task lock
# 39 - not enough free space remaining on the DVD for archive file copy
# 40 - ctbackup program execution failure
# 50 - ftp - 550/553 errors (permission, no file) errors

osname=`uname`

# common exit point for script
exit_cleanup() {
    rm -f $MOUNT_OUTPUT
    rm -f /boot/new_hmc_kernel
    rm -f $TMP_FTP

    # clean up the lock file, if required
    if [ $1 -ne 30 ]; then
        if [ -d /opt/hsc/data/backuphdr.lck ]; then
            rmdir /opt/hsc/data/backuphdr.lck
            rmRC=$?
            if [ $rmRC -ne 0 ]; then
                echo "error removing backup task lock during common cleanup, rc = $rmRC." >> $LOG
            else
                echo "successful removing backup task lock during common cleanup, exiting task now..." >> $LOG
            fi
        else
            echo "backup task lock was not detected on this HMC." >> $LOG
        fi
    fi


    if [ $BACKUP_TYPE -eq 0 ]; then
        /sbin/hdparm -d0 $DVD_DEV >/dev/null 2>&1
    fi

    # This temp ftp log file may or may not exist. Ensure it is removed prior to
    # exiting this script. Special case here first though - if exiting with any of the ftp
    # error codes, append the ftp.log file to the main backup task log prior to erasing.
    # Do this just in case we want to log this information back in the calling thread.
    case $1 in
        21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 50)
        echo "----- begin ftp.log -----" >> $LOG
        x=`cat /var/hsc/log/ftp.log`
        echo "$x" >> $LOG
        echo "----- end ftp.log -----" >> $LOG
    esac
    rm -f /var/hsc/log/ftp.log

    # remove boot.local processing file
    rm -f /opt/hsc/data/.postRestore

    # remove the test accesss file as well
    rm -f $DUMP_DIR/$TEST_ACCESS_FILE

    if [ $1 -eq 0 ]; then
        echo "Backup of critical console data completed successfully on `date`." >> $LOG
    else
        echo "Backup of critical console data exited with rc=$1 on `date`." >> $LOG

        # hook for MM error handling
        if [ -f /opt/esshmc/bin/mmbackupfailed ]; then
            /opt/esshmc/bin/mmbackupfailed $1
        fi
    fi

    # remove log file pointer file
    rm -f /tmp/backuphdr.log.ptr

    # rename working log file to final version
    mv $LOG $FINALLOG

    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
        funcRC=9;
    fi

    echo "Exiting verifyDVDChecksum, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# check contents of ftp log file when sending data
#-------------------------------------------------------------------------------
function checkForFtpDataTransferErrors {

    FTP_LOG=$1
    funcRC=0

    # look for server filesytem full/error codes first
    grep -q -i "^452" $FTP_LOG 2>&1 >/dev/null || grep -q -i "^451" $FTP_LOG 2>&1 >/dev/null || grep -q -i "^552" $FTP_LOG 2>&1 >/dev/null
    if [ $? -eq 0 ]; then
        funcRC=29
    else
        # Requested action not taken. File name not allowed (permission errors?)
        grep -q -i "^553" $FTP_LOG 2>&1 >/dev/null
        if [ $? -eq 0 ]; then
            funcRC=50
        else
            # Requested action not taken. File unavailable (e.g., file not found, no access)
            grep -q -i "^550" $FTP_LOG 2>&1 >/dev/null
            if [ $? -eq 0 ]; then
                funcRC=28
            else
                # login check...
#                grep -q -i "Login failed" $FTP_LOG 2>&1 >/dev/null || grep -q -i "Login incorrect" $FTP_LOG 2>&1 >/dev/null || grep -q -i "Identification failed" $FTP_LOG 2>&1 >/dev/null
                grep -q -i "^530" $FTP_LOG 2>&1 >/dev/null
                if [ $? -eq 0 ]; then
                    # error logging in - bad user/password(?)
                    funcRC=22
                else
                    # no critical errors detcted so far - see if operation succeeded.
                    grep -q -i "^226" $FTP_LOG 2>&1 >/dev/null || grep -q -i "^250" $FTP_LOG 2>&1 >/dev/null
                    if [ $? -eq 0 ]; then
                        funcRC=0
                        rm -f $FTP_LOG
                    else
                        # If no file transfer, look for (known) errors
                        grep -q -i "not logged in" $FTP_LOG > /dev/null 2>&1
                        if [ $? -eq 0 ]; then
                            # Oops - error logging in
                            funcRC=21
                        else
                            grep -q -i "Connection refused" $FTP_LOG > /dev/null 2>&1
                            if [ $? -eq 0 ]; then
                                # Oops - error accessing server
                                funcRC=23
                            else
                                grep -q -i "unknown host" $FTP_LOG > /dev/null 2>&1
                                if [ $? -eq 0 ]; then
                                    # Oops - error accessing server
                                    funcRC=24
                                else
                                    grep -q -i "Not connected" $FTP_LOG > /dev/null 2>&1
                                    if [ $? -eq 0 ]; then
                                        # Oops - error accessing server
                                        funcRC=25
                                    else
                                        # last check for permission issues
                                        grep -q -i "Permission denied" $FTP_LOG > /dev/null 2>&1
                                        if [ $? -eq 0 ]; then
                                            # permission issues
                                            funcRC=26
                                        else
                                            # All other errors here
                                            funcRC=27
                                        fi
                                    fi 
                                fi
                            fi
                        fi   
                    fi
                fi
            fi
        fi
    fi

    echo "Exiting checkForFtpDataTransferErrors, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# check contents of ftp log file when changing directories
#-------------------------------------------------------------------------------
function checkForFtpChdirError {

    FTP_LOG=$1
    funcRC=0

    # First check for some '5xx' error codes indicating the 'cd' comamnd failed
    # or file permission error. Then check for the connection/login errors
    # Requested action not taken. File name not allowed (permission errors?)
    grep -q -i "^553" $FTP_LOG 2>&1 >/dev/null
    if [ $? -eq 0 ]; then
        funcRC=50
    else
        grep -q -i "^550" $FTP_LOG 2>&1 >/dev/null
        if [ $? -eq 0 ]; then
            funcRC=28
        else
            # login check...
    #        grep -q -i "Login failed" $FTP_LOG 2>&1 >/dev/null || grep -q -i "Login incorrect" $FTP_LOG 2>&1 >/dev/null || grep -q -i "Identification failed" $FTP_LOG 2>&1 >/dev/null
            grep -q -i "^530" $FTP_LOG 2>&1 >/dev/null
            if [ $? -eq 0 ]; then
                # error logging in - bad user/password(?)
                funcRC=22
            else
                grep -q -i "^250" $FTP_LOG 2>&1 >/dev/null
                if [ $? -eq 0 ]; then
                    # Directory change ok
                    funcRC=0
                else
                    # Look for (known) errors
                    grep -q -i "not logged in" $FTP_LOG > /dev/null 2>&1
                    if [ $? -eq 0 ]; then
                        # Oops - error logging in
                        funcRC=21
                    else
                        grep -q -i "Connection refused" $FTP_LOG > /dev/null 2>&1
                        if [ $? -eq 0 ]; then
                            # Oops - error accessing server
                            funcRC=23
                        else
                            grep -q -i "unknown host" $FTP_LOG > /dev/null 2>&1
                            if [ $? -eq 0 ]; then
                                # Oops - error accessing server
                                funcRC=24
                            else
                                grep -q -i "Not connected" $FTP_LOG > /dev/null 2>&1
                                if [ $? -eq 0 ]; then
                                    # Oops - error accessing server
                                    funcRC=25
                                else
                                    # last check for permission issues
                                    grep -q -i "Permission denied" $FTP_LOG > /dev/null 2>&1
                                    if [ $? -eq 0 ]; then
                                        # permission issues
                                        funcRC=26
                                    else
                                        # All other errors here
                                        funcRC=27
                                    fi 
                                fi 
                            fi
                        fi
                    fi   
                fi
            fi
        fi
    fi

    echo "Exiting checkForFtpChdirError, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# test if media is able to be mounted and test data copied to it
#-------------------------------------------------------------------------------
function checkDVD_Access {

    LOCAL_DIR=$1
    FILE=$2
    MTPT=$3
    funcRC=0

    # Check to see if media is already mounted - if so then unmount it
    if grep "$MTPT" /etc/mtab; then # Media is already mounted
        if ! umount $MTPT >> $LOG 2>&1; then
            echo "Couldn't unmount the media, $MTPT." >> $LOG
            funcRC=3
        fi
    fi

    # Mount the media and check for write-protect
#    mount -v $MTPT > $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
    if [ $? -eq 0 ]; then
        echo "Mounted the DVD media ok." >> $LOG
        if grep "write-protected" $MOUNT_OUTPUT; then
            echo "The media is write-protected." >> $LOG
            funcRC=4
        else
            # attempt to copy some test data
            if [ "$osname" != "AIX" ]; then
                cp -v $LOCAL_DIR/$FILE $MTPT >> $LOG 2>&1
            else
                cp -v $LOCAL_DIR/$FILE $MTPT >> $LOG 2>&1
            fi
            if [ $? -eq 0 ]; then
                # destination is OK. Remove the test file
                rm -f $MTPT/$FILE
                funcRC=0
            else
                # pretty vague/generic copy error here. Should refine ASAP. Diskspace?
                funcRC=7
            fi
        fi

        # all done with media
        umount $MTPT
    else
        echo "Couldn't mount the media, $MTPT." >> $LOG
        funcRC=5
    fi

    echo "Exiting checkDVD_Access, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# test if mountpoint reachable and test data copied to it
#-------------------------------------------------------------------------------
function checkMount_Access {

    LOCAL_DIR=$1
    FILE=$2
    NFS_SERVER=$3
    RESOURCE=$4
    FSTYPE=$5
    OPTIONS=$6
    REMOTE_DIR=$7
    funcRC=0

    # make test mount point
    if [ -d /mnt/remote ]; then
        echo "remote mount point already exists, continuing...." >> $LOG
    else
        mkdir -p /mnt/remote
    fi
    MTPT=/mnt/remote

    # attempt to mount
    # NFS example:
    #   mount -o vers=2 -o proto=udp <server>:<resource> <mount point>
    # Samba example:
    #   mount -t smbfs -o username=xxx,password=yyy //<server>/<resource> <mount point>
    mount -v $OPTIONS $NFS_SERVER:$RESOURCE $MTPT >> $LOG 2>&1
    mountRC=$?

    if [ $mountRC -eq 0 ]; then

        # Good mount. Now see if we need to switch directories
        if [[ "$REMOTE_DIR" == "" || "$REMOTE_DIR" == "." ]]; then
            echo "mount access test does not require a directory change." >> $LOG

            # ensure it's not a '.' char
            REMOTE_DIR=""
        else
            echo "mount access test requires a change to directory named <$DIRECTORY>." >> $LOG
            cd $MTPT/$REMOTE_DIR
            cdRC=$?
            if [ $cdRC != 0 ]; then
                funcRC=12
            else
                # Switch to a different directory so we can unmount (otherwise, umount fails due to "resource busy")
                cd /
            fi
        fi

        if [ $funcRC == 0 ]; then
            if [ "$osname" != "AIX" ]; then
                cp -v $LOCAL_DIR/$FILE $MTPT/$REMOTE_DIR >> $LOG 2>&1
            else
                cp -v $LOCAL_DIR/$FILE $MTPT/$REMOTE_DIR >> $LOG 2>&1
            fi
            if [ $? -eq 0 ]; then
                # destination is OK. Remove the test file
                rm -f $MTPT/$REMOTE_DIR/$FILE
                funcRC=0
            else
                # pretty vague/generic copy error here. Should refine ASAP. Diskspace? Or more likely,
                # permission issues
                funcRC=11
            fi
        fi

        umount $MTPT >> $LOG 2>&1
    else
        # unable to mount
        echo "an error occurred while attempting to mount the remote system, rc=$mountRC." >> $LOG
        funcRC=10
    fi

    echo "Exiting checkMount_Access, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# test if ftp server reachable and test data able to be sent to it
#-------------------------------------------------------------------------------
function checkFTP_Access {

    LOCAL_DIR=$1
    FILE=$2
    FTP_SERVER=$3
    USER=$4
    PASSWORD=$5
    REMOTE_DIR=$6
    funcRC=0

    FTP_LOG=/var/hsc/log/ftp.log

    # We'll need 2 separate ftp attempts here if offloading the data to a 
    # directory other than user's home dir.  First attempt is just to see
    # if we can 'cd' to the target dirctory.  If successful, then ftp the
    # actual data.
    #
    # Update here - change things a bit for 'ncftp' usage. Note that we're
    # now deleting the 'test access file' prior to exiting this routine.
    # Modify non-AIX path only for now...
    if [[ "$REMOTE_DIR" == "" || "$REMOTE_DIR" == "." ]]; then
        echo "ftp access test does not require a directory change." >> $LOG

        if [ "$osname" != "AIX" ]; then
            echo "host $FTP_SERVER" > $TMP_FTP
            echo "user $USER" >> $TMP_FTP
            echo "pass $PASSWORD" >> $TMP_FTP

            OLDPWD=`pwd`
            cd $LOCAL_DIR
            LANG=en_US $FTP_CMD -f $TMP_FTP -d $FTP_LOG -V -t $TIMEOUT -o useMDTM=0 -Y "DELE $FILE" . $FILE
            cd $OLDPWD
#            /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#bin
#lcd $LOCAL_DIR
#put $FILE
#quit
#EOF
        else
            /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
bin
lcd $LOCAL_DIR
put $FILE
quit
EOF
        fi
        # Check for errors during the transfer
        checkForFtpDataTransferErrors $FTP_LOG
        funcRC=$?

    else
        # case here where remote target is not in user's home dir...
        echo "ftp access test requires a change to directory named <$REMOTE_DIR>." >> $LOG
        
        if [ "$osname" != "AIX" ]; then
            echo "check remote directory access during data transfer..." >> $LOG
#            /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#cd $REMOTE_DIR
#quit
#EOF
        else
            /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
cd $REMOTE_DIR
quit
EOF
        fi

        # First check for 'cd' errors (and the usual connection/login errors...)
        if [ "$osname" != "AIX" ]; then
            # bypass original ftp chdir checking now that we're using ncftp...
            funcRC=0
        else
            checkForFtpChdirError $FTP_LOG
            funcRC=$?
        fi

        if [ $funcRC == 0 ]; then
            # repeat ftp with actual data transfer
            if [ "$osname" != "AIX" ]; then
                echo "host $FTP_SERVER" > $TMP_FTP
                echo "user $USER" >> $TMP_FTP
                echo "pass $PASSWORD" >> $TMP_FTP

                OLDPWD=`pwd`
                cd $LOCAL_DIR
                LANG=en_US $FTP_CMD -f $TMP_FTP -d $FTP_LOG -V -t $TIMEOUT -o useMDTM=0 -Y "DELE $FILE" $REMOTE_DIR $FILE
                cd $OLDPWD
#                /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#bin
#lcd $LOCAL_DIR
#cd $REMOTE_DIR
#put $FILE
#quit
#EOF
            else
                /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
bin
lcd $LOCAL_DIR
cd $REMOTE_DIR
put $FILE
quit
EOF
            fi
            # now check for data transfer errors
            checkForFtpDataTransferErrors $FTP_LOG
            funcRC=$?
        fi
    fi

    echo "Exiting checkFTP_Access, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# offload backup archive file to DVD
#-------------------------------------------------------------------------------
function copyBackupArchiveToDVD {

    LOCAL_DIR=$1
    FILE=$2
    MTPT=$3
    funcRC=0


    # copy the dump
#    mount $MTPT
    # Specifically use UDF, do not rely on filesystem "guessing" or /etc/fstab content.
    #
    # Also here we do not require verbose/redirected stdout since the media has already
    # been mounted/unmounted prior to this - the mount *should* work with no problems...
    mount -t udf /dev/cdrom /mnt/cdrom
    if [ $? -eq 0 ]; then
        #
        # Special case for local media: copy to DVD media as hardcoded filename 'backuphdr.tgz'.
        # Do this so the file is overwritten each time on the media.
        #
        /sbin/hdparm -d1 $DVD_DEV >/dev/null 2>&1

        # check free media space
        x=`df --block-size=1 --type=udf -l | tail -1 | awk '{print $4}'`
        echo "Free space on DVD-RAM is $x bytes." >> $LOG

        # see if prior backuphdr.tgz exists on the media
        if [ -f $MTPT/backuphdr.tgz ]; then
            y=`ls -l $MTPT/backuphdr.tgz | awk '{print $5}'`
            echo "existing backuphdr.tgz archive file size on the media is $y bytes." >> $LOG
        else
            y=0
            echo "no existing backuphdr.tgz archive file size on the media." >> $LOG
        fi

        currentArchiveFilesize=`ls -l $LOCAL_DIR/$FILE | awk '{print $5}'`
        echo "new archive file to offload is $currentArchiveFilesize bytes." >> $LOG

        totalFreeMediaSpace=$((x+y))

        if [ "$totalFreeMediaSpace" -gt "$currentArchiveFilesize" ]; then
            # there should be enough room on the media to copy the archive file...
            if [ "$osname" != "AIX" ]; then
                cp -v $LOCAL_DIR/$FILE $MTPT/backuphdr.tgz >> $LOG 2>&1
            else
                cp -v $LOCAL_DIR/$FILE $MTPT/backuphdr.tgz >> $LOG 2>&1
            fi
            if [ $? -eq 0 ]; then

                # semi-new req'ment here: do checksum of the archive file the was just offloaded to
                # DVD and compare it to the original archive.  Problems may/may not show up when we
                # remove the DVD mount 'sync' option in /etc/fstab if using "bad" media
                echo "archive file appeared to copy successfuly to DVD media,. 'cp' rc = 0, timestamp is `date`." >> $LOG

                # sync (flush) the data and checksum. NOTE: backup progress monitoring thread triggers off
                # exact text in below 'echo' cmd
                /bin/sync
                echo "data sync complete, beginning to calculate checksums now... timestamp is `date`." >> $LOG

                verifyDVDChecksum $LOCAL_DIR/$FILE $MTPT/backuphdr.tgz
                if [ $? -eq 0 ]; then
                    # all's well in Mudville...
                    funcRC=0
                else
                    # checksum miscompare
                    funcRC=9
                fi
            else
                # pretty vague/generic copy error here. Should refine ASAP. Diskspace?
                funcRC=7
            fi
        else
           # out of space on the media
           echo "Not enough space remaining on the offload media." >> $LOG
           funcRC=39
        fi


        # all done with media
        umount $MTPT
    else
        # unable to mount the DVD media
        funcRC=5
    fi

    # remove the working archive file
    rm -f $LOCAL_DIR/$FILE

    echo "Exiting copyBackupArchiveToDVD, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# offload backup archive file to mounted (NFS) server
#-------------------------------------------------------------------------------
function copyBackupArchiveToMount {

    LOCAL_DIR=$1
    FILE=$2
    NFS_SERVER=$3
    RESOURCE=$4
    FSTYPE=$5
    OPTIONS=$6
    REMOTE_DIR=$7
    funcRC=0

    # set local mount point - this directory on the HMC should be established by now
    MTPT=/mnt/remote

    # attempt to mount
    # NFS example:
    #   mount -o vers=2 -o proto=udp <server>:<resource> <mount point>
    # Samba example:
    #   mount -t smbfs -o username=xxx,password=yyy //<server>/<resource> <mount point>
    mount -v $OPTIONS $NFS_SERVER:$RESOURCE $MTPT >> $LOG 2>&1
    mountRC=$?

    if [ $mountRC -eq 0 ]; then

        # Good mount. Check on directory change again
        if [[ "$REMOTE_DIR" == "" || "$REMOTE_DIR" == "." ]]; then
            echo "actual copy of data does NOT requires a directory change." >> $LOG

            # ensure it's not a '.' char
            REMOTE_DIR=""
        else
            echo "actual copy of data requires a directory change to $REMOTE_DIR." >> $LOG
            cd $MTPT/$REMOTE_DIR
            cdRC=$?
            if [ $cdRC != 0 ]; then
                funcRC=12
            else
                # Switch to a different directory so we can unmount (otherwise, umount fails due to "resource busy")
                cd /
            fi
        fi

        if [ $funcRC == 0 ]; then
            if [ "$osname" != "AIX" ]; then
                cp -v $LOCAL_DIR/$FILE $MTPT/$REMOTE_DIR >> $LOG 2>&1
            else
                cp -v $LOCAL_DIR/$FILE $MTPT/$REMOTE_DIR >> $LOG 2>&1
            fi
            if [ $? -eq 0 ]; then
                funcRC=0
            else
                # pretty vague/generic copy error here. Should refine ASAP. Diskspace? Or more likely,
                # permission issues
                funcRC=11
            fi
        fi

        umount $MTPT
    else
        # unable to mount
        echo "an error occurred while attempting to mount the remote system, rc=$mountRC." >> $LOG
        funcRC=10
    fi

    # remove the working archive file
    rm -f $LOCAL_DIR/$FILE

    echo "Exiting copyBackupArchiveToMount, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# offload backup archive file to ftp server
#-------------------------------------------------------------------------------
function ftpBackupArchiveToServer {

    LOCAL_DIR=$1
    FILE=$2
    FTP_SERVER=$3
    USER=$4
    PASSWORD=$5
    REMOTE_DIR=$6
    TEST_ACCESS_FILE=$7
    funcRC=0

    FTP_LOG=/var/hsc/log/ftp.log

    # We'll need 2 separate ftp attempts here if offloading the data to a 
    # directory other than user's home dir.  First attempt is just to see
    # if we can 'cd' to the target dirctory.  If successful, then ftp the
    # actual data.
    if [[ "$REMOTE_DIR" == "" || "$REMOTE_DIR" == "." ]]; then
        echo "ftp of the backup archive file does not require a directory change." >> $LOG

        if [ "$osname" != "AIX" ]; then
            # With the change to 'ncftp', $TEST_ACCESS_FILE should have already been
            # deleted from the remote ftp server (via the '-Y' param)
            echo "host $FTP_SERVER" > $TMP_FTP
            echo "user $USER" >> $TMP_FTP
            echo "pass $PASSWORD" >> $TMP_FTP

            OLDPWD=`pwd`
            cd $LOCAL_DIR
            LANG=en_US $FTP_CMD -f $TMP_FTP -d $FTP_LOG -V -t $TIMEOUT -o useMDTM=0 . $FILE
            cd $OLDPWD
#            /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#bin
#lcd $LOCAL_DIR
#delete $TEST_ACCESS_FILE
#put $FILE
#quit
#EOF
        else
            /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
bin
lcd $LOCAL_DIR
delete $TEST_ACCESS_FILE
put $FILE
quit
EOF
        fi
        # Check for errors during the transfer
        checkForFtpDataTransferErrors $FTP_LOG
        funcRC=$?

    else
        # case here where remote target is not in user's home dir...
        echo "ftp of the backup archive file requires a change to directory named $REMOTE_DIR." >> $LOG

        if [ "$osname" != "AIX" ]; then
            echo "check remote directory access during data transfer..." >> $LOG
#            /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#cd $REMOTE_DIR
#quit
#EOF
        else
            /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
cd $REMOTE_DIR
quit
EOF
        fi
        # First check for 'cd' errors (and the usual connection/login errors...)
        if [ "$osname" != "AIX" ]; then
            # bypass original ftp chdir checking now that we're using ncftp...
            funcRC=0
        else
            checkForFtpChdirError $FTP_LOG
            funcRC=$?
        fi
        
        if [ $funcRC == 0 ]; then
            # repeat ftp with actual data transfer
            if [ "$osname" != "AIX" ]; then
                # same comment as above with regards to the $TEST_ACCESS_FILE
                echo "host $FTP_SERVER" > $TMP_FTP
                echo "user $USER" >> $TMP_FTP
                echo "pass $PASSWORD" >> $TMP_FTP

                OLDPWD=`pwd`
                cd $LOCAL_DIR
                LANG=en_US $FTP_CMD -f $TMP_FTP -d $FTP_LOG -V -t $TIMEOUT -o useMDTM=0 $REMOTE_DIR $FILE
                cd $OLDPWD
#                /usr/lib/mit/bin/ftp -n -u -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
#user $USER $PASSWORD
#bin
#lcd $LOCAL_DIR
#cd $REMOTE_DIR
#delete $TEST_ACCESS_FILE
#put $FILE
#quit
#EOF
            else
                /usr/bin/ftp -n -v $FTP_SERVER <<EOF 2>&1 > $FTP_LOG
user $USER $PASSWORD
bin
lcd $LOCAL_DIR
cd $REMOTE_DIR
delete $TEST_ACCESS_FILE
put $FILE
quit
EOF
            fi
            # now check for data transfer errors
            checkForFtpDataTransferErrors $FTP_LOG
            funcRC=$?
        fi
    fi

    # remove the working archive file
    rm -f $LOCAL_DIR/$FILE

    echo "Exiting ftpBackupArchiveToServer, funcRC = $funcRC." >> $LOG
    return $funcRC
}


#-------------------------------------------------------------------------------
# date -r for AIX (format is yyyymmddhhmm)
#-------------------------------------------------------------------------------
function date_r_aix {
    LANG=C ls -ld $1 | awk -v thisyear=$(date +"%Y") '
    BEGIN {
        Month="Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
        split(Month, array, ",");
    }
    {
        year = $8;
        month = $6;
        time[1] = 0;
        time[2] = 0;
        if (match(year, ":") > 0) {
            split(year, time, ":");
            year=thisyear;
        }
        for (cnt = 1; cnt <= 12; cnt++) {
            if (match(month, array[cnt]) > 0) {
                month = cnt;
                break;
            }
        }
        printf("%s%02s%02s%02s%02s\n", year, month, $7, time[1], time[2]);
    }'
}


#-------------------------------------------------------------------------------
# touch --date for AIX (format is yyyymmddhhmm)
#-------------------------------------------------------------------------------
function touch_aix {
    x=`rpm -qi $1 | grep "Install date:" | awk '
    BEGIN {
        Month="Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
        split(Month, array, ",");
    }
    {
        year = $8;
        month = $4;
        t = $6
        time[1] = 0;
        time[2] = 0;
        time[3] = 0;
        if (match(t, ":") > 0) {
            split(t, time, ":");
        }
        for (cnt = 1; cnt <= 12; cnt++) {
            if (match(month, array[cnt]) > 0) {
                month = cnt;
                break;
            }
        }
        printf("%s%02s%02s%02s%02s\n", year, month, $5, time[1], time[2]);
    }'`

    touch -t "$x" $2
}
# --------------  End Subroutines ----------------------------------------------



# --------------- BEGIN MAIN PROGRAM  ------------------------------------------

#-------------------------------------------------------------------------------
# directory and filename which records the backup actions.
#-------------------------------------------------------------------------------
LOGDIR=/var/hsc/log
FINALLOG=$LOGDIR/backuphdr.log
LOG=/tmp/backuphdr.log.$$

LOG_ERROR_LOG=/tmp/backuphdr.log
MOUNT_OUTPUT=/tmp/mountInfo

CTBACKUP=/usr/sbin/rsct/bin/ctbackup

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

#-------------------------------------------------------------------------------
# mount point: the mount point for the media to which the backup is to be stored
# ??? - this must be changed to mount point for DVD RAM
# mountpoint for DVD-RAM now defined (yes, it really is to /media/cdrom. 'fstab'
# entry wil automount correct physical device) 4/25/01 - SLF
#-------------------------------------------------------------------------------
DVD_MOUNTPOINT=/media/cdrom

#-------------------------------------------------------------------------------
# the filename and backup type of the HMC archive
#-------------------------------------------------------------------------------
IN_FILE=$1
ARCHIVE=`basename $IN_FILE`
DIRECTORY=`dirname $IN_FILE`
BACKUP_TYPE=$2

DUMP_DIR=/dump
TEST_ACCESS_FILE="RemoteAccessFile.Test"

FTP_CMD=/usr/bin/ncftpput
TIMEOUT=120

TMP_FTP=/tmp/ftp_file_$$
>$TMP_FTP
chmod 600 $TMP_FTP

# remove any prior archives that may exist. Remember that $1 arg is the
# backup archive name in the format: HMCBackup_yyyyMMdd.HHmmss.tgz
rm -f $DUMP_DIR/HMCBackup*

# generate some test data
echo "Testing access for backup archive file named $ARCHIVE on `date`." > $DUMP_DIR/$TEST_ACCESS_FILE

#-------------------------------------------------------------------------------
# a file whose date and time reflect when the build of the HMC was *installed* and
# a file which indicates the last RPM package installation date (see modHscBuildDat)
#-------------------------------------------------------------------------------
MARKER=/opt/hsc/com/ibm/hsc/websm/launch/hscmgt/hscbuild.dat
MARKER2=/opt/hsc/com/ibm/hsc/websm/launch/hscmgt/rpminst.dat


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

# Start log to record backup actions.
echo -e "Backup log for `date`, archive name is $ARCHIVE, type is $BACKUP_TYPE.\n" > $LOG

#
# If we see that the backup script is already executing, block this execution
# unless this backup lock file has expired
#
lockfilename="/opt/hsc/data/backuphdr.lck"
if [ $BACKUP_TYPE -ne 5 ]; then
    # mkdir has lock and is more atomic
    mkdir $lockfilename >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        # check the lock date
        typeset -i LOCK_DATE
        typeset -i NOW
        typeset -i DIFF
        typeset -i ONEDAY=60*60*24
        if [ "$osname" = "AIX" ]; then
            ONEDAY=10000
        fi

        if [ "$osname" != "AIX" ]; then
            LOCK_DATE=`date -r $lockfilename +%s`
            echo "current backup task lock date is `date -r $lockfilename`" >> $LOG
            NOW=`date +%s`
        else
            LOCK_DATE=`date_r_aix $lockfilename`
            echo "current backup task lock date is $LOCK_DATE" >> $LOG
            NOW=`date +m%d4/15/07M`
        fi
        echo "now is `date`" >> $LOG

        DIFF=$NOW-$LOCK_DATE

        if [ $DIFF -gt $ONEDAY ]; then
            # re-write a new lock file
            echo "backup task lock currently exits, but is past expiration date, re-writing" >> $LOG
            rmdir $lockfilename
            rc=$?
            if [ $rc -ne 0 ]; then
                echo "unexpected error $rc removing expired backup task lock, exiting task" >> $LOG
                exit_cleanup 32
            fi
            mkdir $lockfilename
            rc=$?
            if [ $rc -ne 0 ]; then
                echo "error $rc creating backup task lock, exiting task" >> $LOG
                exit_cleanup 31
            fi
        else
            #
            # Do not let users run multiple instances of this script!
            #
            echo "backup task lock currently exists on the HMC and is still valid" >> $LOG
            exit_cleanup 30
        fi
    else
        if [ "$osname" != "AIX" ]; then
            echo "backup task lock created with datestamp <`date -r $lockfilename`>" >> $LOG
        else
            TIMESTAMP=`date_r_aix $lockfilename`
            echo "backup task lock created with datestamp <$TIMESTAMP>" >> $LOG
        fi
    fi
    
else
    # remove internal lock file
    echo "input argument indicates removal of the backup task lock" >> $LOG

    # simply exit routine as if it successfuly ran and let common exit point remove this lock file
    exit_cleanup 0
fi


#
# Since the change to use a temporary log file was introduced, if this the backup task is launched
# from the GUI, then we need a way to determine this log file name.  Write this temp log filename
# to a fixed filename so that HMC GUI can monitor the backup status as before. Remove this file in
# common exit routine.
#
echo "$LOG" > /tmp/backuphdr.log.ptr


#
# Before doing any backup operations, test first if we can access the output
# device/resource/site
#
if [ $BACKUP_TYPE -eq 0 ]; then

    # output to DVD
    DVD_DEV=/dev/hdc
    HD=`/opt/hsc/bin/GetHD`
    if [ "$HD" != "hda" ]; then
        DVD_DEV=/dev/hda
    fi

    echo "input args are: <$1> <$2>" >> $LOG
    echo "testing DVD access..." >> $LOG
    checkDVD_Access $DUMP_DIR $TEST_ACCESS_FILE $DVD_MOUNTPOINT
    checkRC=$?
    if [ $checkRC -ne 0 ]; then
        exit_cleanup $checkRC
    fi

elif [ $BACKUP_TYPE -eq 1 ]; then

    # to remote (NFS/Samba) mount. Grab remaining program args from input
    echo "input args are: <$1> <$2> <$3> <$4> <$5> <$6>" >> $LOG
    echo "testing mount access..." >> $LOG
    SERVER=$3
    RESOURCE=$4
    FSTYPE=$5
    OPTIONS=$6

    # First determine if portmap is running - it should not be.
    # Then start that service for the duration of this script
    PORTMAP=/sbin/portmap
    PORTMAP_SHORT=portmap
    PID=`ps -ef | grep $PORTMAP_SHORT | grep -v grep | awk '{print $2}'`

    if test -n "$PID" ; then
        echo "portmap is currently executing, PID is $PID." >> $LOG
    else
        # echo No PID, so start the service.
        echo "about to start the portmap service..." >> $LOG
        /etc/init.d/portmap start
        RC=$?
        sleep 1

        # save away this PID for later process termination    
        NEW_PID=`ps -ef | grep $PORTMAP_SHORT | grep -v grep | awk '{print $2}'`

        if test -n "$NEW_PID" ; then
            echo "portmap started successfully, pid is $NEW_PID" >> $LOG
        else
            echo "unable to start the portmap daemon, rc = $RC" >> $LOG
            exit_cleanup 2
        fi
    fi

    checkMount_Access $DUMP_DIR $TEST_ACCESS_FILE $SERVER $RESOURCE "$FSTYPE" "$OPTIONS" $DIRECTORY
    checkRC=$?
    if [ $checkRC -ne 0 ]; then
        echo "error attempting mount access, killing portmap..." >> $LOG

        if test -n "$PID" ; then
            echo "was running prior to script execution - not terminating the service.">> $LOG
        else
            echo "about to terminate the portmap daemon...">> $LOG
            kill -9 $NEW_PID
        fi
        exit_cleanup $checkRC
    fi

elif [ $BACKUP_TYPE -eq 2 ]; then

    # to ftp server. Grab remaining program args from input
    echo "input args are: <$1> <$2> <$3> <$4> <password>" >> $LOG
    echo "testing ftp access..." >> $LOG
    SERVER=$3
    USERID=$4
    PASSWORD=$5
    checkFTP_Access $DUMP_DIR $TEST_ACCESS_FILE $SERVER $USERID $PASSWORD $DIRECTORY
    checkRC=$?
    if [ $checkRC -ne 0 ]; then
        exit_cleanup $checkRC
    fi

else
    # exit, error - invalid input parameter
    exit_cleanup 8
fi

#
# Defect 589978 - if the 'restore' and 'hmcRestore' are candidates for backup, there is the possibility
# that intermittent errors can occur during the actual restore of these files. When those files (the
# 'restore' script anyways) gets un-tar'd, depending on the "read caching"(?) of the "older" version'
# that is occurring simultaneously as that file is being replaced (via tar), the script may act in an
# abnormal way and simply terminate in strange ways. This leaves the restore processing incomplete.
#
# These 2 files should now be excluded from the backup list, but a copy of them will be made that
# will always be backup'd up. Those files will be post-processed during the boot.init flow
#
BACKUP_DIR=/opt/hsc/data/backup/stage
if [ ! -d $BACKUP_DIR ]; then
   mkdir -p $BACKUP_DIR
fi
echo -e "about to copy restore scripts to backup staging area...\n" >> $LOG
cp -vp /opt/hsc/bin/restore $BACKUP_DIR/restore.orig >> $LOG 2>&1
touch $BACKUP_DIR/restore.orig
cp -vp /etc/rc.d/hmcRestore $BACKUP_DIR/hmcRestore.orig >> $LOG 2>&1
touch $BACKUP_DIR/hmcRestore.orig

# Per defect 624653 - also make working copy of hwscan daemon which may or may not
# be archived. Note the exclusion of the original file later in this script after
# the system wide 'find' command has executed
if [ -f /usr/sbin/hwscand ]; then
    echo -e "about to copy hardware scan daemon to backup staging area...\n" >> $LOG
    cp -vp /usr/sbin/hwscand $BACKUP_DIR/hwscand.orig >> $LOG 2>&1
fi


#
# Generate a list of *most* (not *all*) of the files that have changed since the
# code was installed on the hard disk (as indicated by the marker file).
#
# Set the file to output this list of files to. This avoids the problem of overflowing
# the 'tar' input buffer if too many files are present.
#
# Make sure to catch the sybolic link'd files too and also set up the filter
# to catch ".*" files as well
#
# Currently, there are still issues with saving directories only.  Problem is
# if we identify a directory to backup, the 'tar' command seems to decend into
# that directory and save all files contained in that directory whether or not
# they meet the date filtering criteria. See the comments in the 'restore' script
# for further details regarding users' home directories.
#
# Some files still get archived that shouldn't (some PID files, for example),
# but the system seems tolerant of the recovery of these files.
#
echo -e "list of files to archive now follows...\n" >> $LOG

FILELIST=/tmp/backup.list
exclude_list=`cat /opt/hsc/data/exclude_for_backup.list`
if [ "$osname" != "AIX" ]; then
    fill=" ! -path "
else
    fill=" ! -name "
fi

# for all "normal" files...
cmd1="find /"
end1=" ! -type b ! -type c ! -type p ! -type s -newer $MARKER -print > \$FILELIST"
for name in $exclude_list
do
    cmd1=$cmd1$fill$name
done
cmd1=$cmd1$end1
echo -e "command to eval is: $cmd1 \n" >> $LOG
eval $cmd1

# for all "hidden" files...
#cmd2="find / -name '.*' -xtype f -o -xtype d"
#end2=" ! -type b ! -type c ! -type p ! -type s -newer $MARKER -print >> \$FILELIST"
#for name in $exclude_list
#do
#    cmd2=$cmd2$fill$name
#done
#cmd2=$cmd2$end2
#eval $cmd2
#`find / -name '*' -xtype f ! -path '/var/lock/subsys/*' ! -path '/opt/hsc/com/ibm/hsc/websm/launch/hscmgt/rpminst.dat' ! -path '/extra-swap' ! -path '/var/hsc/log/backuphdr.log' ! -path '/tmp/archive.log' ! -path '/tmp/backup.list' ! -path '/proc/*' ! -path '/dump/*' ! -path '/info/*' ! -path '/updates/*' ! -path '/var/ct/*' ! -path '/extra/updates/*' ! -type b ! -type c ! -type p ! -type s -newer $MARKER -print > $FILELIST`
#`find / -name '.*' -xtype f ! -path '/.journal' ! -path '/var/lock/subsys/*' ! -path '/proc/*' ! -path '/info/*' ! -path '/updates/*' ! -path 'var/ct/*' ! -path '/extra/updates/*' ! -type b ! -type c ! -type p ! -type s -newer $MARKER -print >> $FILELIST`

#
# New for Squadrons (multi-CD installations). Archive the hscbuild.dat file as well
#
echo $MARKER >> $FILELIST

#                      
# Now we need to query all the existing RPM packages on the system in case PTF
# updates added any new RPMs that contain files older than the marker file
#
rpm -qa > /tmp/rpm.list

#
# InfoCenter RPMs should never get backed up - they can/should be re-installed
#
grep -vi 'InfoCenter' /tmp/rpm.list > /tmp/rpm.list.sans.InfoCenter
mv /tmp/rpm.list.sans.InfoCenter /tmp/rpm.list
chmod 777 /tmp/rpm.list

#
# If there is a latest RPM installation date file, use this for RPM comparisons,
# (see modHscBuildDat script). Else, use the file comparison marker file.
#
if [ -f $MARKER2 ]; then
   RPMINSTDATE=$MARKER2
   echo "using latest dated RPM installation package file for RPM date comparisons." >> $LOG
else
   RPMINSTDATE=$MARKER
   echo "using system installation date file for RPM date comparisons." >> $LOG
fi

for i in `cat /tmp/rpm.list`
do
   x=`rpm -qi $i | grep "Install date:" | awk '{print $4" "$5" "$6" "$7" "$8" "$9}'`
   
   # touch temp working file for comparison against marker file using
   # datestamp of installed RPM package
   if [ "$osname" != "AIX" ]; then
      touch /tmp/rpminst.dat --date="$x"
   else
      touch_aix $i /tmp/rpminst.dat
   fi
   chmod 777 /tmp/rpminst.dat

   if [ /tmp/rpminst.dat -nt $RPMINSTDATE ]; then
      # we're newer, so list every file in the package and *selectively* add to save list
      echo "RPM package, $i, installation date is newer than recovery marker file." >> $LOG

      #
      # Send output to a working file first. Then, ensure we're only processing *files*
      # (i.e. not direcories!) next.  Finally, only add the file if it does not already
      # reside in the master list.
      #
      rpm -ql $i > /tmp/rpm.package
      chmod 777 /tmp/rpm.package
      
      for j in `cat /tmp/rpm.package`
      do
         if [ -f $j ]; then
            # only process files, not directory entries
            grep -qx $j $FILELIST
            
            if [ $? -ne 0 ]; then
               # we did not find this file, add to master list
               echo $j >> $FILELIST
            fi
         fi
      done
   fi

   # stay clean...
   rm -f /tmp/rpminst.dat
done

# bit-o-cleanup
rm -f /tmp/rpm.package
rm -f /tmp/rpm.list

echo "RPM file list generation pre-processing complete" >> $LOG


#
# New feature - 06/09/03.  Incorporate any save upgrade data files
# that may have datestamp prior to the hscbuild.dat ($MARKER) file
#        
# Concatenate the save upgrade file list to the end of the
# dynamically generated backup list.  This save upgrade file
# list gets generated each time after a restore of upgrade
# data is done, hence it'll also be backup'd up too.
#
if [ -f /opt/hsc/data/backupUpgradeList ]; then
   # ensure no file repeats here
   for i in `cat /opt/hsc/data/backupUpgradeList`
   do
      if [ -f $i ]; then
         # only process files, not directory entries
         grep -q $i $FILELIST
            
         if [ $? -ne 0 ]; then
            # we did not find this file, add to master list
            echo $i >> $FILELIST
         fi
      fi
   done
fi


#
# Another new feature - look for the existance of a "special file" containg
# a list of files (currently to be generated by the efix install script)
# and add all these files to the master backup list of files to archive.
#
# We do this in case a package/file has been updated from one release/version
# to another, but the file(s) are still older than the hscbuild.dat file
# AND they are not installed via an RPM install (which the RPM "Install date:"
# would have caught and triggered these files to be backed up). 10/01/03 - SLF
#
if [ -f /opt/hsc/data/extbackupfile.list ]; then
   # ensure no file repeats here
   for i in `cat /opt/hsc/data/extbackupfile.list`
   do
      if [ -f $i ]; then
         # only process files, not directory entries
         grep -q $i $FILELIST

         if [ $? -ne 0 ]; then
            # we did not find this file, add to master list
            echo $i >> $FILELIST
         fi
      else
        if [ -L $i ]; then
         # only process files, not directory entries
           grep -q $i $FILELIST
            
           if [ $? -ne 0 ]; then
            # we did not find this file, add to master list
             echo $i >> $FILELIST
           fi
        fi
      fi
   done
fi

 
#
# Use new RMC backup procedure which generates a unique directory containing
# all their data
#
if [ -f $CTBACKUP ]; then
    # run the RMC backup script
    echo "=========> begin ctbackup processing <=========" >> $LOG
    $CTBACKUP >> $LOG 2>&1

    ctbackupRC=$?
    if [ $ctbackupRC -ne 0 ]; then
        echo "'ctbackup' execution failure, rc=$ctbackupRC. HMC backup task terminating." >> $LOG
        exit_cleanup 40
    else
        echo "'ctbackup' execution success, continuing..." >> $LOG

        # now process the data that the 'ctbackup' program created
        if [ -d /var/ct.backup ]; then
            if [ "$osname" != "AIX" ]; then
                `find /var/ct.backup -name '*' -xtype f ! -type b ! -type c ! -type p ! -type s -print >> $FILELIST`
            else
                `find /var/ct.backup -name '*' \( -type f -o -type l \) ! -type b ! -type c ! -type p ! -type s -print >> $FILELIST`
            fi
        fi
    fi

    echo "=========> end ctbackup processing <=========" >> $LOG
fi

 
#
# Hack for defect 547464.  Somehow the HMC is ending up with broken symlink'd files
# that end with a "*" character. Un-taring such files causes problems.  Exclude
# files in "/usr/lib/*.so*"
#
grep -vi "/usr/lib/.*\.so\*$" $FILELIST > $FILELIST.sans.splat
mv $FILELIST.sans.splat $FILELIST

#
# Defect 601731 (continuation of 589978) - permanently exclude the files '/opt/hsc/bin/restore' and
# '/etc/init.d/hmcRestore' from the list of files to save. The reason the exclusion of these files
# from the 'find' command does not work is that they are part of the IBMhsc.coreserver RPM file.
#
grep -vw "/opt/hsc/bin/restore" $FILELIST > $FILELIST.sans.restore
mv $FILELIST.sans.restore $FILELIST
grep -vw "/etc/rc.d/hmcRestore" $FILELIST > $FILELIST.sans.hmcRestore
mv $FILELIST.sans.hmcRestore $FILELIST
echo "HMC restore files now excluded from backup file list..." >> $LOG

#
# Additional special processing for file per defect 624653. 'hwscand' apparently
# executing prior to boot.local - account for this. See related defect 589978.
#
grep -vw "/usr/sbin/hwscand" $FILELIST > $FILELIST.sans.hwscand
mv $FILELIST.sans.hwscand $FILELIST
echo "original hwscan daemon excluded from backup file list..." >> $LOG

#
# Defect 601396 - always exclude MM specific directories under /extra
#
if [ -f /opt/hsc/data/hmcType.properties ]; then
    x=`cat /opt/hsc/data/hmcType.properties`
    if [ $x = 'HMCTYPE=essHMC' ]; then
        grep -vw "/extra/ctsupt" $FILELIST | grep -vw "/extra/hmceed" | grep -vw "/extra/pepkg" | grep -vw "/extra/var" | grep -vw "/extra/data/dumps" > $FILELIST.sans.extra
        mv $FILELIST.sans.extra $FILELIST
    fi
fi

#
# Feature 587785 to ensure archive file created here will only be restored on same system/driver
# as was originally installed on. Add new eClipz indicator files and be sure to coordinate
# these with the restore script. Always add these files despite them probably never being flagged
# as newer than marker file
#
if [ -f /etc/HmcBase ]; then
    # HMC initial install version
    grep -q "/etc/HmcBase" $FILELIST
    if [ $? -ne 0 ]; then
        # add to list only once!
        echo "/etc/HmcBase" >> $FILELIST
    fi
fi
if [ -f /opt/hsc/data/hmcmodel.dat ]; then
    # HMC machine type/model
    grep -q "/opt/hsc/data/hmcmodel.dat" $FILELIST
    if [ $? -ne 0 ]; then
        # add to list only once!
        echo "/opt/hsc/data/hmcmodel.dat" >> $FILELIST
    fi
fi

#
# Defect 630413: apache-tomcat files are not installed on the HMC as part of an
# RPM package. Ensure they always get backed up since their file dates will always
# be prior to the hscbuild.dat marker file (for eClipz GA2). This is a problem if
# starting with eCLipz GA1, then efix'ing to GA2. The apache-tomcat files are *not*
# part of the GA1 base, but are required for GA2, and since we re-install from GA1
# recovery media in this case, we'll be missing all those /opt/apache-tomcat-<ver>/*
# files. (As of GA2, there's currently only approx 50 of these files, so no big deal
# to redundantly archive them if originally *starting* with GA2 install media)
#
if [ -d /opt/apache-tomcat*/ ]; then
    il=`find /opt/apache-tomcat*/ -type f -print`
    for i in $il
    do
        echo "$i" >> $FILELIST
    done
    il=`find /opt/apache-tomcat*/ -type l -print`
    for i in $il
    do
        echo "$i" >> $FILELIST
    done

    echo "-- special processing for /apache-tomcat completed..." >> $LOG
fi


# Form the name of the archive file by concatenating the directory and filename.
# All backups will go to the /dump partition first
archive="/dump/$ARCHIVE"

#
# Allow kernel update to be signal/restored correctly on re-install
# If there is a bzImage-xxx being backed up, then create a file
# /boot/new_hmc_kernel containing the bzImage-xxxx being backed up
# and save it , removed afterward
#
#
grep -q "/boot/bzImage-" $FILELIST
if [ $? -eq 0 ]; then
   kname=`grep "/boot/bzImage-" $FILELIST 2>/dev/null`
   if [ "$kname" != "" ]; then
     x=`basename $kname`
     echo $x > /boot/new_hmc_kernel
     echo "/boot/new_hmc_kernel" >> $FILELIST 
   fi
fi

touch /opt/hsc/data/.postRestore
echo /opt/hsc/data/.postRestore >> $FILELIST
echo "-- postRestore boot.local flag set..." >> $LOG

#
# Begin the archive process.
# ToDo: Need to check for diskspace problems or other errors before/after tar cmd runs
# Now that we are also saving *directories* that meet the timstamp criteria, ensure
# the --no-recursion flag is set
# 
# NOTE: backup progress monitoring thread triggers off exact text in below 'echo' cmd
#
echo "Creating new archive..." >> $LOG
tar --create --gzip --verbose --absolute-names --file=$archive --no-recursion --files-from=$FILELIST >> $LOG 2>&1
TAR_RC=$?

# useful output for later log file anlysis. NOTE: backup progress monitoring thread triggers off
# exact text in below 'echo' cmd
echo "-- staged backup content completed at `date`." >> $LOG

# useful debug info...
numfiles=`wc $FILELIST | awk '{print $1}'`
archivesize=`ls -l $archive | awk '{print $5}'`
echo "==> numbers of files to archive is: $numfiles, archive filesize is: $archivesize." >>$LOG

# Although useful for debug purposes, cleanup the list of files to archive
rm -f $FILELIST
rm -f /boot/new_hmc_kernel

# check for 'tar' errors.  A '2' appear to be returned if we attempt to 'tar' a
# "corrupt" file, example: broken symbolic link or a file that is locked possibly.
if [ $TAR_RC -ne 0 ]; then
    echo "tar command failure. Return code is $TAR_RC, continuing..." >> $LOG
    if [ $TAR_RC -ne 2 ]; then
        echo "unexpected tar error, preparing to exit..." >> $LOG
        rm -f $archive
        exit_cleanup 6
    else
        echo "tar encountered in-use, locked, or invalid file, continuing..." >> $LOG
    fi
fi


#
# Now move this backup file to it proper location
#
if [ $BACKUP_TYPE -eq 0 ]; then

    # output to DVD
    copyBackupArchiveToDVD $DUMP_DIR $ARCHIVE $DVD_MOUNTPOINT
    copyRC=$?
    if [ $copyRC -ne 0 ]; then
        exit_cleanup $copyRC
    fi

elif [ $BACKUP_TYPE -eq 1 ]; then

    # to remote (NFS/Samba) mount. Grab remaining program args from input
    SERVER=$3
    RESOURCE=$4
    FSTYPE=$5
    OPTIONS=$6
    copyBackupArchiveToMount $DUMP_DIR $ARCHIVE $SERVER $RESOURCE "$FSTYPE" "$OPTIONS" $DIRECTORY
    copyRC=$?

    # whether the backup worked or not, we should kill the portmap service if
    # we started it.
    echo "attempt to stop the portmap service..." >> $LOG
    if test -n "$PID" ; then
        echo "portmap was running prior to script execution - not terminating the service." >> $LOG
    else
        echo "now terminating the portmap service..." >> $LOG
        kill -9 $NEW_PID
    fi

    if [ $copyRC -ne 0 ]; then
        exit_cleanup $copyRC
    fi

elif [ $BACKUP_TYPE -eq 2 ]; then

    # to ftp server. Grab remaining program args from input
    SERVER=$3
    USERID=$4
    PASSWORD=$5
    ftpBackupArchiveToServer $DUMP_DIR $ARCHIVE $SERVER $USERID $PASSWORD $DIRECTORY $TEST_ACCESS_FILE
    ftpRC=$?
    if [ $ftpRC -ne 0 ]; then
        exit_cleanup $ftpRC
    fi

fi


#
# That's all folks!
#
exit_cleanup 0
