xref: /titanic_50/usr/src/tools/scripts/Install.sh (revision abc79d9dd51e98eafb6fc25b4a0b4f66bef40b00)
1#!/bin/ksh
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 (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24#
25# Author:  Jeff Bonwick
26#
27#	Please report any bugs to bonwick@eng.
28#
29# How Install works:
30#
31#	Install performs the following steps:
32#
33#	1. Get the list of modules, configuration files, and links
34#	   that are desired.
35#
36#	2. Create the requested subset of /kernel in Install's temp space
37#	   (/tmp/Install.username by default.)
38#
39#	3. Create a tar file (/tmp/Install.username/Install.tar) based on (3).
40#
41#	4. If -n was specified, exit.  If a target was specified using -T,
42#	   rcp the tarfile to the target and exit.  If a target was specified
43#	   using -t, rsh to the target machine and untar the tarfile in the
44#	   target directory.
45#
46# If any of these steps fail, Install will give you an error message and,
47# in most cases, suggest corrective measures.  Then, you can recover the
48# install with "Install -R". (This is not required; it's just faster than
49# starting from scratch.)
50#
51# One final comment:  Unfortunately, tar and I disagree on what
52# constitutes a fatal error.  (tar -x will exit 0 even if it can't write
53# anything in the current directory.)  Thus, I am reduced to grepping stderr
54# for (what I consider) fatal and nonfatal error messages.  If you run into
55# a situation where this doesn't behave the way you think it should (either
56# an "Install failed" message after a successful install, or an "Install
57# complete" message after it bombs), please let me know.
58
59#
60# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
61# under certain circumstances, which can really screw things up; unset it.
62#
63unset CDPATH
64
65INSTALL=`basename $0`
66DOT=`pwd`
67
68TRAILER="Install.$LOGNAME"
69INSTALL_STATE=${INSTALL_STATE-$HOME/.Install.state}
70export INSTALL_STATE
71INSTALL_DIR=${INSTALL_DIR-/tmp/$TRAILER}
72if [ "`basename $INSTALL_DIR`" != "$TRAILER" ]; then
73	INSTALL_DIR="$INSTALL_DIR/$TRAILER"
74fi
75export INSTALL_DIR
76INSTALL_LIB=${INSTALL_LIB-$HOME/LibInstall}
77export INSTALL_LIB
78INSTALL_RC=${INSTALL_RC-$HOME/.Installrc}
79export INSTALL_RC
80INSTALL_CP=${INSTALL_CP-"cp -p"}
81export INSTALL_CP
82INSTALL_RCP=${INSTALL_RCP-"rcp -p"}
83export INSTALL_RCP
84
85STATE=0
86
87DEFAULT_OPTIONS="-naq"
88GLOM=no
89GLOMNAME=kernel
90IMPL="default"
91WANT32="yes"
92WANT64="yes"
93
94modlist=/tmp/modlist$$
95# dummy directory for make state files.
96modstatedir=/tmp/modstate$$
97
98trap 'fail "User Interrupt" "You can resume by typing \"$INSTALL -R\""' 1 2 3 15
99
100function usage {
101	echo ""
102	echo $1
103	echo '
104Usage: Install	[ -w workspace ]
105		[ -s srcdir (default: usr/src/uts) ]
106		[ -k karch (e.g. sun4u; required if not deducible from pwd) ]
107		[ -t target (extract tar file on target, e.g. user@machine:/) ]
108		[ -T target (copy tar file to target, e.g. user@machine:/tmp) ]
109		[ -n (no target, just create tar file in /tmp (default)) ]
110		[ -u (install unix only) ]
111		[ -m (install modules only) ]
112		[ -a (install everything, i.e. unix + modules (default)) ]
113		[ -v (verbose output) ]
114		[ -V (REALLY verbose output) ]
115		[ -q (quiet (default)) ]
116		[ -c (clean up (remove temp files) when done (default) ]
117		[ -p (preserve temp files -- useful for debugging) ]
118		[ -L (library create: put tarfile in $INSTALL_LIB/env.karch) ]
119		[ -l lib (library extract: use $INSTALL_LIB/lib as source) ]
120		[ -D libdir (default: $HOME/LibInstall) ]
121		[ -d tempdir (Install work area (default: /tmp)) ]
122		[ -G glomname (put all files under platform/karch/glomname) ]
123		[ -i impl (e.g. sunfire; recommended with -G) ]
124		[ -x (update /etc/name_to_major et al) ]
125		[ -X (do not update /etc/name_to_major et al (default)) ]
126		[ -P (update /etc/path_to_inst -- generally not advisable) ]
127		[ -h (help -- prints this message) ]
128		[ -R (recover a previous Install) ]
129		[ -o objdir (object directory - either obj or debug (the default)) ]
130		[ -K (do not copy kmdb) ]
131		[ -3 32-bit modules only ]
132		[ -6 64-bit modules only ]
133		[ list of modules to install ]
134
135For full details:
136
137	man -M /ws/on297-gate/public/docs Install
138'
139	exit 1
140}
141
142#
143# Save the current state of Install
144#
145
146function save_state {
147	rm -f $INSTALL_STATE
148	(echo "# State of previous Install
149TARGET=$TARGET
150ENV_PATH=$ENV_PATH
151ENV_NAME=$ENV_NAME
152KARCH=$KARCH
153UTS=$UTS
154INSTALL_DIR=$INSTALL_DIR
155INSTALL_LIB=$INSTALL_LIB
156IMODE=$IMODE
157LIBCREATE=$LIBCREATE
158LIBSRC=$LIBSRC
159VERBOSE=$VERBOSE
160CLEANUP=$CLEANUP
161GLOM=$GLOM
162GLOMNAME=$GLOMNAME
163KMDB=$KMDB
164files='$files'
165STATE=$STATE" >$INSTALL_STATE) || verbose "Warning: cannot save state"
166}
167
168#
169# Restore the previous state of Install
170#
171
172function restore_state {
173	test -s $INSTALL_STATE || fail "Can't find $INSTALL_STATE"
174	eval "`cat $INSTALL_STATE`"
175}
176
177#
178# Install failed -- print error messages and exit 2
179#
180
181function fail {
182	save_state
183	#
184	# We might have gotten here via a trap.  So wait for any
185	# children (especially "make modlist") to exit before giving
186	# the error message or cleaning up.
187	#
188	wait
189	while [ $# -gt 0 ]
190	do
191		echo $1
192		shift
193	done
194	rm -rf $modstatedir
195	rm -f $modlist
196	echo "Install failed"
197	exit 2
198}
199
200#
201# Echo a string in verbose mode only
202#
203
204function verbose {
205	test "$VERBOSE" != "q" && echo $1
206}
207
208#
209# hack for tmpfs bug -- remove files gradually
210#
211
212function remove_dir {
213	test -d $1 || return
214	local_dot=`pwd`
215	cd $1
216	touch foo
217	rm -f `find . -type f -print`
218	cd $local_dot
219	rm -rf $1
220}
221
222#
223# Create a directory if it doesn't already exist.
224# mkdir will provide an error message, so don't provide an additional
225# message.
226#
227
228function tstmkdir {
229	[ -d $1 ] || mkdir -p $1 || fail
230}
231
232#
233# Patch up target directories for glommed kernel.
234# usage: fixglom listfile glomname
235#
236
237function fixglom {
238	nawk \
239	    -v glomname=$2 \
240	    -v karch=$KARCH '
241	$1 == "MOD" || $1 == "SYMLINK" {
242		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $4)
243		sub(/^kernel/, "platform/" karch "/" glomname, $4)
244		sub(/^usr.kernel/, "platform/" karch "/" glomname, $4)
245		print
246	}
247	$1 == "LINK" {
248		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3)
249		sub(/^kernel/, "platform/" karch "/" glomname, $3)
250		sub(/^usr.kernel/, "platform/" karch "/" glomname, $3)
251		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $5)
252		sub(/^kernel/, "platform/" karch "/" glomname, $5)
253		sub(/^usr.kernel/, "platform/" karch "/" glomname, $5)
254		print
255	}
256	$1 == "CONF" {
257		sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3)
258		sub(/^kernel/, "platform/" karch "/" glomname, $3)
259		sub(/^usr.kernel/, "platform/" karch "/" glomname, $3)
260		print
261	}
262	' $1 > $1.new
263	mv $1.new $1
264}
265
266#
267# Filter out implementation-specific modules, unless that
268# implementation was requested by the user.
269# usage: filtimpl listfile implname
270#
271
272function filtimpl {
273	nawk \
274	    -v impl=$2 '
275	$1 == "MOD" || $1 == "SYMLINK" {
276		if ($6 == "all" || $6 == impl)
277			print
278	}
279	$1 == "CONF" {
280		if ($5 == "all" || $5 == impl)
281			print
282	}
283	$1 == "LINK" {
284		if ($7 == "all" || $7 == impl)
285			print
286	}
287	' $1 > $1.new
288	mv $1.new $1
289}
290
291#
292# Filter the module list to match the user's request.
293# Usage: filtmod listfile modules
294#
295function filtmod {
296	nawk -v reqstring="$2" '
297	function modmatch(modname) {
298		if (reqstring == "All") {
299			return (1)
300		} else if (reqstring == "Modules") {
301			if (modname != "unix" && modname != "genunix")
302				return (1)
303		} else {
304			if (modname in reqmods)
305				return (1)
306		}
307		return (0)
308	}
309	BEGIN {
310		#
311		# The split call creates indexes 1, 2, 3, ...  We want
312		# the module names as indexes.
313		#
314		split(reqstring, tmpmods)
315		for (i in tmpmods)
316			reqmods[tmpmods[i]] = 1
317	}
318	$1 == "MOD" {
319		if (modmatch($3))
320			print
321	}
322	$1 == "CONF" {
323		if (modmatch($6))
324			print
325	}
326	$1 == "SYMLINK" {
327		if (modmatch($7))
328			print
329	}
330	$1 == "LINK" {
331		if (modmatch($4))
332			print
333	}
334	' $1 > $1.new
335	mv $1.new $1
336}
337
338#
339# Unpack the crypto tarball into the given tree, then massage the
340# tree so that the binaries are all in objNN or debugNN directories.
341#
342function unpack_crypto {
343	typeset tarfile=$1
344	typeset ctop=$2
345	[ -d "$ctop" ] || fail "Can't create tree for crypto modules."
346
347	[ "$VERBOSE" = "V" ] && echo "unpacking crypto tarball into $ctop..."
348	bzcat "$tarfile" | (cd "$ctop"; tar xf -)
349
350	typeset root="$ctop/proto/root_$MACH"
351	[ $OBJD = obj ] && root="$ctop/proto/root_$MACH-nd"
352	[ -d "$root" ] || fail "Can't unpack crypto tarball."
353
354	(cd "$root"; for d in platform kernel usr/kernel; do
355		[ ! -d $d ] && continue
356		find $d -type f -print
357	done) | while read file; do
358		typeset dir=$(dirname "$file")
359		typeset base=$(basename "$file")
360		typeset type=$(basename "$dir")
361		if [ "$type" = amd64 ]; then
362			newdir="$dir/${OBJD}64"
363		elif [ "$type" = sparcv9 ]; then
364			newdir="$dir/${OBJD}64"
365		else
366			newdir="$dir/${OBJD}32"
367		fi
368		mkdir -p "$root/$newdir"
369		[ "$VERBOSE" = "V" ] && echo "mv $file $newdir"
370		mv "$root/$file" "$root/$newdir"
371	done
372}
373
374#
375# usage: fixcrypto listfile ctop
376# Massage entries in listfile for crypto modules, so that they point
377# into ctop.
378#
379function fixcrypto {
380	typeset listfile=$1
381	typeset ctop=$2
382
383	typeset ccontents=/tmp/crypto-toc$$
384	find "$ctop" -type f -print > $ccontents
385	typeset root=root_$MACH
386	[ "$OBJD" = obj ] && root=root_$MACH-nd
387
388	grep -v ^MOD $listfile > $listfile.no-mod
389	grep ^MOD $listfile | while read tag srcdir module targdir size impl; do
390		#
391		# We don't just grep for ${OBJD}$size/$module because
392		# there can be generic and platform-dependent versions
393		# of a module.
394		#
395		newsrcfile=$(grep -w $root/$targdir/${OBJD}$size/$module $ccontents)
396		if [ -n "$newsrcfile" ]; then
397			# srcdir doesn't include final objNN or debugNN
398			echo $tag $module $targdir $size $impl \
399			    $(dirname $(dirname "$newsrcfile"))
400		else
401			echo $tag $module $targdir $size $impl $srcdir
402		fi
403	done > $listfile.mod
404	cat $listfile.mod $listfile.no-mod > $listfile
405
406	rm -f $listfile.mod
407	rm -f $listfile.no-mod
408	rm -f $ccontents
409}
410
411#
412# Copy a module, or create a link, as needed.
413#
414
415function copymod {
416	case $1 in
417	MOD)
418		targdir=$INSTALL_FILES/$4
419		tstmkdir $targdir
420		target=$targdir/$3
421		verbose "$INSTALL_CP $2/${OBJD}$5/$3 $target"
422		$INSTALL_CP $2/${OBJD}$5/$3 $target || \
423		    fail "can't create $target"
424		;;
425	SYMLINK)
426		targdir=$INSTALL_FILES/$4
427		tstmkdir $targdir
428		target=$targdir/$5
429		rm -f $target
430		verbose "ln -s $3 $target"
431		ln -s $3 $target || fail "can't create $target"
432		;;
433	LINK)
434		targdir=$INSTALL_FILES/$5
435		tstmkdir $targdir
436		target=$targdir/$6
437		rm -f $target
438		verbose "ln $INSTALL_FILES/$3/$4 $target"
439		ln $INSTALL_FILES/$3/$4 $target || fail "can't create $target"
440		;;
441	CONF)
442		target=$INSTALL_FILES/$3
443		tstmkdir `dirname $target`
444		conffile=`basename $3`
445		verbose "$INSTALL_CP $4/$conffile $target"
446		$INSTALL_CP $4/$conffile $target
447		;;
448	*)
449		fail "unrecognized modlist entry: $*"
450		;;
451	esac
452}
453
454# Sanity-check the given module list.
455function check_modlist {
456	nawk '
457	BEGIN {
458		nfields["MOD"] = 6
459		nfields["CONF"] = 6
460		nfields["LINK"] = 7
461		nfields["SYMLINK"] = 7
462	}
463	{
464		# This also catches unknown tags.
465		if (nfields[$1] != NF) {
466			print "error: invalid modlist record:"
467			print $0
468			print "expected", nfields[$1], "fields, found", NF
469			status=1
470		}
471	}
472	END {
473		exit status
474	}
475	' $1 || fail "Errors in kernel module list"
476}
477
478#
479# Copy kernel modules to $INSTALL_DIR
480#
481
482function copy_kernel {
483
484	case $KARCH in
485		sun4*)		ISA=sparc;	MACH=sparc	;;
486		i86*)		ISA=intel;	MACH=i386	;;
487		*)		fail "${KARCH}: invalid kernel architecture";;
488	esac
489	export MACH
490
491	if [ "$GLOM" = "no" ]; then
492		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH"
493	else
494		verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH, impl = $IMPL"
495	fi
496
497	test -d $KARCH || fail "${KARCH}: invalid kernel architecture"
498	test -d $ISA || fail "${ISA}: invalid instruction set architecture"
499
500	tstmkdir $INSTALL_FILES
501	rm -rf $modstatedir
502	tstmkdir $modstatedir
503	export MODSTATE=$modstatedir/state
504
505	#
506	# Figure out which "make" to use.  dmake is faster than serial
507	# make, but dmake 7.3 has a bug that causes it to lose log
508	# output, which means the modlist might be incomplete.
509	#
510	make=dmake
511	dmvers=`$make -version`
512	if [ $? -ne 0 ]; then
513		make=/usr/ccs/bin/make
514	elif [[ $dmvers = *Distributed?Make?7.3* ]]; then
515		unset make
516		searchpath="/ws/onnv-tools/SUNWspro/SOS10/bin
517			/opt/SUNWspro/SOS10/bin
518			/opt/SUNWspro/bin"
519		for dmpath in $searchpath; do
520			verbose "Trying $dmpath/dmake"
521			if [ -x $dmpath/dmake ]; then
522				dmvers=`$dmpath/dmake -version`
523				if [[ $dmvers != *Distributed?Make?7.3* ]]; then
524					make="$dmpath/dmake"
525					break;
526				fi
527			fi
528		done
529		if [ -z $make ]; then
530			make=/usr/ccs/bin/make
531			echo "Warning: dmake 7.3 doesn't work with Install;" \
532				"using $make"
533		fi
534	fi
535
536	#
537	# Get a list of all modules, configuration files, and links
538	# that we might want to install.
539	#
540	verbose "Building module list..."
541	(cd $KARCH; MAKEFLAGS=e $make -K $MODSTATE modlist.karch) | \
542	    egrep "^MOD|^CONF|^LINK|^SYMLINK" > $modlist
543	[ "$VERBOSE" = "V" ] && cat $modlist
544	check_modlist $modlist
545	if [ -n "$ON_CRYPTO_BINS" ]; then
546		cryptotar="$ON_CRYPTO_BINS"
547		if [ "$OBJD" = obj ]; then
548			isa=$(uname -p)
549			cryptotar=$(echo "$ON_CRYPTO_BINS" |
550			    sed -e s/.$isa.tar.bz2/-nd.$isa.tar.bz2/)
551		fi
552		[ -f "$cryptotar" ] || fail "crypto ($cryptotar) doesn't exist"
553		cryptotree=$(mktemp -d /tmp/crypto.XXXXXX)
554		[ -n "$cryptotree" ] || fail "can't create tree for crypto"
555		unpack_crypto "$cryptotar" "$cryptotree"
556		#
557		# fixcrypto must come before fixglom, because
558		# fixcrypto uses the unglommed path to find things in
559		# the unpacked crypto.
560		#
561		fixcrypto $modlist "$cryptotree"
562	fi
563	if [ "$GLOM" = "yes" ]; then
564		fixglom $modlist $GLOMNAME
565		filtimpl $modlist $IMPL
566	fi
567	if [[ -n "$files" && "$files" != All ]]; then
568		filtmod $modlist "$files"
569	fi
570
571	#
572	# Copy modules and create links.  For architectures with both
573	# 32- and 64-bit modules, we'll likely have duplicate
574	# configuration files, so do those after filtering out the
575	# duplicates.
576	#
577	verbose "Copying files to ${INSTALL_FILES}..."
578
579	#
580	# The IFS is reset to the newline character so we can buffer the
581	# output of grep without piping it directly to copymod, otherwise
582	# if fail() is called, then it will deadlock in fail()'s wait call
583	#
584	OIFS="$IFS"
585	IFS="
586	"
587	set -- `grep -v "^CONF" $modlist`;
588	IFS="$OIFS"
589	for onemod in "$@"; do
590		copymod $onemod
591	done
592
593	OIFS="$IFS"
594	IFS="
595	"
596	set -- `grep "^CONF" $modlist | sort | uniq`;
597	IFS="$OIFS"
598	for onemod in "$@"; do
599		copymod $onemod
600	done
601
602	#
603	# Add the glommed kernel name to the root archive
604	#
605	if [[ $GLOM == "yes" ]];
606	then
607		filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk"
608		mkdir -p `dirname $filelist`
609		echo "platform/$KARCH/$GLOMNAME" >$filelist
610	fi
611
612	STATE=1 # all kernel modules copied correctly
613	save_state
614}
615
616function kmdb_copy {
617	typeset src="$1"
618	typeset destdir="$2"
619
620	if [[ ! -d $dest ]] ; then
621		[[ "$VERBOSE" != "q" ]] && echo "mkdir -p $destdir"
622
623		mkdir -p $destdir || fail "failed to create $destdir"
624	fi
625
626	[[ "$VERBOSE" != "q" ]] && echo "cp $src $destdir"
627
628	cp $src $destdir || fail "failed to copy $src to $destdir"
629}
630
631function kmdb_copy_machkmods {
632	typeset modbase="$1"
633	typeset destdir="$2"
634	typeset dir=
635	typeset kmod=
636
637	[[ ! -d $modbase ]] && return
638
639	for dir in $(find $modbase -name kmod) ; do
640		set -- $(echo $dir |tr '/' ' ')
641
642		[[ $# -lt 2 ]] && fail "invalid mach kmod dir $dir"
643
644		shift $(($# - 2))
645		kmod=$1
646
647		[[ ! -f $dir/$kmod ]] && continue
648
649		kmdb_copy $dir/$kmod $destdir
650	done
651}
652
653function kmdb_copy_karchkmods {
654	typeset modbase="$1"
655	typeset destdir="$2"
656	typeset bitdir="$3"
657	typeset dir=
658	typeset kmod=
659	typeset karch=
660
661	[[ ! -d $modbase ]] && return
662
663	for dir in $(find $modbase -name kmod) ; do
664		set -- $(echo $dir | tr '/' ' ')
665
666		[[ $# -lt 3 ]] && fail "invalid karch kmod dir $dir"
667
668		shift $(($# - 3))
669		kmod=$1
670		bdir=$2
671
672		[[ $bdir != $bitdir ]] && continue
673		[[ ! -f $dir/$1 ]] && continue
674
675		kmdb_copy $dir/$kmod $destdir
676	done
677}
678
679function kmdb_copy_kmdbmod {
680	typeset kmdbpath="$1"
681	typeset destdir="$2"
682
683	[[ ! -f $kmdbpath ]] && return 1
684
685	kmdb_copy $kmdbpath $destdir
686
687	return 0
688}
689
690function copy_kmdb {
691	typeset kmdbtgtdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME/misc
692	typeset bitdirs=
693	typeset isadir=
694	typeset b64srcdir=
695	typeset b64tgtdir=
696	typeset b32srcdir=
697	typeset b32tgtdir=
698	typeset machdir=
699	typeset platdir=
700
701	if [[ $KMDB = "no" || ! -d $SRC/cmd/mdb ]] ; then
702		# The kmdb copy was suppressed or the workspace doesn't contain
703		# the mdb subtree.  Either way, there's nothing to do.
704		STATE=2
705		save_state
706		return
707	fi
708
709	if [[ $(mach) = "i386" ]] ; then
710		isadir="intel"
711		b64srcdir="amd64"
712		b64tgtdir="amd64"
713		b32srcdir="ia32"
714		b32tgtdir="."
715	else
716		isadir="sparc"
717		b64srcdir="v9"
718		b64tgtdir="sparcv9"
719		b32srcdir="v7"
720		b32tgtdir="."
721	fi
722
723	typeset foundkmdb=no
724	typeset kmdbpath=
725	typeset destdir=
726
727	platdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME
728	if [[ $GLOM = "yes" ]] ; then
729		machdir=$platdir
730	else
731		machdir=$INSTALL_FILES/kernel
732	fi
733
734	srctrees=$SRC
735	if [[ -d $SRC/../closed && "$CLOSED_IS_PRESENT" != no ]]; then
736		srctrees="$srctrees $SRC/../closed"
737	else
738		if [ -z "$ON_CRYPTO_BINS" ]; then
739			echo "Warning: ON_CRYPTO_BINS not set; pre-signed" \
740			    "crypto not provided."
741		fi
742	fi
743	if [[ $WANT64 = "yes" ]] ; then
744		# kmdbmod for sparc and x86 are built and installed
745		# in different places
746		if [[ $(mach) = "i386" ]] ; then
747			kmdbpath=$SRC/cmd/mdb/$isadir/$b64srcdir/kmdb/kmdbmod
748			destdir=$machdir/misc/$b64tgtdir
749		else
750			kmdbpath=$SRC/cmd/mdb/$KARCH/$b64srcdir/kmdb/kmdbmod
751			destdir=$platdir/misc/$b64tgtdir
752		fi
753
754		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
755			foundkmdb="yes"
756
757			for tree in $srctrees; do
758				kmdb_copy_machkmods \
759				    $tree/cmd/mdb/$isadir/$b64srcdir \
760				    $machdir/kmdb/$b64tgtdir
761				kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \
762				    $platdir/kmdb/$b64tgtdir $b64srcdir
763			done
764		fi
765	fi
766
767	if [[ $WANT32 = "yes" ]] ; then
768		kmdbpath=$SRC/cmd/mdb/$isadir/$b32srcdir/kmdb/kmdbmod
769		destdir=$machdir/misc/$b32tgtdir
770
771		if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
772			foundkmdb="yes"
773
774			for tree in $srctrees; do
775				kmdb_copy_machkmods \
776				    $tree/cmd/mdb/$isadir/$b32srcdir \
777				    $machdir/kmdb/$b32tgtdir
778				kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \
779				    $platdir/kmdb/$b32tgtdir $b32srcdir
780			done
781		fi
782	fi
783
784	# A kmdb-less workspace isn't fatal, but it is potentially problematic,
785	# as the changes made to uts may have altered something upon which kmdb
786	# depends.  We will therefore remind the user that they haven't built it
787	# yet.
788	if [[ $foundkmdb != "yes" ]] ; then
789		echo "WARNING: kmdb isn't built, and won't be included"
790	fi
791
792	STATE=2
793	save_state
794	return
795}
796
797#
798# Make tarfile
799#
800
801function make_tarfile {
802	echo "Creating tarfile $TARFILE"
803	test -d $INSTALL_FILES || fail "Can't find $INSTALL_FILES"
804	cd $INSTALL_FILES
805	rm -f $TARFILE files
806
807	# We don't want to change the permissions or ownership of pre-existing
808	# directories on the target machine, so we're going to take care to
809	# avoid including directories in the tarfile.  On extraction, tar won't
810	# modify pre-existing directories, and will create non-existent ones as
811	# the user doing the extraction.
812	find . ! -type d -print |fgrep -vx './files' >files
813	tar cf $TARFILE -I files || fail "Couldn't create tarfile $TARFILE"
814	STATE=3
815}
816
817#
818# Routines to copy files to the target machine
819#
820
821function remote_fail {
822	fail "" "$1" "" \
823		"Make sure that $TARGET_MACHINE is up." \
824"Check .rhosts in the home directory of user $TARGET_USER on $TARGET_MACHINE." \
825		"Check /etc/hosts.equiv, /etc/passwd, and /etc/shadow." \
826		"Change permissions on $TARGET_MACHINE as necessary." \
827		"Then, use \"$INSTALL -R\" to resume the install." ""
828}
829
830function remote_install {
831	if [ "$IMODE" = "n" ]; then
832		STATE=4
833		return 0
834	fi
835	test -s $TARFILE || fail "$TARFILE missing or empty"
836	verbose "Installing system on $TARGET"
837	test -d $INSTALL_DIR || fail "Can't find $INSTALL_DIR"
838	cd $INSTALL_DIR
839	rm -f errors fatal nonfatal
840	if [ "$IMODE" = "T" ]; then
841		EMESG="Can't rcp to $TARGET"
842		touch errors
843		sh -e${SHV}c "$INSTALL_RCP $TARFILE $TARGET/Install.tar"
844	else
845		EMESG="Can't rsh to $TARGET_MACHINE"
846		rsh -l $TARGET_USER $TARGET_MACHINE \
847		    "(cd $TARGET_DIR; /usr/bin/tar x${V}f -)" \
848		    <$TARFILE 2>errors
849	fi
850	test $? -ne 0 && remote_fail "$EMESG"
851	cd $INSTALL_DIR
852	egrep "set time|warning|blocksize" errors >nonfatal
853	egrep -v "set time|warning|blocksize" errors >fatal
854	if [ -s fatal ]; then
855		echo "Fatal errors from rsh:"
856		cat fatal
857		remote_fail "Can't install on $TARGET_MACHINE"
858	fi
859	if [ -s nonfatal -a "$VERBOSE" != "q" ]; then
860		echo "Non-fatal errors from rsh:"
861		cat nonfatal
862	fi
863	rm -f fatal nonfatal errors
864	test "$IMODE" = "T" && echo "Files can be extracted on \
865$TARGET_MACHINE using 'tar xvf $TARGET_DIR/Install.tar'"
866	STATE=4
867}
868
869function okexit {
870	cd /tmp
871	test "$CLEANUP" = c && remove_dir $INSTALL_DIR
872	save_state
873	rm -rf $modstatedir
874	rm -f $modlist
875	[ -n "$cryptotree" ] && rm -rf "$cryptotree"
876	verbose "Install complete"
877	exit 0
878}
879
880#
881# Process options
882#
883
884RCOPTS=""
885LIBCREATE="no"
886LIBSRC=""
887ENV_PATH=$CODEMGR_WS
888OBJD="debug"
889KMDB="yes"
890
891test -s $INSTALL_RC && RCOPTS=`cat $INSTALL_RC`
892set $INSTALL $DEFAULT_OPTIONS $RCOPTS $*
893shift
894
895while getopts acd:D:G:hi:k:Kl:Lmno:pPqRs:t:T:uvVw:xX36 opt
896do
897	case $opt in
898	    w)	ENV_PATH="$OPTARG"; SRC="$ENV_PATH/usr/src";;
899	    s)	UTS="$OPTARG";;
900	    k)	KARCH="$OPTARG";;
901	  t|T)	TARGET="$OPTARG"; IMODE=$opt; CLEANUP="c";;
902	    n)	TARGET=""; IMODE="n"; CLEANUP="p";;
903	    u)	files="unix genunix";;
904	    m)	files="Modules";;
905	    a)	files="All";;
906	v|V|q)	VERBOSE=$opt;;
907	  c|p)	CLEANUP=$opt;;
908	    L)	LIBCREATE="yes"; CLEANUP="c";;
909	    l)	LIBSRC="$OPTARG";;
910	    D)	INSTALL_LIB="$OPTARG";;
911	    d)	INSTALL_DIR="$OPTARG/$TRAILER";;
912	    G)	GLOM=yes; GLOMNAME="$OPTARG";;
913	P|X|x)	echo "-$opt is obsolete; ignored";;
914	    h)	usage "${INSTALL}: installs unix and modules";;
915	    R)	x=$OPTIND; restore_state; OPTIND=$x;;
916	    i)	IMPL="$OPTARG";;
917	    o)	OBJD="$OPTARG";;
918	    K)  KMDB="no";;
919	    3)  WANT64="no";;
920	    6)  WANT32="no";;
921	   \?)	usage "Illegal option";;
922	esac
923done
924shift `expr $OPTIND - 1`
925
926ENV_NAME=`basename $ENV_PATH`
927
928#
929# The rest of the command line is a list of individual files to copy.
930# If non-null, this list overrides the -uma options.
931#
932
933if [[ $# -gt 0 ]] ; then
934	files="$*"
935	KMDB="no"
936fi
937
938case "$VERBOSE" in
939	v)	V="v"; SHV="x";;
940	V)	V="v"; SHV="x"; set -x;;
941	q)	V=""; SHV="";;
942esac
943
944#
945# Create temp directory for Install's files
946#
947
948tstmkdir $INSTALL_DIR
949
950TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
951INSTALL_FILES=$INSTALL_DIR/$KARCH
952
953#
954# Extract the target machine and target directory from a target of the
955# form [user@]machine:/dir .
956#
957
958if [ "$IMODE" != "n" ]; then
959	eval `echo $TARGET | nawk -F':' '{
960		if (NF != 2 || !length($1) || !length($2))
961			print "usage \"Invalid target\""
962		m = $1; d = $2
963		if ($1 ~ /@/) {
964		    k = split($1, f, "@");
965		    if (k != 2 || !length(f[1]) || !length (f[2]))
966			    print "usage \"Invalid target\""
967		    u = f[1]; m = f[2]
968		}
969		print "TARGET_USER=" u ";"
970		print "TARGET_MACHINE=" m ";"
971		print "TARGET_DIR=" d ";"
972	}'`
973	if [ -z "$TARGET_USER" ]; then
974		TARGET_USER=$LOGNAME
975	fi
976fi
977
978#
979# Allow the use of library source or target for the install
980#
981
982if [ -n "$LIBSRC" ]; then
983	LIBSRC="`basename $LIBSRC .tar`.tar"
984	TARFILE=$INSTALL_LIB/$LIBSRC
985	test -s $TARFILE || fail "Can't find tarfile $TARFILE"
986	verbose "Installing from library tarfile $TARFILE"
987	STATE=3
988elif [ "$LIBCREATE" = "yes" ]; then
989	tstmkdir $INSTALL_LIB
990	TARFILE="$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar"
991fi
992
993#
994# The next few lines allow recovery and activation with -R,
995# and library installs with -l.
996#
997
998[[ $STATE -eq 1 ]] && copy_kmdb
999[[ $STATE -eq 2 ]] && make_tarfile
1000[[ $STATE -eq 3 ]] && remote_install
1001[[ $STATE -eq 4 ]] && okexit
1002
1003save_state
1004
1005cd $DOT
1006DOTDOT=`cd ..; pwd`
1007
1008#
1009# Try to be smart: if DOTDOT ends in uts, then infer UTS and KARCH from DOT
1010# Otherwise, if SRC is set, infer UTS = $SRC/uts.
1011#
1012
1013if [ "`basename $DOTDOT`" = "uts" ]; then
1014	UTS=$DOTDOT
1015	KARCH=`basename $DOT`
1016	if [ ! -n "$SRC" ]; then
1017		SRC=`dirname $DOTDOT`
1018		verbose "Setting SRC to $SRC"
1019	fi
1020	export SRC
1021fi
1022
1023if [ -z "$UTS" -a -n "$SRC" ]; then
1024	UTS="${SRC}/uts"
1025	test -n "$KARCH" || fail "no karch specified (e.g. -k sun4u)"
1026fi
1027
1028if [ "$LIBCREATE" = "yes" ]; then
1029	TARFILE=$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar
1030else
1031	TARFILE=$INSTALL_DIR/Install.${KARCH}.tar
1032fi
1033INSTALL_FILES=$INSTALL_DIR/$KARCH
1034save_state
1035
1036cd $DOT
1037test -z "$UTS" && fail 'Cannot find kernel sources -- $SRC not set'
1038test -d "$UTS" || fail "${UTS}: no such directory"
1039
1040#
1041# Convert UTS into an absolute path.
1042#
1043
1044cd $UTS
1045UTS=`pwd`
1046
1047test "`basename $UTS`" = "uts" || \
1048	verbose "Warning: source path $UTS doesn't end in 'uts'"
1049
1050remove_dir $INSTALL_DIR/$KARCH
1051rm -f $TARFILE
1052
1053copy_kernel	# sets STATE=1 if successful
1054copy_kmdb	# sets STATE=2 if successful
1055make_tarfile	# sets STATE=3 if successful
1056remote_install	# sets STATE=4 if successful
1057
1058okexit
1059