Home | History | Annotate | Download | only in scripts
      1 #!/bin/ksh -p
      2 #
      3 # CDDL HEADER START
      4 #
      5 # The contents of this file are subject to the terms of the
      6 # Common Development and Distribution License (the "License").
      7 # You may not use this file except in compliance with the License.
      8 #
      9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10 # or http://www.opensolaris.org/os/licensing.
     11 # See the License for the specific language governing permissions
     12 # and limitations under the License.
     13 #
     14 # When distributing Covered Code, include this CDDL HEADER in each
     15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16 # If applicable, add the following below this CDDL HEADER, with the
     17 # fields enclosed by brackets "[]" replaced with your own identifying
     18 # information: Portions Copyright [yyyy] [name of copyright owner]
     19 #
     20 # CDDL HEADER END
     21 #
     22 #
     23 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 #
     26 #ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #
     29 # usage: acr [root [archivedir]]
     30 #
     31 # examples:  acr
     32 #	     acr /export/home/zone/root
     33 #	     acr /export/home/zone/root ${CODEMGR_WS}/archives/sparc/nightly
     34 #
     35 
     36 if [ $# -gt 2 ] ; then
     37 	print -u2 "usage:  $0 <root> <archivedir>"
     38 	exit 1
     39 fi
     40 
     41 root=${1-/}
     42 archivedir=$2
     43 if [ -z "$archivedir" -o "$archivedir" = again ]; then
     44 	if [ ! -s $root/etc/motd ]; then
     45 		print -u2 "$root/etc/motd not found; this doesn't look like a" \
     46 		    "valid root."
     47 		exit 1
     48 	fi
     49 	archivedir=$(nawk '/^bfu.ed from / { print $3; exit }' $root/etc/motd)
     50 fi
     51 
     52 if [ ! -d "$archivedir" ]; then
     53     	print -u2 "Archive directory '$archivedir' not found."
     54 	exit 1
     55 fi
     56 
     57 #
     58 # temporary file scorecard:
     59 #
     60 # conflictscripts	list of scripts we need to run.
     61 #
     62 # installnew		list of editable files without class action scripts
     63 #
     64 # processedscript	basename of class action script edited to NOP
     65 #			installf/removef's and use /tmp/bfubin
     66 #
     67 # allresults		log of all class action script output.
     68 #
     69 # thisresult		log of most recent class action script
     70 #
     71 
     72 tmpdir=$(mktemp -t -d acr.XXXXXX)
     73 
     74 if [ -z "$tmpdir" ] ; then
     75     	print -u2 "mktemp failed to produce output; aborting."
     76 	exit 1
     77 fi
     78 
     79 if [ ! -d $tmpdir ] ; then
     80     	print -u2 "mktemp failed to create a directory; aborting."
     81 	exit 1
     82 fi
     83 
     84 conflictscripts=$tmpdir/conflictscripts
     85 installnew=$tmpdir/installnew
     86 allresults=$tmpdir/allresults
     87 thisresult=$tmpdir/thisresult
     88 processedscript=$tmpdir/processedscript
     89 
     90 #
     91 # This file is left over (on purpose) by BFU so that in a post-BFU environment
     92 # we know which zones BFU processed.
     93 #
     94 bfu_zone_list=$root/.bfu_zone_list
     95 
     96 get_cr_archive() {
     97 	compressed_archive=$archivedir/conflict_resolution.gz
     98 	if [ ! -s $compressed_archive ] ; then
     99 		print -u2 "Failed to find conflict resolution information" \
    100 		    "at $compressed_archive."
    101 		return 1
    102 	fi
    103 
    104 	print -n "Getting ACR information from $archivedir... "
    105 
    106 	gzip -d -c $compressed_archive | \
    107 	    (cd $tmpdir; cpio -idmucB > /dev/null 2>&1) || return 1
    108 
    109 	crdir=$tmpdir/conflict_resolution
    110 
    111 	if [ ! -d $crdir ] ; then
    112 		print -u2 "The conflict resolution archive is missing the" \
    113 		    "conflict_resolution directory."
    114 		return 1
    115 	fi
    116 
    117 	if [ ! -f $crdir/editable_file_db ] ; then
    118 		print -u2 "The conflict resolution archive is missing the" \
    119 			"editable file list."
    120 		return 1
    121 	fi
    122 	print "ok"
    123 	return 0
    124 }
    125 
    126 #
    127 # If we're running after a BFU, some behaviors are different.
    128 #
    129 if [ -d /tmp/bfubin ] ; then
    130 	bfu_alt_reality="true"
    131 else
    132 	bfu_alt_reality="false"
    133 fi
    134 
    135 
    136 acr_a_root() {
    137 	typeset root
    138 	typeset zone
    139 
    140 	root=$1
    141 	zone=$2
    142 
    143 	print "ZONE $2 on $1" >> $allresults
    144 
    145 
    146 	rm -f $conflictscripts
    147 	rm -f $installnew
    148 
    149 	#
    150 	# The files that need to be processed are those that were stored by
    151 	# bfu in bfu.conflicts.  Just process those that changed in the
    152 	# distribution since the last bfu (those that are listed in the
    153 	# $root/bfu.conflicts/NEW file).
    154 	#
    155 	if [ ! -d $root/bfu.conflicts ] ; then
    156 		print -u2 "No BFU conflict information."
    157 		return 1
    158 	fi
    159 
    160 	if [ ! -s $root/bfu.conflicts/NEW ] ; then
    161 		print "No conflicts to resolve."
    162 		return 0
    163 	fi
    164 
    165 	#
    166 	# Some class-action scripts rely on being run in the order defined in
    167 	# packages.  The $crdir/editable_file_db file contains the classes
    168 	# in the correct order, so we preserve that order.
    169 	#
    170 	cat $crdir/editable_file_db | \
    171 	while read filename script pkg pkginst isa mach unique pkgdef
    172 	do
    173 		grep "^$filename\$" $root/bfu.conflicts/NEW >> /dev/null || \
    174 		    continue
    175 
    176 		if [ "$mach" != "-" -a  $(uname -m) != "$mach" ] ; then
    177 			continue
    178 		fi
    179 
    180 		print $filename $script $pkg $pkginst $isa $mach $unique \
    181 		    $pkgdef >> $conflictscripts
    182 	done
    183 
    184 	if [ ! -s $conflictscripts ] ; then
    185 		print "\nNo upgrade scripts were found for any of the" \
    186 		    "conflicting files."
    187 		return 1
    188 	fi
    189 
    190 
    191 	#
    192 	# Look for files that are in the conflict list, but don't have
    193 	# entries in the $conflictscripts file.  These have no
    194 	# install scripts, so should just be copied. (The fact that such
    195 	# files exist indicates a bug in bfu or possibly in the Solaris
    196 	# packaging.  If these are really editable files, they should have
    197 	# class action scripts.  If not, bfu shouldn't special-case them.)
    198 	#
    199 	cat $root/bfu.conflicts/NEW | while read filename ; do
    200 		grep "$filename " $conflictscripts >> /dev/null
    201 		if [ $? != 0 ] ; then
    202 			print $filename >> $installnew
    203 		fi
    204 	done
    205 
    206 	if [ -s $installnew ] ; then
    207 		print "\n    The following files did not have conflict" \
    208 		    "resolution scripts; this may"
    209 		print "    indicate a bug in BFU.  The new versions will be" \
    210 		    "installed.  The previous"
    211 		print "    versions of these files can be found in" \
    212 		    "$root/bfu.child:\n"
    213 		cat $installnew | sed 's/^/        /'
    214 		print
    215 	fi
    216 
    217 	UPDATE=yes
    218 	BASEDIR=$root
    219 	PKGSAV=/tmp
    220 	PKG_INSTALL_ROOT=$root
    221 	export UPDATE BASEDIR PKGSAV PKG_INSTALL_ROOT
    222 
    223 	column_fmt='    %-35s  %-20s '
    224 
    225 	printf "\n$column_fmt %s\n" "FILE" "ACTION" "STATUS"
    226 	cat $conflictscripts | while read filename script pkg pkginst isa mach \
    227 	    unique pkgdef ; do
    228 		if [ "$script" = "upgrade_default" ] ; then
    229 			msg=`printf "$column_fmt" \
    230 			    $filename "upgrade_default_copy"`
    231 			cp $root/bfu.conflicts/$filename $root/$filename
    232 			if [ $? != 0 ]; then
    233 				printf "$msg ok\n"
    234 				continue
    235 			else
    236 				printf "$msg FAIL\n" 1>&2
    237 				return 1
    238 			fi
    239 		fi
    240 
    241 		if [ "$unique" = "c" ] ; then
    242 			scriptloc=$crdir/$pkgdef/$script
    243 		else
    244 			scriptloc=$crdir/$pkgdef/$pkginst/$script
    245 		fi
    246 		msg=`printf "$column_fmt" $filename $script`
    247 
    248 		#
    249 		# If we are running in the post-BFU alternate reality, we need
    250 		# to modify the class action script to work in that alternate
    251 		# reality.  Otherwise, we merely need to "neuter" installf
    252 		# and removef.  In any event, skip this one and go to the next
    253 		# if the sed fails.
    254 		#
    255 		if [ $bfu_alt_reality = "true" ] ; then
    256 			sed -e 's,^#!/bin/sh,#!/tmp/bfubin/sh,' \
    257 			    -e 's,/usr/bin/,/tmp/bfubin/,g' \
    258 			    -e 's,/usr/bin:,/tmp/bfubin:,' \
    259 			    -e 's,installf,/tmp/bfubin/true,' \
    260 			    -e 's,removef,/tmp/bfubin/true,' \
    261 			    $scriptloc > $processedscript.$script
    262 			error=$?
    263 		else
    264 			sed -e 's,installf,/usr/bin/true,' \
    265 			    -e 's,removef,/usr/bin/true,' \
    266 			    $scriptloc > $processedscript.$script
    267 			error=$?
    268 		fi
    269 
    270 		if [ $error != 0 ] ; then
    271 			printf "$msg FAIL (sed surgery->$error)\n" 1>&2
    272 			continue
    273 		fi
    274 
    275 		chmod +x $processedscript.$script
    276 		error=$?
    277 		if [ $error != 0 ] ; then
    278 			printf "$msg FAIL (chmod->$error)\n" 1>&2
    279 			continue
    280 		fi
    281 
    282 		PKG=$pkg
    283 		PKGINST=$pkg
    284 		if [ $mach = "-" ] ; then
    285 			ARCH=$isa
    286 		else
    287 			ARCH=$isa.$mach
    288 		fi
    289 		export PKG PKGINST ARCH
    290 
    291 		print "PROCESSING $filename with $script" >> $allresults
    292 		print $root/bfu.conflicts/$filename $root/$filename |
    293 			$processedscript.$script > $thisresult 2>&1
    294 		error=$?
    295 		if [ $error != 0 ] ; then
    296 			printf "$msg FAIL (exit $error)\n" 1>&2
    297 			print -u2 "    Output of upgrade script:"
    298 			sed 's/^/        /' < $thisresult >&2
    299 		else
    300 			printf "$msg ok\n"
    301 		fi
    302 		cat $thisresult >> $allresults
    303 		print "RETURN CODE: $error" >> $allresults
    304 	done
    305 
    306 	if [ -s $installnew ] ; then
    307 		cat $installnew | while read filename ; do
    308 
    309 			msg=`printf "$column_fmt" $filename \
    310 			    "cp from new version"`
    311 			cp $root/bfu.conflicts/$filename $root/$filename
    312 			error=$?
    313 			if [ $error != 0 ] ; then
    314 				printf "$msg FAIL (exit $error)\n" 1>&2
    315 			else
    316 				printf "$msg ok\n"
    317 			fi
    318 
    319 		done
    320 	fi
    321 }
    322 
    323 #
    324 # If we're post-BFU, then BFU should have left us a file listing which zones it
    325 # processed.  If we're not post-BFU, just process all installed native and
    326 # Sn-1 zones.
    327 #
    328 if [ $bfu_alt_reality = "false" ]; then
    329 	zoneadm list -pi | nawk -F: '{
    330 		if ($3 == "installed" &&
    331 		    ($6 == "native" || $6 == "" || $6 == "sn1")) {
    332 			printf "%s %s\n", $2, $4
    333 		}
    334 	}' > $bfu_zone_list
    335 fi
    336 
    337 #
    338 # To be terse, check whether there is any work to do at all; if not,
    339 # just print one line and exit.
    340 #
    341 need_resolve=false
    342 if [ -s $root/bfu.conflicts/NEW ]; then
    343 	need_resolve=true
    344 else
    345 	if [ -s $bfu_zone_list ]; then
    346 		cat $bfu_zone_list | while read zone zonepath; do
    347 			if [ -s $zonepath/root/bfu.conflicts/NEW ] ; then
    348 				need_resolve=true
    349 			fi
    350 		done
    351 	fi
    352 fi
    353 
    354 if [ "$need_resolve" = "false" ]; then
    355 	print "No conflicts to resolve."
    356 	exit 0
    357 fi
    358 
    359 get_cr_archive || exit 1
    360 
    361 printf "\nProcessing global zone:\t"
    362 acr_a_root $root "global"
    363 
    364 if [ $root != "/" ]; then
    365 	printf "\nSkipping non-global zones (root is not /)"
    366 else
    367 	if [ -s $bfu_zone_list ]; then
    368 		cat $bfu_zone_list | while read zone zonepath; do
    369 			printf "\nProcessing zone $zone:\t"
    370 			acr_a_root $zonepath/root $zone
    371 		done
    372 	fi
    373 fi
    374 
    375 echo
    376 
    377 # workaround for 6644920
    378 BIN=bin
    379 cr_args=${root:+ -R $root}
    380 LD_LIBRARY_PATH=/tmp/bfulib PATH=/tmp/bfubin \
    381     /tmp/bfubin/ksh $root/boot/solaris/$BIN/create_ramdisk $cr_args
    382 
    383 print "Finished.  See $allresults for complete log."
    384