OpenSolaris_b135/tools/scripts/mkbfu.sh

#!/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
# 
# ident	"%Z%%M%	%I%	%E% SMI"
#
# Make archives suitable for bfu

#
# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
# under certain circumstances, which can really screw things up; unset it.
#
unset CDPATH

fail() {
	echo $* >&2
	exit 1
}

# Place a limit on the number of background jobs we can produce at one
# time.  The mechanism used is crude; we wait for all jobs to complete
# before continuing.  It'd be nice if ksh actually had such a native
# facility.
bgcheck() {
	bgctr=$((bgctr + 1))
	if [ $bgctr -ge $bgmax ]; then
	        wait
	        bgctr=0
		for outf in $CPIODIR/*.out; do
			errf=${outf%.out}.err
			if [ -s $errf ]; then
				echo "Failed to create\c" >&2
				cat $outf $errf >&2
			else
				echo "Creating\c"
				cat $outf
			fi
			rm -f $outf $errf
		done
	fi
}
bgctr=0
bgmax=${DMAKE_MAX_JOBS:-1}

# Produce a named archive.  Archives always have two names -- the
# first part is an identifier for the archive, the second part is
# 'root' or 'usr' or 'lib' or 'sbin' or 'kernel'.
create_archive() {
	arc="$CPIODIR/$1.$2"
	outf="${arc}.out"
	cpioerr="${arc}.cpioerr"
	echo " $1 $2 archive:\t\c" >$outf
	eval $cpio >$arc$ext
	awk '/^[0-9]* blocks$/ { blocks=1; print $0; next }
	{ print $0 > "/dev/stderr" }
	END {
		if (!blocks) {
			# Terminate the "echo \c" line above.
			print
			print "No cpio block count" > "/dev/stderr"
		}
	}' <$cpioerr >>$outf
	rm -f $cpioerr
}

ext=
filter=
compressor=
usage="Usage: $0 [-f filter] [-z] proto-dir archive-dir"
prove_you_mean_it="\n\
\n\
Unless invoked directly by makebfu, this script will produce archives with\n\
incorrect permissions which will brickify a system if installed.  You most\n\
likely wanted to run makebfu instead; if not, set\n\n\
\t\tI_REALLY_WANT_TO_RUN_MKBFU=YES\n\n\
in your environment and try again.\n\n\n"

[ -n "$I_REALLY_WANT_TO_RUN_MKBFU" ] || fail "$prove_you_mean_it"
[ "$I_REALLY_WANT_TO_RUN_MKBFU" = "YES" ] || fail "$prove_you_mean_it"

while getopts :f:z opt
do
	case "$opt" in
	    f)	filter="$OPTARG";;
	    z)	compressor="gzip -c"
		ext=".gz";;
	    *)	fail "$usage";;
	esac
done
shift $(($OPTIND - 1))

[ $# -eq 2 ] || fail "$usage"

# The extra subshell allows us to wait for cpio to exit completely (rather
# that merely closing stdout) before attempting to examine the stderr output
# file.  Otherwise, we'll race with cpio's completion.
cpio='( ( cpio -ocB 2>$cpioerr ); true )'
if [ "$filter" ]; then
	cpio="$cpio | $filter"
fi
if [ "$compressor" ]; then
	cpio="$cpio | $compressor"
fi

PROTO=$1
CPIODIR=$2

CLASS=`uname -m`

[ -d $PROTO ] || fail "Proto directory $PROTO does not exist."

cd $PROTO

rm -rf $CPIODIR
mkdir -p $CPIODIR

# Create "new style" archives if Zones are present, with lib, sbin and kernel
# in their own archives; otherwise create "old style" archives with everything
# in generic.root
if [ -d etc/zones ]; then
	( {	FILELIST=`ls . | grep -v usr | grep -v platform |
			grep -v kernel | grep -v boot | grep -v sbin |
			grep -v lib | sed -e "s@^@./@"`
		find $FILELIST -depth -print
		echo "./usr"
		echo "./platform"
		echo "./lib"
		echo "./sbin"
		echo "./kernel"
	} | create_archive generic root ) 2>$CPIODIR/generic.root.err &
	bgcheck

	( {	FILELIST=`ls ./lib | sed -e "s@^@./lib/@"`
		find $FILELIST -depth -print
	} | create_archive generic lib ) 2>$CPIODIR/generic.lib.err &
	bgcheck

	( {	FILELIST=`ls ./sbin | sed -e "s@^@./sbin/@"`
		find $FILELIST -depth -print
	} | create_archive generic sbin ) 2>$CPIODIR/generic.sbin.err &
	bgcheck

	( {	FILELIST=`ls ./kernel | sed -e "s@^@./kernel/@"`
		find $FILELIST -depth -print
	} | create_archive generic kernel ) 2>$CPIODIR/generic.kernel.err &
	bgcheck
else
	( {     FILELIST=`ls . | grep -v usr | grep -v platform |
			grep -v boot | sed -e "s@^@./@"`
		find $FILELIST -depth -print
		echo "./usr"
		echo "./platform"
	} | create_archive generic root ) 2>$CPIODIR/generic.root.err &
	bgcheck
fi

( {	FILELIST=`ls ./usr | grep -v platform | sed -e "s@^@./usr/@"`
	find $FILELIST -depth -print | egrep -v -e "./usr/share/src"
	echo "./usr/platform"
} | create_archive generic usr ) 2>$CPIODIR/generic.usr.err &
bgcheck

for i in `cd platform; find * -prune \( -type d -o -type l \) -print`
do
	( {	FILELIST=`ls -1 ./platform | grep "$i$" |
		    sed -e "s@^@./platform/@"`
		find $FILELIST -depth -print
	} | create_archive $i root ) 2>$CPIODIR/${i}.root.err &
	bgcheck

	( {	FILELIST=`ls -1 ./usr/platform | grep "$i$" |
		    sed -e "s@^@./usr/platform/@"`
		find $FILELIST -depth -print
	} | create_archive $i usr ) 2>$CPIODIR/${i}.usr.err &
	bgcheck
done

if [ -d boot ]; then
	if [ "$CLASS" = "i86pc" ]; then
		ARCHIVECLASS="$CLASS"
	else
		ARCHIVECLASS="generic"
	fi
	( find boot -depth -print | create_archive $ARCHIVECLASS boot ) \
	    2>$CPIODIR/$ARCHIVECLASS.boot.err &
	bgcheck
fi

# If there are any background jobs left, then gather them now.
if [ $bgctr -gt 0 ]; then
	bgmax=0
	bgcheck
fi