#!/bin/ksh

PATH="/usr/bin:/usr/sbin:${PATH}"; export PATH
PKGCOND=/usr/bin/pkgcond
SataKU=118855-14

function last_patch {

	## returns the number of patches installed at or above this rev.

	root_dir=${ROOTDIR:-/}

	## parse id and rev
	pid=`echo $1 | cut -d\- -f1`
	prev=`echo $1 | cut -d\- -f2`
	patch_cnt=0

	## get all installed refernces to the installed patch base id	
	installed_patches=`patchadd -p -R $root_dir | sed -n -e 's/Req.*//' -e 's/[a-zA-Z]*://g' -e 's/,//g' -e "/$pid/p"`
	
	for x in $installed_patches ; do
		base=`echo $x  | cut -d\- -f1`
		rev=`echo $x | cut -d\- -f2`
		if [ $pid -eq $base ] && [ $rev -ge $prev ] ; then 
			## count all installed patches includeing this patch
			patch_cnt=$(($patch_cnt + 1))
		fi
	done
	
	return $patch_cnt
}

function PatchInstalled {

	patchadd -p -R $ROOTDIR | sed 's/Obs.*//' | grep $1 2>&1 > /dev/null

}

function MdFixDevids {

	MD_CONF=$ROOTDIR/kernel/drv/md.conf

	#
	# Modify the md.conf file to have SVM resynch the devids of
	# volume members
	#
	if [ -f $MD_CONF ] && \
		! /bin/grep 'md_devid_destroy[ 	]*=[ 	]*1[ 	]*;' $MD_CONF \
		    > /dev/null 2>&1; then

		#
		# The string "# Begin MDD database info (do not edit)" will be
		# present in md.conf VERBATIM if there are SVM volumes present.
		# the string will always be the same, since it's put there by
		# code, not by humans.
		#
		/bin/sed -e \
		    '/# Begin MDD database info (do not edit)/ a\
md_devid_destroy=1;' $MD_CONF > /tmp/md.conf.$$
		/bin/mv /tmp/md.conf.$$ $MD_CONF
		/bin/chmod 644 $MD_CONF
		/bin/chown root:sys $MD_CONF
	fi
}

function SataSupport {

	#
	# 
	#
	PATCHID=$PatchNum
	PATCHEXEC=$1
	PATCHROOT=$1
	
	ZPOOL_CACHE=$ROOTDIR/etc/zfs/zpool.cache
	FBTEMPLATE=$PATCHROOT/fbtmplmeth.ksh
	FBSVCMETH=patch-${PATCHID}-fb
	ROOT_FBSVCMETH=$ROOTDIR/lib/svc/method/$FBSVCMETH
	FBSVCTMPL=$PATCHROOT/fbtmplsvc.xml
	# The service name (from the <service> tag in fbtmplsvc.xml):
	FBSVCNAME=system/patch-${PATCHID}-fb
	FBSVCINSTANCE=${FBSVCNAME}:default
	
	function patchfunc {
		/bin/echo 'export SYSV3=	# for echo -n'
		/bin/echo '/bin/echo "Patch '$PATCHID' requires some additional operations:" > /dev/console'
		/bin/echo '/bin/echo "Please wait while ZFS pools are reimported:" > /dev/console'
		while read nextline; do
			VOLNAME=`/bin/echo $nextline | /bin/awk '{print $NF}'`
			/bin/echo '/bin/echo -n "Reimporting ZFS pool: '$VOLNAME'..." > /dev/console'
			/bin/echo 'if ! /sbin/'${nextline}' > /dev/null 2>&1; then'
			/bin/echo '    /bin/echo "failed." > /dev/console'
			/bin/echo "    /bin/echo '******* WARNING *******'"
			/bin/echo "    /bin/echo \"zpool import of pool \\\`"$VOLNAME"' failed.\""
			/bin/echo "    /bin/echo '******* WARNING *******'"
			/bin/echo "else"
			/bin/echo '/bin/echo "done." > /dev/console'
			/bin/echo "fi"
		done
		/bin/echo 'unset SYSV3'
	}
	
	#
	# No ZFS pools?  No need for the smf service.
	#
	if [ ! -f $ZPOOL_CACHE ]; then
    		exit 0;
	fi
	
	#
	# Look for required files;  if any are missing, bail out with an error.
	#
	if [ ! -x $PATCHEXEC/zfs_cache ]; then
    		echo Missing zfs_cache command.
    		exit 1;
	fi
	if [ ! -f $FBTEMPLATE ]; then
    		echo Missing reboot service method template
    		exit 1;
	fi
	if [ ! -f $FBSVCTMPL ]; then
    		echo Missing reboot service XML manifest
    		exit 1;
	fi

	#
	# If patching the live system, no repository directive is needed.
	# (and supplying one in that case can cause trouble)
	#
	if [[ "$ROOTDIR" == "/" ]] || [[ -z "$ROOTDIR" ]]; then
		REPOSITORY=
	else
		REPOSITORY="repository $ROOTDIR/etc/svc/repository.db"
	fi

	#
	# Build the list of script commands we need to add to the template
	#
	$PATCHEXEC/zfs_cache -R $ROOTDIR | patchfunc > /tmp/zfscmds.$$
	if ! /bin/mv $ZPOOL_CACHE $PATCHROOT/zpool.cache.patch-$PATCHID \
	     > /dev/null 2>&1 ; then
		#
		# If we can't move it, we must delete it
		#
		rm -f $ZPOOL_CACHE
	fi

	#
	# Modify the smf method template with the list of commands we just
	# generated.  These commands include zpool import and progress
	# display (output to /dev/console) support code.
	#
	/bin/sed -e "/"'%%ZFSCMDS%%'"/r /tmp/zfscmds.$$" \
		 -e "s/"'%%PATCHID%%'"/$PATCHID/g"		$FBTEMPLATE | \
	    /bin/grep -v '%%ZFSCMDS%%' > $ROOT_FBSVCMETH
	/bin/chmod 555 $ROOT_FBSVCMETH
	/bin/chown root:sys $ROOT_FBSVCMETH
	/bin/rm -f /tmp/zfscmds.$$

	#
	# Put the service manifest in /var/svc/manifest so it can be imported   
	# on next reboot.  The run-once service will run soon after.
	# 
	/bin/sed "s/"'%%PATCHID%%'"/$PATCHID/g" \
	    $FBSVCTMPL > $ROOTDIR/var/svc/manifest/system/patch-${PATCHID}.xml

}

CheckZones()
{
        if [ "$ROOTDIR" = "/" -a -x /usr/bin/zonename ]; then
                ZONENAME=`/usr/bin/zonename`
                if [ ${ZONENAME} = "global" ]; then
                        GLOBAL_ZONE=true
                else
                        GLOBAL_ZONE=false
                fi
        else
                # Unable to determine zone
                GLOBAL_ZONE=true
        fi
}

LocalZones () {

  # Only for FCS
  return 0
}


ExecuteALLCmds () {

	#
	# If SataKU patch is installed and this is the first KU patch 
	# to be added on top of it, then we must perform the following...
	#
	if PatchInstalled $SataKU ; then
		last_patch $SataKU
		status=$?
		if [ $status -eq 2 ] ; then
			#
			# cp scripts and templates to patch save area.  Used by both patchadd and patchrm
			#
			patch_tools=$ROOTDIR/var/sadm/patch/$PatchNum
			cp $patchdir/fbtmp* $patchdir/zfs_cache $patch_tools
			MdFixDevids
			SataSupport $patch_tools
			/usr/sbin/bootadm update-archive -R $ROOTDIR
		fi
	fi
}

ExecuteInProperEnvironment () {
 
   if $PKGCOND is_whole_root_nonglobal_zone > /dev/null 2>&1 ; then
       # Execute non-global whole root zone commands.
       # Should be same action as the default action.
       return 0
   fi

   if $PKGCOND is_nonglobal_zone > /dev/null 2>&1 ; then
       # Execute non-global zone commands. Should be no action here
       return 0
   fi

   if $PKGCOND is_netinstall_image > /dev/null 2>&1 ; then
       # Execute commands applicable to patching the mini-root.
       # There are usually no actions to take here since your patching
       # the mini-root on an install server.
       return 0
   fi

   if $PKGCOND is_mounted_miniroot > /dev/null 2>&1 ; then
       # Execute commands specific to the mini-root
       return 0
   fi

   if $PKGCOND is_diskless_client > /dev/null 2>&1 ; then
       # Execute commands specific to diskless client
       return 0
   fi

   if $PKGCOND is_alternative_root > /dev/null 2>&1 ; then
       # Execute commands specific to an alternate root
	ExecuteALLCmds
       return 0
   fi

   if $PKGCOND is_global_zone > /dev/null 2>&1 ; then
       # In a global zone and system is mounted on /.
       # Execute all commands.
	ExecuteALLCmds
       return 0
   fi

   return 1
} 

ZONENAME=global
[ -x /sbin/zonename ] && ZONENAME=`/sbin/zonename`

if [ -x $PKGCOND ] ; then
   ExecuteInProperEnvironment && exit 0 || exit 1
else
   CheckZones
   if [ "${GLOBAL_ZONE}" = "true" ]; then
        ExecuteALLCmds
   else
        LocalZones
   fi
fi 

exit 0
