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 2009 Sun Microsystems, Inc. All rights reserved. 24 # Use is subject to license terms. 25 # 26 # 27 # usage: acr [root [archivedir]] 28 # 29 # examples: acr 30 # acr /export/home/zone/root 31 # acr /export/home/zone/root ${CODEMGR_WS}/archives/sparc/nightly 32 # 33 34 if [ $# -gt 2 ] ; then 35 print -u2 "usage: $0 <root> <archivedir>" 36 exit 1 37 fi 38 39 root=${1-/} 40 archivedir=$2 41 if [ -z "$archivedir" -o "$archivedir" = again ]; then 42 if [ ! -s $root/etc/motd ]; then 43 print -u2 "$root/etc/motd not found; this doesn't look like a" \ 44 "valid root." 45 exit 1 46 fi 47 archivedir=$(nawk '/^bfu.ed from / { print $3; exit }' $root/etc/motd) 48 fi 49 50 if [ ! -d "$archivedir" ]; then 51 print -u2 "Archive directory '$archivedir' not found." 52 exit 1 53 fi 54 55 # 56 # temporary file scorecard: 57 # 58 # conflictscripts list of scripts we need to run. 59 # 60 # installnew list of editable files without class action scripts 61 # 62 # processedscript basename of class action script edited to NOP 63 # installf/removef's and use /tmp/bfubin 64 # 65 # allresults log of all class action script output. 66 # 67 # thisresult log of most recent class action script 68 # 69 70 tmpdir=$(mktemp -t -d acr.XXXXXX) 71 72 if [ -z "$tmpdir" ] ; then 73 print -u2 "mktemp failed to produce output; aborting." 74 exit 1 75 fi 76 77 if [ ! -d $tmpdir ] ; then 78 print -u2 "mktemp failed to create a directory; aborting." 79 exit 1 80 fi 81 82 conflictscripts=$tmpdir/conflictscripts 83 installnew=$tmpdir/installnew 84 allresults=$tmpdir/allresults 85 thisresult=$tmpdir/thisresult 86 processedscript=$tmpdir/processedscript 87 88 # 89 # This file is left over (on purpose) by BFU so that in a post-BFU environment 90 # we know which zones BFU processed. 91 # 92 bfu_zone_list=$root/.bfu_zone_list 93 94 get_cr_archive() { 95 compressed_archive=$archivedir/conflict_resolution.gz 96 if [ ! -s $compressed_archive ] ; then 97 print -u2 "Failed to find conflict resolution information" \ 98 "at $compressed_archive." 99 return 1 100 fi 101 102 print -n "Getting ACR information from $archivedir... " 103 104 gzip -d -c $compressed_archive | \ 105 (cd $tmpdir; cpio -idmucB > /dev/null 2>&1) || return 1 106 107 crdir=$tmpdir/conflict_resolution 108 109 if [ ! -d $crdir ] ; then 110 print -u2 "The conflict resolution archive is missing the" \ 111 "conflict_resolution directory." 112 return 1 113 fi 114 115 if [ ! -f $crdir/editable_file_db ] ; then 116 print -u2 "The conflict resolution archive is missing the" \ 117 "editable file list." 118 return 1 119 fi 120 print "ok" 121 return 0 122 } 123 124 # 125 # If we're running after a BFU, some behaviors are different. 126 # 127 if [ -d /tmp/bfubin ] ; then 128 bfu_alt_reality="true" 129 else 130 bfu_alt_reality="false" 131 fi 132 133 134 acr_a_root() { 135 typeset root 136 typeset zone 137 138 root=$1 139 zone=$2 140 141 print "ZONE $2 on $1" >> $allresults 142 143 144 rm -f $conflictscripts 145 rm -f $installnew 146 147 # 148 # The files that need to be processed are those that were stored by 149 # bfu in bfu.conflicts. Just process those that changed in the 150 # distribution since the last bfu (those that are listed in the 151 # $root/bfu.conflicts/NEW file). 152 # 153 if [ ! -d $root/bfu.conflicts ] ; then 154 print -u2 "No BFU conflict information." 155 return 1 156 fi 157 158 if [ ! -s $root/bfu.conflicts/NEW ] ; then 159 print "No conflicts to resolve." 160 return 0 161 fi 162 163 # 164 # Some class-action scripts rely on being run in the order defined in 165 # packages. The $crdir/editable_file_db file contains the classes 166 # in the correct order, so we preserve that order. 167 # 168 cat $crdir/editable_file_db | \ 169 while read filename script pkg pkginst isa mach unique pkgdef 170 do 171 grep "^$filename\$" $root/bfu.conflicts/NEW >> /dev/null || \ 172 continue 173 174 if [ "$mach" != "-" -a $(uname -m) != "$mach" ] ; then 175 continue 176 fi 177 178 print $filename $script $pkg $pkginst $isa $mach $unique \ 179 $pkgdef >> $conflictscripts 180 done 181 182 if [ ! -s $conflictscripts ] ; then 183 print "\nNo upgrade scripts were found for any of the" \ 184 "conflicting files." 185 return 1 186 fi 187 188 189 # 190 # Look for files that are in the conflict list, but don't have 191 # entries in the $conflictscripts file. These have no 192 # install scripts, so should just be copied. (The fact that such 193 # files exist indicates a bug in bfu or possibly in the Solaris 194 # packaging. If these are really editable files, they should have 195 # class action scripts. If not, bfu shouldn't special-case them.) 196 # 197 cat $root/bfu.conflicts/NEW | while read filename ; do 198 grep "$filename " $conflictscripts >> /dev/null 199 if [ $? != 0 ] ; then 200 print $filename >> $installnew 201 fi 202 done 203 204 if [ -s $installnew ] ; then 205 print "\n The following files did not have conflict" \ 206 "resolution scripts; this may" 207 print " indicate a bug in BFU. The new versions will be" \ 208 "installed. The previous" 209 print " versions of these files can be found in" \ 210 "$root/bfu.child:\n" 211 cat $installnew | sed 's/^/ /' 212 print 213 fi 214 215 UPDATE=yes 216 BASEDIR=$root 217 PKGSAV=/tmp 218 PKG_INSTALL_ROOT=$root 219 export UPDATE BASEDIR PKGSAV PKG_INSTALL_ROOT 220 221 column_fmt=' %-35s %-20s ' 222 223 printf "\n$column_fmt %s\n" "FILE" "ACTION" "STATUS" 224 cat $conflictscripts | while read filename script pkg pkginst isa mach \ 225 unique pkgdef ; do 226 if [ "$script" = "upgrade_default" ] ; then 227 msg=`printf "$column_fmt" \ 228 $filename "upgrade_default_copy"` 229 cp $root/bfu.conflicts/$filename $root/$filename 230 if [ $? = 0 ]; then 231 printf "$msg ok\n" 232 continue 233 else 234 printf "$msg FAIL\n" 1>&2 235 return 1 236 fi 237 fi 238 239 if [ "$unique" = "c" ] ; then 240 scriptloc=$crdir/$pkgdef/$script 241 elif [ "$unique" = "s" ] ; then 242 scriptloc=$crdir/$pkgdef/$pkginst/$script 243 else 244 scriptloc=$root/usr/sadm/install/scripts/$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 if [ "$script" = "i.build" ] ; then 293 print $crdir/$pkgdef/$pkginst/$filename $root/$filename | 294 $processedscript.$script > $thisresult 2>&1 295 else 296 print $root/bfu.conflicts/$filename $root/$filename | 297 $processedscript.$script > $thisresult 2>&1 298 fi 299 error=$? 300 if [ $error != 0 ] ; then 301 printf "$msg FAIL (exit $error)\n" 1>&2 302 print -u2 " Output of upgrade script:" 303 sed 's/^/ /' < $thisresult >&2 304 else 305 printf "$msg ok\n" 306 fi 307 cat $thisresult >> $allresults 308 print "RETURN CODE: $error" >> $allresults 309 done 310 311 if [ -s $installnew ] ; then 312 cat $installnew | while read filename ; do 313 314 msg=`printf "$column_fmt" $filename \ 315 "cp from new version"` 316 cp $root/bfu.conflicts/$filename $root/$filename 317 error=$? 318 if [ $error != 0 ] ; then 319 printf "$msg FAIL (exit $error)\n" 1>&2 320 else 321 printf "$msg ok\n" 322 fi 323 324 done 325 fi 326 } 327 328 # 329 # If we're post-BFU, then BFU should have left us a file listing which zones it 330 # processed. If we're not post-BFU, just process all installed native and 331 # Sn-1 zones. 332 # 333 if [ $bfu_alt_reality = "false" ]; then 334 zoneadm list -pi | nawk -F: '{ 335 if ($3 == "installed" && 336 ($6 == "native" || $6 == "" || $6 == "sn1")) { 337 printf "%s %s\n", $2, $4 338 } 339 }' > $bfu_zone_list 340 fi 341 342 # 343 # To be terse, check whether there is any work to do at all; if not, 344 # just print one line and exit. 345 # 346 need_resolve=false 347 if [ -s $root/bfu.conflicts/NEW ]; then 348 need_resolve=true 349 else 350 if [ -s $bfu_zone_list ]; then 351 cat $bfu_zone_list | while read zone zonepath; do 352 if [ -s $zonepath/root/bfu.conflicts/NEW ] ; then 353 need_resolve=true 354 fi 355 done 356 fi 357 fi 358 359 if [ "$need_resolve" = "false" ]; then 360 print "No conflicts to resolve." 361 exit 0 362 fi 363 364 get_cr_archive || exit 1 365 366 printf "\nProcessing global zone:\t" 367 acr_a_root $root "global" 368 369 if [ $root != "/" ]; then 370 printf "\nSkipping non-global zones (root is not /)" 371 else 372 if [ -s $bfu_zone_list ]; then 373 cat $bfu_zone_list | while read zone zonepath; do 374 printf "\nProcessing zone $zone:\t" 375 acr_a_root $zonepath/root $zone 376 done 377 fi 378 fi 379 380 echo 381 382 # workaround for 6644920 383 BIN=bin 384 cr_args=${root:+ -R $root} 385 LD_LIBRARY_PATH=/tmp/bfulib PATH=/tmp/bfubin \ 386 /tmp/bfubin/ksh $root/boot/solaris/$BIN/create_ramdisk $cr_args 387 388 print "Finished. See $allresults for complete log." 389