#! /bin/sh
#
# ident data/SCCS/s.install_cluster_zone 1.2 09/19/05:18:11:57 SMI
#
# Script to install a patch cluster supplement for Solaris 10 or later
#
########################################################################

set -e

#
# Force the path to first look in certain directories
#
PATH=/sbin:/usr/sbin:/bin:$PATH
export PATH


#
# Supplement tag information
# (Tag needs to be convertible to a valid filename too...)
SUPPLEMENT_NAME="Solaris 10 Recommended Patch Cluster"

VALID_OS="5.10"
PATCH_ORDER="patch_order"
OS_REL=`uname -r`

# Broadcast what we are doing
#
echo
echo "Patch cluster install script for ${SUPPLEMENT_NAME}"
echo

logname=`echo ${SUPPLEMENT_NAME} | sed 's/ /_/g'`_log
LOGFILE=/var/sadm/install_data/${logname}

#
# Command line and environment option processing
#
# (Default is *not* to save base objects)
#
Usage()
{
	echo "usage: `basename $0` [-q] [-t] [-nosave] [target] [patchdir]"
	echo " [-q]       - quiet option, suppresses interactive warning"
	echo " [-t]       - Maintains the patchadd return codes from the"
        echo "              Solaris release  prior to Solaris 10"
	echo " [-nosave]  - do not save original objects"
        echo " [target]   - destination system to apply or query patches, can be one of:" 
        echo "              [-R client_root_path]  - apply/query patch on bootable client root"
	echo " [patchdir] - optional pathname to directory of patches"

}


#
# Validate the system and zones to ensure processing should continue
#
validate_system()
{

        touch $LOGFILE || {
                echo "ERROR:  $LOGFILE not writeable.\n"
                return 1
        }

        if [ "$OS_REL" != "$VALID_OS" ]; then
                echo "ERROR:  OS is not valid for this cluster.  Exiting."
                return 1
        fi

        ZONENAME="/sbin/zonename"
        if [ -x $ZONENAME ]; then
                if [ `$ZONENAME` != "global" ]; then
                        echo "ERROR:  install_cluster can only be applied to global zone.  Exiting."
                        return 1
                fi
        else
                echo "ERROR:  $ZONENAME cannot be found."
                echo "        install_cluster for $SUPPLEMENT_NAME not applied.  Exiting."
                return 1
        fi

}


cleanup()
{
        #
        # A little cleanup.
        #
        if [ "$finished" = "NO" ]; then
                failed_list="${failed_list} ${patch}"
        fi

        #
        # List the patches that were successfully installed (if any)
        #
        if [ " ${success_list}" != " " ]
        then
                echo
                echo "The following patches were able to be installed:"
		echo ${success_list} | /usr/bin/tr ' ' '\012' | sed 's/^/        /g'
        fi

        #
        # List the patches that failed installation (if any)
        #
        if [ " ${failed_list}" != " " ]
        then
                echo
                echo "ERROR:  The following patches were not able to be installed:"
		echo ${failed_list} | /usr/bin/tr ' ' '\012' | sed 's/^/        /g'
        fi

        echo
        echo "For more installation messages refer to the installation logfile:"
        echo "  ${LOGFILE}"
        echo
        echo "Use '/usr/bin/showrev -p' to verify installed patch-ids."
        echo "Refer to individual patch README files for more patch detail."
        echo "Rebooting the system is usually necessary after installation."
}

 
uid=`id | sed 's/uid=\([0-9]*\)(.*/\1/'`
if [ "$uid" != "0" ] ; then
	echo "You must be root to execute this script."
	exit 1
fi

finished="NO"
saveold=''
useOldOSErr=''
quiet="NO"
target=""
while [ "$1" != "" ];
do
	case $1 in
	-nosave)	saveold='-d';;
	--nosave)	saveold='-d';;
	-n)	        saveold='-d';;
	-q)		quiet='YES';;
	-t)		useOldOSErr='-t';;
	-R)		shift
                        if [ $# -gt 0 ] && [ ! -d $1 ]; then
                            echo "$1 client root path not found?"
                            exit 1
                        else
                            target="-R $1" 
                        fi;;
	-*)		Usage; exit 2;;
	*)
		if [ "$finished" = "YES" ]; then
			Usage; exit 2
		fi
		#
		# Where do we find the list of patches to install
		# (we need an absolute pathname...)
		#
		# This is done to maintain the cwd to PATCHDIR to
		# suppress auto unmounts...
		if [ ! -d $1 ]; then
                  echo "$1 optional patch directory not found?"
                  exit 1
                else
		  cd $1
		  finished="YES"
                fi
		;;
	esac
	shift
done
PATCHDIR=`pwd`

if [ "$quiet" != "YES" ]; then
	cat << EOF

*WARNING* SYSTEMS WITH LIMITED DISK SPACE SHOULD *NOT* INSTALL PATCHES:
With or without using the save option, the patch installation process
will still require some amount of disk space for installation and
administrative tasks in the /, /usr, /var, or /opt partitions where
patches are typically installed.  The exact amount of space will
depend on the machine's architecture, software packages already 
installed, and the difference in the patched objects size.  To be
safe, it is not recommended that a patch cluster be installed on a
system with less than 4 MBytes of available space in each of these
partitions.  Running out of disk space during installation may result
in only partially loaded patches.  Check and be sure adequate disk space
is available before continuing.

EOF
	while .
	do
	  echo "Are you ready to continue with install? [y/n]: \c"
	  read reply
	  case $reply
	  in
	    y)	break;;
	    n)	exit;;
	    *)	echo invalid response, enter only 'y' for yes or 'n' for no;;	
	  esac
	done
fi

#
# The patch reference directory must exist
#
if [ ! -d /var/sadm/patch ]; then
        mkdir /var/sadm/patch
        chown bin /var/sadm/patch
        chgrp bin /var/sadm/patch
        chmod 555 /var/sadm/patch
fi

#
# If using save feature:
# Approximate and set cluster save size value.  The maximum save space
# needed should be about no more than half of the actual patch cluster size
# since the patch installation procedure will use compression to save files, and
# patches with multiple architecture packages will only have appropriate
# packages installed on the system.
#
if [ "${saveold}" != -d ]; then
	echo "Determining if sufficient save space exists..."
	BASESIZE=`du -sk $PATCHDIR | cut -f1`
	SUPPLEMENT_SIZE=`expr $BASESIZE / 2`
	bytes_avail=`df -b /var/sadm/patch | tail -1`
	bytes_avail=`echo $bytes_avail | sed 's/.*\ //'`
	if [ ${SUPPLEMENT_SIZE} -gt ${bytes_avail} ]; then
		echo "Insufficient space in /var/sadm/patch to save old files."
		echo "Space required in kilobytes:  ${SUPPLEMENT_SIZE}"
		echo "Space available in kilobytes:  ${bytes_avail}"
		exit 1
	else
		echo "Sufficient save space exists, continuing..."
	fi
else
	echo "The nosave option was used.  Objects will not be saved."
fi


#
# First validate system.  
#
validate_system || exit 1

#
# Install all the patches in patch_order file in PATCHDIR
#
echo "Installing patches located in $PATCH_ORDER file in ${PATCHDIR}"
echo "" >> ${LOGFILE}
echo "" >> ${LOGFILE}
echo "*** Install ${SUPPLEMENT_NAME} begins `date` ***" >> ${LOGFILE}
echo "*** PATCHDIR = ${PATCHDIR} ***" >> ${LOGFILE}
echo "" >> ${LOGFILE}

set +e

finished="YES"
success_list=""
failed_list=
result=0
trap 'echo; echo Interrupted ... Please wait; cleanup; exit 1' 1 2 3 15

# Check for existence of patch_order file
if [ -f $PATCH_ORDER ]; then
    echo "Using $PATCHDIR/$PATCH_ORDER file for patch installation sequence"

    for patch in `cat $PATCH_ORDER` ; do
        if [ -d $patch ]; then
            echo "Installing ${patch}..." | tee -a ${LOGFILE}
            finished="NO"
            ( /usr/sbin/patchadd ${saveold} ${useOldOSErr} \
             ${target} ${patch} ) >> ${LOGFILE} 2>&1
            result=$?
            if [ ${result} -ne 0 ]; then
                echo "  Installation of ${patch} failed. Return code ${result}."
                failed_list="${failed_list} ${patch}"
            else
                echo "  Installation of ${patch} succeeded.  Return code ${result}."
                success_list="${success_list} ${patch}"
            fi
            finished="YES"
        fi
    done
else
    echo ""
    echo "ERROR:  $PATCH_ORDER file does not exist.  Unable to install cluster."
fi

cleanup

if [ " ${failed_list}" = " " ]; then
        exit 0
else
        exit 1
fi
