#!/bin/ksh -pu
#
# ident "@(#)utpreserve.ksh	1.23 04/09/30 SMI"
#
# Copyright 2001,2004 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# utpreserve
#
# master task to preserve the Sunray data during upgrades etc
# 
#

trap "CleanupAndExit 1" HUP INT QUIT TERM

#
# Usage()
#
# Description:
#    Shows usage string
#
# Parameters:
#    (none)

Usage() {
  print -u2 "Usage: $G_PROGRAM_ID $PROGRAM_OPTS"
  print -u2 ""
  print -u2 " -d data_dir  : specify a directory to store the data in"
           
  CleanupAndExit 1
}

#
# CleanupAndExit()
#
# Description:
#    clean up procedure before exiting. Send Exit event in case of normal
#    termination (error code 0). Abort event otherwise (failure or 
#    interruption)
#
#
# Parameters:
#    $1 : exit code

CleanupAndExit() {
  trap "" HUP INT QUIT TERM
 
  #
  # remove all temporary files created
  #
  rm -rf ${G_TMP_DIR} > /dev/null 2>&1

  rm -rf "${PRESERVE_DIR}/preserve" > /dev/null 2>&1

  #
  # send termination event (Exit or Abort) to all modules to do their cleanup 
  # procedure
  #
  if [[ "$1" = "0" ]]; then
     SendEventToModule Exit
  else
     SendEventToModule Abort
  fi

  #
  # This function (CleanupAndExit) can be called from StartPreserve (a function
  # which is in pipe with tee). The exit code cannot be seen by the main script
  # (utpreserve) as the last task of the "pipeline" is tee. So, a temporary
  # file is created to communicate the error code to the main script 
  # (utpreserve). Of course, this file is created if needed (just check if tee 
  # is running...)

  if ps -f | grep tee | grep ${G_PID} > /dev/null 2>&1 ; then
     echo $1 > $ERROR_FILE
  fi

  exit $1
}

#
# PrintFinalMessage()
#
# Description:
#    Just to print a message at the end of installation/uninstallation
#
# Parameters:
#    (none)

PrintFinalMessage() {

      fmt <<-!

	********************************************************************
	
	Preservation of $G_UT_PROD_NAME data has completed.  Please check
	the log file, $G_LOGFILE, for errors.

	Please use NFS, FTP, or other media/means to move:

	${NEWPRESERVEDIR}/${PRESERVE_FILENAME}.tar.gz

	to a safe location on another server before performing any OS install.

	*********************************************************************

	!

}


#
# CreateTarball()
#
# Description:
#    Tar up and compress all the preserved data
#
# Parameters:
#    (none)

CreateTarball() {
  typeset curdir=${PWD}

  if [[ ! -d ${PRESERVE_DIR} || ! -d ${PRESERVE_DIR}/preserve ]]; then
     echo "No data has been preserved"
     return 1
  fi

  cd $PRESERVE_DIR
  echo "Creating tarball of preserved files\n"
  pax -w -f "${PRESERVE_FILENAME}.tar" ./preserve > /dev/null 2>&1
  exit_no=$?
  if [[ $exit_no != "0" ]]; then

    cd $curdir
    return $exit_no

  fi

  echo "Compressing tarball of preserved files\n"
  gzip "${PRESERVE_FILENAME}.tar" > /dev/null 2>&1
  exit_no=$?
  if [[ $exit_no != "0" ]]; then

    cd $curdir
    return $exit_no

  fi

  cd $curdir
  return 0
}

#
# CheckDirectories()
#
# Description:
#    Check existence of install directories (support_lib, modules)
#
# Parameters:
#    (none)
#
# Globals used:
#    G_MEDIA_DIR

CheckDirectories() {

   # Check existence of support_lib dir. if it doesn't, libraries cannot be
   # sourced
   if [[ ! -d $G_MEDIA_DIR/support_lib ]]; then
      echo "$0: Error, cannot find support_lib directory"
      exit 1
   fi

   # Check existence of modules dir. if it doesn't, modules cannot be 
   # called.
   if [[ ! -d $G_MEDIA_DIR/iu_modules ]]; then
      echo "$0: Error, cannot find modules directory"
      exit 1
   fi

   return 0
}

#
# StartPreserve()
#
# Description:
#    To kick off the data preservation procedure
#
# Parameters:
#    (none)

StartPreserve() {

   #
   # Initialize all modules
   #
   SendEventToModule Init

   PrintPostInitMessage

   echo "\nWARNING: all daemons/services will be stopped now"

   if ! YesOrNo "\n\nContinue?" "Y"; then
      CleanupAndExit 1
   fi

   #
   # Start the preservation process
   #
   SendEventToModule Preserve 

   if CreateTarball ; then
     PrintFinalMessage
   else
     Fatal "Unable to preserve data. Error while creating archive file"
   fi
   CleanupAndExit 0
}

#
# checkEmpty()
#
# Description:
#    Checks to see if the directory specified is emtpy.  If not, prompt
#    the user for cleanup and remove the directory.
#
# Parameters:
#    $1 directory name

checkEmpty() {
     # check if directory is empty
     typeset -r DIR=$1
     typeset -r LS_OUTPUT=`ls -1F $DIR`
     if [[ -z "$LS_OUTPUT" ]]; then
	# empty directory, remove it
     	rm -rf ${DIR}
     else
	# non-empty directory, promtp user
	print "\nFiles found under ${DIR}:"
	ls -1F $DIR
	print ""
	if YesOrNo "Do you want to remove these files/directories" "N"
	then
	    rm -rf $DIR
	else
	    fmt <<-!

		Please cleanup the directory ${DIR} before
		rerunning $G_PROGRAM_ID.

		!
	    return 1
	fi
     fi
     return 0
}


#
# main 
#

#
# global variables definition
#

# get the full pathname of the command
typeset command=$(whence $0)

export G_OS="$(uname -s)"
export G_OS_REL="$(uname -r)"

# location of the support_lib and modules directories
export G_MEDIA_DIR=${command%/*}/../lib

# location of the bundles (SWS,SDS,LDAP,...)
export G_PRODUCT_DIR=${command%/*}/..

# Perform sanity checks on directories
CheckDirectories

#
# include libraries and definitions
#

. ${G_MEDIA_DIR}/support_lib/gl_defs
. ${G_MEDIA_DIR}/support_lib/iu_lib
. ${G_MEDIA_DIR}/support_lib/master_lib

#
# local variables definition
#

PATH="/bin:/usr/sbin:/usr/bin"

export G_MODE="preserve"
typeset -r OPTSTR=":d:"
typeset -r PROGRAM_OPTS="[-d data_dir ]"

# ERROR_FILE must be under G_TMP, not G_TMP_DIR.  The directory G_TMP_DIR
# contains the temporary working files and is deleted while the ERROR_FILE
# is still in use.
typeset -r ERROR_FILE="${G_TMP}/.${G_PROGRAM_ID}.${G_PID}.errcode"

PRESERVE_DIR=${G_UPGRADE_DIR}
NEWPRESERVEDIR=${G_UPGRADE_DIR}
typeset -r PRESERVE_VERSION=`${G_MEDIA_DIR}/utprodinfo -p SUNWutr PRODVERS 2>&- | cut -d_ -f1`
typeset -r PRESERVE_FILENAME="preserve_${PRESERVE_VERSION}"
#
# main starts here
#

#
# parse the command line
#
while getopts $OPTSTR OPT; do
  case "$OPT" in
    d) NEWPRESERVEDIR="$OPTARG";;
   \?) Usage;;
  esac
done
shift $(($OPTIND - 1))

if (( $# != 0 )); then
  Usage
fi

#
# sanity checks
#
if [[ ${G_OS} = "Linux" ]] && ! ${G_MEDIA_DIR}/utprodinfo -p pax  >/dev/null 2>&1; then
    print "Error: Please install the pax rpm before running utpreserve"
    exit 1
fi


CheckUidIsZero

print "# Script: ${G_PROGRAM_ID}\tVersion: \n" > $G_LOGFILE

# clean up residuals from previous utpreserve run
  if [[ -L $PRESERVE_DIR ]]; then
     rm -f $PRESERVE_DIR
  elif [[ -d $PRESERVE_DIR ]]; then
     # check if directory is empty
     if ! checkEmpty $PRESERVE_DIR; then
	exit 1
     fi
  elif [[ -a $PRESERVE_DIR ]]; then
     # it's not a directory
     Fatal "$PRESERVE_DIR is not a directory or link."
  fi

# if new temp directory specified, then create a soft link to it in G_TMP_DIR

  if [[ ${NEWPRESERVEDIR} != ${PRESERVE_DIR} ]]; then
     if [[ -a ${NEWPRESERVEDIR} ]]; then
	# new preserved dir exists
        if [[ ! -d ${NEWPRESERVEDIR} ]]; then
	   Fatal "${NEWPRESERVEDIR} is not a valid directory"
	else
	   if ! checkEmpty ${NEWPRESERVEDIR}; then
	      exit 1
	   fi
	   mkdir -p ${NEWPRESERVEDIR}
	fi
     else
	print "\nDirectory ${NEWPRESERVEDIR} does not exist."
	if YesOrNo "Should I create it" "Y"
	then
	    if ! mkdir -p ${NEWPRESERVEDIR}; then
		Fatal "Failed to create directory ${NEWPRESERVEDIR}."
	    fi
	else
	    fmt <<-!

		Please create the directory ${NEWPRESERVEDIR} before
		rerunning $G_PROGRAM_ID.

		!
	    exit 1
	fi

     fi
 
# if a relative pathname is specified, make it absolute (needed for the
# soft link)
     if $( echo "${NEWPRESERVEDIR}" | egrep -s "^[^/]" ); then
        NEWPRESERVEDIR=${PWD}/${NEWPRESERVEDIR}
     fi

     ln -fs ${NEWPRESERVEDIR} ${PRESERVE_DIR}
     if [[ $? != 0 ]]; then
  	Fatal "cannot create link to ${NEWPRESERVEDIR}"
     fi
  fi
  if [[ ! -a $PRESERVE_DIR ]] && [[ ! -L $PRESERVE_DIR ]]; then
     mkdir -p $PRESERVE_DIR
  fi

StartPreserve 2>&1 | tee -a $G_LOGFILE

#
# As StartPreserve is in pipe with tee, we never get the exit code of it
# (we get the one from tee instead, which is always 0). The cleanup procedure,
# then, create a temporary file (ERROR_FILE) which contains the error code
# of StartPreserve. 

if [[ -f $ERROR_FILE ]]; then
   errcode=`cat $ERROR_FILE`
   rm -f $ERROR_FILE
   exit $errcode
fi

exit 0

#
# END
#
