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 2008 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 # 
     26 # This script builds the overhead information used by bfu to do
     27 # automatic conflict resolution.  This overhead information is stored
     28 # in a gzip'ed cpio archive called "conflict_resolution.gz" in the
     29 # archive directory. It contains all of the class-action script
     30 # required to upgrade the editable files, plus a control file
     31 # (editable_file_db) which lists the editable files and the
     32 # class-action scripts needed to upgrade them.
     33 #
     34 
     35 parse_pkginfo() {
     36 
     37 	isa=$1
     38 	dir=$2
     39 
     40 	nawk -v matchisa=$isa -v pkginst=$dir -F= '
     41 
     42 	# This clause matches architecture specific entries. e.g. CLASSES_i386=
     43 	# It has a different format to the other ERE entries as this allows
     44 	# the variable substition.
     45 
     46 	$1 ~ "CLASSES_"matchisa"[\t ]*$" {
     47 		gsub(/"/, "", $2);
     48 		numisaclasses = split($2, isaclasses, " ");
     49 		next;
     50 	}
     51 	/^CLASSES *=/ {
     52 	  	gsub(/"/, "", $2);
     53 		numclasses = split($2, classes, " ");
     54 	  	next;
     55 	}
     56 	/^PKG *=/  {
     57 	  	gsub(/"/, "", $2);
     58 		pkg = $2;
     59 		next;
     60 	}
     61 	/^ARCH *=/ {
     62 		mach = "-";
     63 	  	gsub(/"/, "", $2);
     64 		if ($2 ~ /ISA/) {
     65 			pkgisa = matchisa;
     66 		} else {
     67 			dotpos = index($2, ".");
     68 			if (dotpos != 0 ) {
     69 				pkgisa = substr($2, 1, dotpos - 1);
     70 				mach = substr($2, dotpos + 1);
     71 			} else {
     72 				pkgisa = $2
     73 			}
     74 		}
     75 		if (pkgisa != matchisa)
     76 			exit 0;
     77 		next;
     78 	}
     79 	END {
     80 		if (numclasses == 0 && numisaclasses == 0)
     81 			exit 0;
     82 
     83 		for (i in isaclasses) {
     84 		    	if (isaclasses[i] == "none") 
     85 			    	continue;
     86 
     87 			printf("%s %s %s %s %s\n", pkg, pkginst, pkgisa, mach, 
     88 				isaclasses[i]);
     89 		}
     90 		for (i in classes) {
     91 		    	if (classes[i] == "none") 
     92 			    	continue;
     93 
     94 			printf("%s %s %s %s %s\n", pkg, pkginst, pkgisa, mach, 
     95 				classes[i]);
     96 		}
     97 	}
     98 	' $dir/pkginfo.tmpl 
     99 }
    100 
    101 
    102 process_non_on_classes () {
    103 
    104     # $1 is one of non_on_classes
    105     # $2 is editablefilelist
    106     nononclass=$1
    107     efilelist=$2
    108     pkgdir=$3
    109     
    110     if [ "$1" = "build" ] ; then
    111 	# print the target file name and pkg name from editablefilelist
    112 	nawk -v class=${nononclass} '$3 == class { print $1,$2 }' $efilelist | \
    113 	    while read tgtfile pkgname; do
    114 		mkdir -p ${pkgdir}/${pkgname}/`dirname ${tgtfile}`
    115 		if [ -s ${pkgname}/`basename ${tgtfile}` ] ; then
    116 		    cp ${pkgname}/`basename ${tgtfile}` \
    117 			${pkgdir}/${pkgname}/${tgtfile}
    118 		else
    119 		    print -u2 "mkacr: Can't find i.build source script."
    120 		fi
    121 	    done
    122     fi
    123 }
    124 
    125 #
    126 # the process_pkdefs_directory function generates the conflict
    127 # resolution information for a single pkgdefs directory (there can
    128 # be more than one in an ON workspace).
    129 # 
    130 # It gets two arguments explicitly:
    131 #	$1 - the location of the pkgdefs directory
    132 #	$2 - a string to be used as a "uniquifier" for generating
    133 #	     pathnames for class files (there can be more than one
    134 #	     class action script with the same name, but they are all
    135 #	     stored in one directory in the conflict resolution
    136 #	     database).
    137 #
    138 # It gets two pieces of data globally:  the values of the "corepkgs"
    139 # and the "bfu_incompatible_classes" variables.
    140 #
    141 process_pkgdefs_directory() {
    142 
    143 	pkgdefsdir=$1
    144 	un=$2
    145 
    146 	cd $pkgdefsdir
    147 
    148 	# Step 1: Generate a list of packages to be processed, with the
    149 	# "core" packages at the head of the list.
    150 
    151 	if [ "$ACR_DEBUG" = "yes" ] ; then
    152 		print "Step 1: Generating list of packages to be processed"
    153 	fi
    154 
    155 	for dir in $corepkgs; do
    156 		if [ -d $dir -a -s $dir/pkginfo.tmpl -a \
    157 		     -s $dir/prototype_$isa ] ; then
    158 			print $dir
    159 		fi
    160 	done | sort > $pkglist
    161 
    162 	for dir in *; do
    163 		if [ -d $dir -a -s $dir/pkginfo.tmpl -a \
    164 		    -s $dir/prototype_$isa ] ; then
    165 			print $dir
    166 		fi
    167 	done | sort > $allpkglist
    168 
    169 	# make copy of pkglist so comm doesn't keep going because it's
    170 	# appending to an input file
    171 
    172 	cp $pkglist $pkgcopy
    173 	comm -13 $pkgcopy $allpkglist >> $pkglist
    174 
    175 	#
    176 	# Step 2: build a list of all of the classes in all the packages
    177 	# (except for the "none" class).  The order of each package's class
    178 	# list must match the order in the pkginfo.tmpl file.
    179 	#
    180 
    181 	if [ "$ACR_DEBUG" = "yes" ] ; then
    182 		print "Step 2: Build list of all classes in all packages."
    183 	fi
    184 
    185 	cat $pkglist | while read dir; do
    186 	    	parse_pkginfo $isa $dir 
    187 	done > $allclasslist_t
    188 
    189 	cat $allclasslist_t | while read pkg pkginst p_isa mach class; do
    190 		if [ -s common_files/i.$class -o \
    191 		     -s common_files/i.${class}_$isa ] ; then
    192 			print $pkg $pkginst $p_isa $mach $class c
    193 		else
    194 			echo ${non_on_classes} |
    195 				    /usr/bin/grep -w i.${class} > /dev/null
    196 			if [ $? -eq 0 ] ; then
    197 				print $pkg $pkginst $p_isa $mach $class n
    198 			else
    199 				print $pkg $pkginst $p_isa $mach $class s
    200 			fi		
    201 		fi
    202 	done > $allclasslist
    203 
    204 	#
    205 	# Step 3: For each package with at least one installation class,
    206 	# scan the package's prototype files and look for files that are
    207 	# editable or volatile and which have class-action scripts.  Make
    208 	# a list of those files, with their packages and script names.
    209 	#
    210 
    211 	if [ "$ACR_DEBUG" = "yes" ] ; then
    212 		print "Step 3: Build list of editable files."
    213 	fi
    214 
    215 	nawk '$3 == "'$isa'" {print $2}' $allclasslist | sort -u |
    216 	while read pkginst; do
    217 		if [ -s $pkginst/prototype_com ] ; then
    218 			protos="$pkginst/prototype_com $pkginst/prototype_$isa"
    219 		else
    220 			protos="$pkginst/prototype_$isa"
    221 		fi
    222 		
    223 		cat $protos | nawk -v pkginst=$pkginst \
    224 		    '(/^[ev] /) && ($2 != "none") && ($2 != "build") {
    225 				printf("%s %s %s\n", $3, pkginst, $2);}
    226 		    (/^[ev] /) && ($2 == "build") {
    227 				split($3,buildtgt,"=");
    228 				printf("%s %s %s\n", buildtgt[1], pkginst,$2);}'
    229 	done > $editablefilelist
    230 
    231 	#
    232 	# Step 4: Use the information in $allclasslist and
    233 	# $editablefilelist to generate the list of files
    234 	# to be copied to the bfu archive and the
    235 	# editable-file/class-action-script database to be installed
    236 	# in the archive.
    237 	#
    238 
    239 	if [ "$ACR_DEBUG" = "yes" ] ; then
    240 		print "Step 4: Merge class list and editable files list"
    241 	fi
    242 
    243 	cat $allclasslist | while read pkg pkgdir classisa mach class iscommon
    244 	do
    245 		nawk -v pkgdir=$pkgdir -v class=$class -v pkg=$pkg \
    246 		    -v isa=$classisa -v mach=$mach -v iscommon=$iscommon \
    247 		    -v uniquifier=$un '
    248 			{ if ($2 == pkgdir && $3 == class)
    249 				printf("%s i.%s %s %s %s %s %s %s\n", $1,
    250 					class, pkg, $2, isa, mach, iscommon,
    251 					uniquifier);
    252 			}' $editablefilelist
    253 	done > $db
    254 
    255 	for badclass in $bfu_incompatible_classes; do
    256 		nawk -v badclass=$badclass -v replclass="upgrade_default" '{
    257 			if ($2 == badclass)
    258 				class = replclass;
    259 			else
    260 				class = $2;
    261 			printf("%s %s %s %s %s %s %s %s\n", 
    262 					$1, class, $3, $4, $5, $6, $7, $8)
    263 		    }' $db > $tmpdb
    264 		mv $tmpdb $db
    265 	done
    266 
    267 	#
    268 	# Step 5 - Copy the editable-file/class-action-script database file
    269 	#   to the class scripts to the archive directory.
    270 	#
    271 
    272 	if [ "$ACR_DEBUG" = "yes" ] ; then
    273 		print "Step 5: Create bfu conflict resolution directory"
    274 	fi
    275 
    276 	mkdir -p $tmpdir/conflict_resolution/$un
    277 
    278 	nawk '{ print $3 }' $editablefilelist | sort -u | while read class; do
    279 		if [ -s common_files/i.$class ] ; then
    280 			cp common_files/i.$class \
    281 			    $tmpdir/conflict_resolution/$un
    282 		elif [ -s common_files/i.${class}_$isa ] ; then
    283 			cp common_files/i.${class}_$isa \
    284 			    $tmpdir/conflict_resolution/$un/i.$class
    285 		else
    286 			echo ${non_on_classes} |
    287 			    /usr/bin/grep -w i.${class} > /dev/null
    288 			if [ $? -eq 0 ] ; then
    289 			    #
    290 			    # process_non_on_classes is called only once
    291 			    # per non_on_class due to sort -u above. 
    292 			    #
    293 			    process_non_on_classes ${class} \
    294 				 ${editablefilelist} \
    295 				 $tmpdir/conflict_resolution/$un
    296 			    continue;
    297 			else
    298 			    nawk -v class=$class '$3 == class { print $2 }' \
    299 				$editablefilelist | sort -u > $classpk
    300 			    if [ $(wc -l < $classpk) -ne 1 ] ; then
    301 				    cat >&2 <<EOF
    302 mkacr: The class script i.$class cannot be found in the pkgdefs common files
    303 directory, and there is more than one package that uses it.
    304 EOF
    305 				    exit 1
    306 			    fi
    307 			fi
    308 			pkgdir=$(cat $classpk)
    309 			if [ -s $pkgdir/i.$class ] ; then
    310 				mkdir -p $tmpdir/conflict_resolution/$un/$pkgdir
    311 				cp $pkgdir/i.$class \
    312 				    $tmpdir/conflict_resolution/$un/$pkgdir
    313 			elif [ -s $pkgdir/i.${class}_$isa ] ; then
    314 				mkdir -p $tmpdir/conflict_resolution/$un/$pkgdir
    315 				cp $pkgdir/i.${class}_$isa \
    316 				    $tmpdir/conflict_resolution/$un/$pkgdir/i.$class
    317 			else
    318 				print -u2 "mkacr: Can't find class script i.$class"
    319 				exit 1
    320 			fi
    321 		fi
    322 	done
    323 
    324 	cat $db >> $tmpdir/conflict_resolution/editable_file_db
    325 
    326 	if [ "$ACR_DEBUG" = "yes" ] ; then
    327 		mkdir $tmpdir/$un
    328 		mv $tmpdir/ps.* $tmpdir/$un
    329 	else
    330 		rm -fr $tmpdir/ps.*
    331 	fi
    332 }
    333 
    334 #
    335 # Execution starts here
    336 #
    337 
    338 export LC_ALL=C
    339 ACR_DEBUG=${ACR_DEBUG-no}
    340 
    341 USAGE="Usage: $0 <workspace> <instruction-set-architecture> <archive-dir>"
    342 
    343 if [ $# -ne 3 ] ; then
    344 	print -u2 $USAGE
    345 	exit 1
    346 fi
    347 
    348 workspace=$1
    349 isa=$2
    350 if [ -d $workspace/pkgdefs ] ; then
    351 	:
    352 elif [ -d $workspace/usr/src/pkgdefs ] ; then
    353 	workspace=$workspace/usr/src
    354 else 
    355 	print -u2 $USAGE
    356 	exit 1
    357 fi
    358 
    359 if [ ! -d $3 ] ; then
    360 	print -u2 $USAGE
    361 	exit 1
    362 fi
    363 archivedir=$(cd $3; pwd)
    364 
    365 if [ "$isa" != "sparc" -a "$isa" != "i386" ] ; then
    366 	print -u2 "$0: Instruction set architecture must be \"sparc\" or \"i386\""
    367 	exit 1
    368 fi
    369 
    370 #
    371 # temporary file scorecard, in order of appearance:
    372 # (Temporary files that begin with "ps." are pass-specific.  mkacr
    373 # generates its database in multiple passes:  one for each pkgdef
    374 # directory in the ON source base.  Currently there are 2:
    375 # usr/src/pkgdefs and usr/src/realmode/pkgdefs.  The temp files
    376 # that begin with "ps." are deleted at the end of each pass.)
    377 #
    378 # ps.pkglist	package names, starting with core pkgs
    379 #
    380 # ps.allpkglist 	pass 1 additional package list
    381 #
    382 # ps.pkgcopy	pass 1 temporary copy of core package names 
    383 #
    384 # ps.allclasslist	list of all classes
    385 #
    386 # ps.allclasslist_t	preliminary version of ps.allclasslist
    387 #
    388 # ps.editablefilelist	list of editable files.
    389 #
    390 # ps.db, tmpdb	temporary files used in construction of editable_file_db
    391 #
    392 # ps.cpioerr 	stderr from cpio.
    393 #
    394 
    395 tmpdir=$(mktemp -t -d mkacr.XXXXXX)
    396 
    397 if [ -z "$tmpdir" ] ; then
    398         print -u2 "mktemp failed to produce output; aborting"
    399         exit 1
    400 fi
    401 
    402 if [ ! -d "$tmpdir" ] ; then
    403     	print -u2 "$0: Couldn't create temporary directory $tmpdir"
    404 	exit 1
    405 fi
    406 
    407 if [ "$ACR_DEBUG" = "yes" ] ; then
    408     	print "Temporary files will be left in $tmpdir"
    409 else
    410 	trap 'rm -rf $tmpdir' 0
    411 fi
    412 
    413 cpioerr=$tmpdir/ps.cpioerr
    414 pkglist=$tmpdir/ps.pkglist
    415 allpkglist=$tmpdir/ps.allpkglist
    416 pkgcopy=$tmpdir/ps.pkgcopy
    417 allclasslist=$tmpdir/ps.allclasslist
    418 allclasslist_t=$tmpdir/ps.allclasslist_t
    419 editablefilelist=$tmpdir/ps.editablefilelist
    420 db=$tmpdir/ps.db
    421 tmpdb=$tmpdir/ps.tmpdb
    422 classpk=$tmpdir/ps.classpk
    423 
    424 #
    425 # set up the list of corepkgs and bfs-incompatible classes for the
    426 # processing of the usr/src/pkgdefs directory
    427 #
    428 
    429 corepkgs="
    430 	SUNWcar.*
    431 	SUNWcakr.*
    432 	SUNWckr
    433 	SUNWcsd
    434 	SUNWcsr
    435 	SUNWcsu
    436 	SUNWcsl
    437 	SUNWcslr
    438 	SUNWkvm.*
    439 "
    440 bfu_incompatible_classes="
    441 	i.initd
    442 "
    443 non_on_classes="
    444         i.CONFIG.prsv
    445         i.CompCpio
    446         i.awk
    447         i.build 
    448         i.ipsecalgs
    449         i.kcfconf
    450         i.kmfconf 
    451         i.pkcs11conf
    452         i.sed
    453 "
    454 
    455 process_pkgdefs_directory $workspace/pkgdefs std
    456 
    457 if [[ -d $workspace/../closed/pkgdefs && "$CLOSED_IS_PRESENT" != no ]]; then
    458 	process_pkgdefs_directory $workspace/../closed/pkgdefs std-closed
    459 fi
    460 
    461 #
    462 # set up the list of corepkgs and bfs-incompatible classes for the
    463 # processing of the usr/src/realmode/pkgdefs directory
    464 #
    465 
    466 corepkgs="SUNWrmodr"
    467 bfu_incompatible_classes=""
    468 
    469 if [ -d $workspace/realmode/pkgdefs ] ; then
    470     	process_pkgdefs_directory $workspace/realmode/pkgdefs realmode
    471 fi
    472 
    473 if [ "$ACR_DEBUG" = "yes" ] ; then
    474 	print "Final processing: Create bfu conflict resolution archive"
    475 fi
    476 
    477 print "Creating conflict resolution archive: \c";
    478 
    479 (cd $tmpdir
    480 find conflict_resolution -print | cpio -ocB 2>$cpioerr |
    481     gzip -c > $archivedir/conflict_resolution.gz ) || exit 1
    482 
    483 awk '/^[0-9]* blocks$/ { blocks=1; print $0; next }
    484 { print $0 > "/dev/stderr" }
    485 END {
    486 	if (!blocks) {
    487 		# Terminate the "print \c" line above.
    488 		print
    489 		print "No cpio block count" > "/dev/stderr"
    490 	}
    491 }' <$cpioerr
    492 
    493 exit 0
    494