#!/bin/ksh -p

## Patch is the minimum path number that is required
## This assumes that the patch also includes a regular SUNW_REQUIRES for patch

PATH=/usr/bin:/usr/sbin:$PATH; export PATH
PKGCOND=/usr/bin/pkgcond

 patch=118855-14
 uname=$(uname -v)
 uname=${uname##*_}    # remove text before underscore...

 if [ "$ROOTDIR" = "/" ] ; then
     if [[ $uname == "Generic" ]] || \
     [[ ${uname%-*} == ${patch%-*} && ${uname#*-} -lt ${patch#*-} ]]; then
         print -u2 "\
         In order to apply this libc patch, the Kernel patch ${patch},
         or a higher rev, must be installed and the system rebooted
         prior to installing this patch. \
         "
         exit 1
    fi
 fi


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 CheckForRequiredFiles {

#
# Look for required files;  if any are missing, bail out with an error.
#

	if [ ! -x $patchdir/zfs_cache ]; then
		echo ERROR: Missing zfs_cache command.
		exit 1;
	fi

	if [ ! -f $patchdir/fbtmplmeth.ksh ]; then
		echo ERROR: Missing reboot service method template
		exit 1;
	fi

	if [ ! -f $patchdir/fbtmplsvc.xml ]; then
		echo ERROR: Missing reboot service XML manifest
		exit 1;
	fi

	return 0

}

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
}

not_installed() {
        driver=$1
        grep "^${driver} " $ROOTDIR/etc/name_to_major > /dev/null 2>&1

        return $?
}

update_logindevperm() {
        cp $ROOTDIR/etc/logindevperm $ROOTDIR/etc/logindevperm.before-$PatchNum

}

load_mods() {

	## load modules during patch installation per 6349240
	## to prevent warnings from displaying on the console
	## before the system is rebooted.

	## find all kernel driver modules in patch
	PLATFORM=`uname -i`
	CLASS=`uname -m`
 	ISA_INFO=`/usr/bin/isainfo -b`

	cd  ${patchdir:-$PWD}

		for i in *
		do
		pkginfo `echo $i | cut -f 1 -d '.'` > /dev/null 2>&1
			if [ $? -eq 0 ]; then
				grep " kernel\>" $i/pkgmap | grep -v mpxio | grep -v kmdb
				grep "/kernel\>" $i/pkgmap | grep "$PLATFORM" | grep -v "cpu"
				grep "/kernel\>" $i/pkgmap | grep "$CLASS/" | grep -v "cpu"
			fi

		done 2>/dev/null | nawk '/^1 f/ && ! /\.conf|\/unix|\/genunix/ {print $4}' >/tmp/modules.$$

		if [ "$ROOTDIR" = "/" ] ; then

		##
		## Disable kernel module unloading
		##
		print "Disabling kernel module unloading ... \n"
		if [ -x /usr/bin/mdb ]; then
			if [ $ISA_INFO = 64 ]; then
				SAVED_ADDR=`echo '_kobj_printf/J' | mdb -k | cut -f2 -d ':'` 
				echo '_kobj_printf/Z systrace_stub' | mdb -kw > /dev/null 2>&1
			else
				SAVED_ADDR=`echo '_kobj_printf/X' | mdb -k | cut -f2 -d ':'`
				echo '_kobj_printf/W systrace_stub' | mdb -kw > /dev/null 2>&1
			fi
			echo "moddebug/W20000" | adb -kw /dev/ksyms /dev/mem | grep moddebug > /dev/null 2>&1

		else
			echo "mdb not found: patchadd not safe."
		fi

		while read line; do
		## preload each module
			[ -f /$line ] && {
				## echo "loading module $line"
				modload /$line > /dev/null 2>&1
			}

		done < /tmp/modules.$$

		fi

		if [ $ISA_INFO = 64 ]; then
			echo '_kobj_printf/Z '$SAVED_ADDR | mdb -kw > /dev/null 2>&1
		else
			echo '_kobj_printf/W '$SAVED_ADDR | mdb -kw  > /dev/null 2>&1
		fi

	mv /tmp/modules.$$ /tmp/backoutmods.$PatchNum
}


Execute_commands() {

   CheckForRequiredFiles
   load_mods
   update_logindevperm


   return 0
}

LocalZones () {
# commands specific to non-gloabl zones
return 0

}

ExecuteInProperEnvironment () {

   if $PKGCOND is_whole_root_nonglobal_zone > /dev/null 2>&1 ; then
       # Execute non-global whole root zone commands.
	update_logindevperm;
       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.
	update_logindevperm;
       return 0
   fi

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

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

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

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

   return 1
} 

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

exit 0

