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