# This script creates the backout package for a patch package
#
# directory format options.
#
# @(#) postinstall 1.13 01/01/12 SMI
#
# Copyright (c) 1995 by Sun Microsystems, Inc.
# All rights reserved
#

# Description:
#       Set the TYPE parameter for the remote file
#
# Parameters:
#       none
#
# Globals set:
#	TYPE

set_TYPE_parameter () {
	if [ ${PATCH_UNDO_ARCHIVE:?????} = "/dev" ]; then
		# handle device specific stuff
		TYPE="removable"
	else
		TYPE="filesystem"
	fi
}

#
# Description:
#       Build the remote file that points to the backout data
#
# Parameters:
#       $1:	the un/compressed undo archive
#
# Globals set:
#	UNDO, STATE

build_remote_file () {
	remote_path=$PKGSAV/$SUNW_PATCHID/remote
	set_TYPE_parameter
	STATE="active"

	if [ $1 = "undo" ]; then
		UNDO="undo"
	else
		UNDO="undo.Z"
	fi

	cat > $remote_path << EOF
# Backout data stored remotely
TYPE=$TYPE
FIND_AT=$ARCHIVE_DIR/$UNDO
STATE=$STATE
EOF
}

PATH=/usr/sadm/bin:$PATH

if [ "$PKG_INSTALL_ROOT" = "/" ]; then
	PKG_INSTALL_ROOT=""
fi

if [ -n "$PATCH_BUILD_DIR" -a -d "$PATCH_BUILD_DIR" ]; then
	BUILD_DIR="$PATCH_BUILD_DIR/$SUNW_PATCHID.$PKGINST"
else
	BUILD_DIR="$PKG_INSTALL_ROOT/var/tmp/$SUNW_PATCHID.$PKGINST"
fi

if [ ! -n "$PATCH_UNDO_ARCHIVE" ]; then
	PATCH_UNDO_ARCHIVE="none"
fi

FILE_DIR=$BUILD_DIR/files
RELOC_DIR=$FILE_DIR/reloc
ROOT_DIR=$FILE_DIR/root
BO_Deletes=$FILE_DIR/deletes
THIS_DIR=`dirname $0`
PROTO_FILE=$BUILD_DIR/prototype
TEMP_REMOTE=$PKGSAV/$SUNW_PATCHID/temp

if [ "$PATCH_PROGRESSIVE" = "true" ]; then
        # remove the scripts that are left behind
        install_scripts=`dirname $0`
        rm $install_scripts/checkinstall $install_scripts/patch_checkinstall $install_scripts/patch_postinstall

	# If this is being used in an old-style patch, insert
	# the old-style script commands here.

	#XXXOld_CommandsXXX#

	exit 0
fi

#
# At this point we either have a deletes file or we don't. If we do,
# we create a prototype entry.
#
if [ -f $BO_Deletes ]; then
	echo "i deletes=$BO_Deletes" >> $BUILD_DIR/prototype
fi

#
# Now delete everything in the deletes list after transferring
# the file to the backout package and the entry to the prototype
# file. Remember that the pkgmap will get the CLIENT_BASEDIR path
# but we have to actually get at it using the BASEDIR path. Also
# remember that removef will import our PKG_INSTALL_ROOT
#
Our_Deletes=$THIS_DIR/deletes
if [ -f $Our_Deletes ]; then
	cd $BASEDIR

	cat $Our_Deletes | while read path; do
		Reg_File=0

		if valpath -l $path; then
			Client_Path="$CLIENT_BASEDIR/$path"
			Build_Path="$RELOC_DIR/$path"
			Proto_Path=$BASEDIR/$path
		else	# It's an absolute path
			Client_Path=$path
			Build_Path="$ROOT_DIR$path"
			Proto_Path=$PKG_INSTALL_ROOT$path
		fi

		# If BASEDIR/CLIENTBASEDIR = "/", then the previous prepends
		# an extra / i.e. //. The sed command later can't find a
		# Proto_Path with // and therefore will not substitute the
		# correct build_Path resulting in the backout pkg not being
		# created.

		if [ "$CLIENT_BASEDIR" = "/" ]; then
			Client_Path=`echo $Client_Path | sed 's|^\/\/|\/|'`
			Proto_Path=`echo $Proto_Path | sed 's|^\/\/|\/|'`
		fi
			
		# Note: If the file isn't really there, pkgproto
		# doesn't write anything but displays an error
		# so check for the file before processing.

		if [ -f "$Proto_Path" ]; then
			LINE=`pkgproto $Proto_Path=$path`
		else
			continue
		fi

		ftype=`echo $LINE | nawk '{ print $1 }'`
		if [ "$ftype" = "f" ]; then
			Reg_File=1
		fi

		if [ $Reg_File = 1 ]; then
			# Add source file to the prototype entry
			if [ "$Proto_Path" = "$path" ]; then
				LINE=`echo $LINE | sed -e "s|$Proto_Path|$Build_Path|2"`
			else
				LINE=`echo $LINE | sed -e "s|$Proto_Path|$Build_Path|"`
			fi

			DirName=`dirname $Build_Path`
			# make room in the build tree
			mkdir -p $DirName
			cp -p $Proto_Path $Build_Path
		fi

		# Insert it into the prototype file
		echo $LINE 1>>$PROTO_FILE 2>/dev/null

		# Remove the file only if it's OK'd by removef
		rm `removef $PKGINST $Client_Path` 1>/dev/null 2>&1
	done
	removef -f $PKGINST

	rm $Our_Deletes
fi

#
# Unless specifically denied, make the backout package.
#
if [ "$PATCH_NO_UNDO" != "true" ]; then
	cd $BUILD_DIR	# We have to build from here.

	if [ "$PATCH_UNDO_ARCHIVE" != "none" ]; then
		STAGE_DIR="$PATCH_UNDO_ARCHIVE"
		ARCHIVE_DIR="$PATCH_UNDO_ARCHIVE/$SUNW_PATCHID/$PKGINST"
		mkdir -p $ARCHIVE_DIR
		mkdir -p $PKGSAV/$SUNW_PATCHID
	else
		if [ -d $PKGSAV/$SUNW_PATCHID ]; then
			rm -r $PKGSAV/$SUNW_PATCHID
		fi
		STAGE_DIR=$PKGSAV
		ARCHIVE_DIR=$PKGSAV/$SUNW_PATCHID
		mkdir $ARCHIVE_DIR
	fi

	pkgmk -o -d $STAGE_DIR 1>/dev/null 2>&1
	pkgtrans -s $STAGE_DIR $ARCHIVE_DIR/undo $PKG 1>/dev/null 2>&1
	compress $ARCHIVE_DIR/undo
	retcode=$?
	if [ "$retcode" != 0 ]; then
		echo "compress(1) returned error code $retcode"
		echo "The $PKGINST backout package will not be compressed."
		echo "Continuing to process backout package."
	fi
	if [ "$PATCH_UNDO_ARCHIVE" != "none" ]; then
		if [ $retcode != 0 ]; then
			build_remote_file "undo"
		else
			build_remote_file "undo.Z"
		fi
	fi
	rm -r $STAGE_DIR/$PKG

	cd ..
	rm -r $BUILD_DIR
	# remove the scripts that are left behind
	install_scripts=`dirname $0`
	rm $install_scripts/checkinstall $install_scripts/patch_checkinstall $install_scripts/patch_postinstall
fi

#
# Since this apparently worked, we'll mark as obsoleted the prior
# versions of this patch - installpatch deals with explicit obsoletions.
#
cd ${PKG_INSTALL_ROOT:-/}
cd var/sadm/pkg

active_base=`echo $SUNW_PATCHID | nawk '
	{ print substr($0, 1, match($0, "-")-1) } '`

List=`ls -d $PKGINST/save/${active_base}* 2>/dev/null`
if [ $? -ne 0 ]; then
	List=""
fi

for savedir in $List; do
        patch=`basename $savedir` 
        if [ $patch = $SUNW_PATCHID ]; then
		break
	fi

        # If we get here then the previous patch gets deleted
	if [ -f $savedir/undo ]; then
		mv $savedir/undo $savedir/obsolete
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
	elif [ -f $savedir/undo.Z ]; then
		mv $savedir/undo.Z $savedir/obsolete.Z
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
        elif  [ -f $savedir/remote ]; then
                `grep . $PKGSAV/$patch/remote | sed 's|STATE=.*|STATE=obsolete|' > $TEMP_REMOTE` 
                rm -f $PKGSAV/$patch/remote 
                mv $TEMP_REMOTE $PKGSAV/$patch/remote  
                rm -f $TEMP_REMOTE 
                echo $SUNW_PATCHID >> $savedir/obsoleted_by
	elif  [ -f $savedir/obsolete -o -f $savedir/obsolete.Z ]; then
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
	fi
done

# If additional operations are required for this package, place
# those package-specific commands here.

#XXXSpecial_CommandsXXX#

#pragma ident	"@(#)postinstall	1.23	06/01/09 SMI"
# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
# SUNWpd postinstall script

PATH="/usr/bin:/usr/sbin:${PATH}"
export PATH
EXIT=0
status=0

ISA_TYPE_I386="i386"
ISA_TYPE_SPARC="sparc"

ISA_TYPE="$ARCH"

# 
# Driver info 
# 
DRV=glm
DRVALIAS="\"pci1000,b\""
DRVPERM='* 0755 root sys'

NAMEMAJOR="$BASEDIR/etc/name_to_major"
MINORPERM="$BASEDIR/etc/minor_perm"
DEVLINKTB="$BASEDIR/etc/devlink.tab"
DRIVERALS="$BASEDIR/etc/driver_aliases"
PATH_TO_INST="$BASEDIR/etc/path_to_inst"
IUAP="$BASEDIR/etc/iu.ap"

if test ! -f ${NAMEMAJOR} -o ! -w ${NAMEMAJOR}; then
	echo "add_major: data file ${NAMEMAJOR} is missing/inaccessible." >&2
	exit 1
fi

if test ! -f ${MINORPERM} -o ! -w ${MINORPERM}; then
	echo "add_minor: data file ${MINORPERM} is missing/inaccessible." >&2
	exit 1
fi

if test ! -f ${DEVLINKTB} -o ! -w ${DEVLINKTB}; then
	echo "add_devlink: data file ${DEVLINKTB} is missing/inaccessible." >&2
	exit 1
fi

if test ! -f ${DRIVERALS} -o ! -w ${DRIVERALS}; then
	echo "add_drv_alias: data file ${DRIVERALS} is missing/inaccessible." >&2
	exit 1
fi

trap "rm -f /tmp/$$.*;exit 1" 1 2 3 13 15
TMP=/tmp/$$

# adds new major numbers to system for device drivers
# Usage:
#	add_major name1 name2 name3 name4 ....

add_major()
{
sort +1 -2n ${NAMEMAJOR} | nawk '#
BEGIN	{oldmajor = -1}
NR == 1	{n=split(namelist,x)
	 if (n < 1)
	    exit(1)
	 for (i=1; i<=n; i++)
	    chklist[x[i]]++
	}
	{for (name in chklist)
	 {
	    if ($1 == name)
		delete chklist[name]
	 }
	 if (($2 - oldmajor) > 1)
	 {
	    gap++
	    gaplist[gap] = oldmajor " " $2;
	 }
	 oldmajor = $2;
	}
END	{addsize=1
	 for (name in chklist)
	    addlist[addsize++] = name
	
	 addidx = 1
	 for (i=1; i<=gap && addidx < addsize; i++)
	 {
	    split(gaplist[i],x)
	    begmajor = x[1]
	    endmajor = x[2]
	    for (begmajor++;begmajor < endmajor && addidx < addsize;)
	    {
		printf "%s %d\n",addlist[addidx],begmajor
		addidx++
		begmajor++
	    }
	 }
	 for (; addidx < addsize; addidx++)
	 {
	    oldmajor++
	    printf "%s %d\n",addlist[addidx],oldmajor
	 }
	}
' namelist="$*" - > $TMP.new

if [ -s $TMP.new ]
then
#    echo "Adding following devices to ${NAMEMAJOR}"
#    cat $TMP.new
    sort +1 -2n ${NAMEMAJOR} $TMP.new -o ${NAMEMAJOR}
fi
}


# adds new minor permissions to system for device drivers
# Usage:
#	add_minor perm1 perm2 perm3 perm4 ....
#    i.e.
#	add_minor 'sd:* 0666 bin bin' 'sd:a 0644 root sys'

add_minor()
{
for p in "$@"
do echo "$p"
done | nawk '#
FILENAME != "-"	{permtab[$1] = $0;next}
FILENAME == "-"	{
		 if ($4 == "") {
			 printf("Missing token: (%s), skipping.\n", $0)
			 next
		 }
		 if ($5 != "") {
			 printf("Too many arguments: (%s), skipping.\n", $0)
			 next
		 }
		 if ($1 !~ /:/) {
			 printf("Bad name:minor pair: %s, skipping.\n", $1)
			 next
		 }
		 if ($2 < "0000" || $2 > "4777") {
			 printf("Bad mode: %s, skipping %s.\n", $2, $1)
			 next
		 }
		 if (!($1 in permtab))
		     print >> permtmp
		 next
		}
' permtmp=$TMP.perm ${MINORPERM} - >&2

if [ -s $TMP.perm ]
then
#	echo "Adding following permissions to ${MINORPERM}"
#	cat $TMP.perm
	sort +0 -1 ${MINORPERM} $TMP.perm -o ${MINORPERM}
fi
}


add_devlink()
{
while test $# -ge 2
do
echo "$1	$2"
shift 2
done | nawk '-F ' '#
FILENAME == "-"		{devlinktab[$1] = $0;next}
FILENAME != "-"		{if ($1 in devlinktab)
delete devlinktab[$1]
}
END			{for (d in devlinktab)
			    print devlinktab[d] >> devlinktmp
			}
' devlinktmp=$TMP.devlink - ${DEVLINKTB} >&2

if [ -s $TMP.devlink ]
then
#       echo "Adding following entries to ${DEVLINKTB}"
#       cat $TMP.devlink
	cat $TMP.devlink >> ${DEVLINKTB}
fi
}


# adds new entries to driver_aliases file
# Usage:
#	add_drv_alias spec1 spec2 spec3
#
#	where spec is:
#		<driver> <alias>
#

add_drv_alias()
{
while test $# -ge 2
do
	echo "$1 $2"
	shift 2
done | nawk '#
FILENAME == "-"		{newaliases[$2] = $1;next}
FILENAME != "-"		{if ($2 in newaliases) {
			     if ($1 == newaliases[$2])
				 delete newaliases[$2]
			 }
			}
END			{for (d in newaliases)
			    print newaliases[d],d > drvalias
			}
' drvalias=$TMP.drvalias - ${DRIVERALS} >&2
 
if [ -s $TMP.drvalias ]
then
#   echo "Adding following entries to ${DRIVERALS}"
#   cat $TMP.drvalias
    cat $TMP.drvalias >> ${DRIVERALS}
fi
}

# modunload the driver if installing on running system
if [ "${BASEDIR}" = "/" ]; then
        modnum=`set -- \`modinfo | grep ecpp\`; echo $1`
        if [ "$modnum" ]; then
                modunload -i $modnum
        fi
fi

# add_drv ecpp driver if not already installed
modnum=`grep -c ecpp ${NAMEMAJOR}`
if [ "$modnum" = "0" ]; then
	# add new entries to name_to_major, minor_perm,  driver_classes files
	/usr/sbin/add_drv -b ${BASEDIR} -i '"pnpALI,1533,3" "ns87317-ecpp"' -m '* 0666 root sys' -n ecpp || status=1
fi

rm -f /tmp/$$.*

# Do nothing on sparc machine.
if [ "${ISA_TYPE}" = "${ISA_TYPE_I386}" ]; then
	
	#
	# Select the correct add_drv options to execute for glm
	#
	if [ "${BASEDIR}" = "/" ]; then
		#
		# Irrespective of whether hardware exists
		# or not don't attempt to attach driver
		# to the hardware. This is to avoid problems
		# with installing a 32 bit driver on a 64 bit
		# running system.
		#
		ADD_DRV="add_drv -n"
	else
		#
		# On a client,
		# modify the system files and touch/reconfigure
		# for reconfigure reboot
		#
		ADD_DRV="add_drv -b ${BASEDIR}"
	fi

	# Remove references to symhisl if any in /etc/driver_aliases to
	# avoid confusion.
	grep -v "symhisl ${DRVALIAS}" $DRIVERALS >> $DRIVERALS.new
 
	mv $DRIVERALS.new $DRIVERALS

	# Remove references to symhisl if any in /etc/path_to_inst to
	# avoid confusion.
	grep -v "pci1000,b@" $PATH_TO_INST >> $PATH_TO_INST.new
 
	mv $PATH_TO_INST.new $PATH_TO_INST

	#
	# Make sure add_drv has *not* been previously executed
	# before attempting to add glm driver.
	#
	grep -w "${DRV}" ${BASEDIR}/etc/name_to_major > /dev/null 2>&1
	if [ $? -eq 1 ]; then
		${ADD_DRV} -m "${DRVPERM}" -i "${DRVALIAS}" -c scsi ${DRV}
		if [ $? -ne 0 ]; then
			echo "\nFailed add_drv!\n" >&2
			exit 1
		fi
	else
		exit 0
	fi
fi

exit $status
