Install.sh revision c3e6cb59e6ec7e289cc296c8f5f6e77651afe0a2
#
# 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
# 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
#
#
#
# Author: Jeff Bonwick
#
# Please report any bugs to bonwick@eng.
#
# How Install works:
#
# Install performs the following steps:
#
# 1. Get the list of modules, configuration files, and links
# that are desired.
#
# 2. Create the requested subset of /kernel in Install's temp space
# (/tmp/Install.username by default.)
#
# 3. Create a tar file (/tmp/Install.username/Install.tar) based on (3).
#
# 4. If -n was specified, exit. If a target was specified using -T,
# rcp the tarfile to the target and exit. If a target was specified
# using -t, rsh to the target machine and untar the tarfile in the
# target directory.
#
# If any of these steps fail, Install will give you an error message and,
# in most cases, suggest corrective measures. Then, you can recover the
# install with "Install -R". (This is not required; it's just faster than
# starting from scratch.)
#
# One final comment: Unfortunately, tar and I disagree on what
# constitutes a fatal error. (tar -x will exit 0 even if it can't write
# anything in the current directory.) Thus, I am reduced to grepping stderr
# for (what I consider) fatal and nonfatal error messages. If you run into
# a situation where this doesn't behave the way you think it should (either
# an "Install failed" message after a successful install, or an "Install
# complete" message after it bombs), please let me know.
#
# 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
DOT=`pwd`
export INSTALL_STATE
fi
export INSTALL_DIR
export INSTALL_LIB
export INSTALL_RC
export INSTALL_CP
export INSTALL_RCP
STATE=0
DEFAULT_OPTIONS="-naq"
IMPL="default"
WANT32="yes"
WANT64="yes"
# dummy directory for make state files.
trap 'fail "User Interrupt" "You can resume by typing \"$INSTALL -R\""' 1 2 3 15
function usage {
echo ""
echo $1
echo '
Usage: Install [ -w workspace ]
[ -k karch (e.g. sun4u; required if not deducible from pwd) ]
[ -t target (extract tar file on target, e.g. user@machine:/) ]
[ -T target (copy tar file to target, e.g. user@machine:/tmp) ]
[ -n (no target, just create tar file in /tmp (default)) ]
[ -u (install unix only) ]
[ -m (install modules only) ]
[ -a (install everything, i.e. unix + modules (default)) ]
[ -v (verbose output) ]
[ -V (REALLY verbose output) ]
[ -q (quiet (default)) ]
[ -c (clean up (remove temp files) when done (default) ]
[ -p (preserve temp files -- useful for debugging) ]
[ -L (library create: put tarfile in $INSTALL_LIB/env.karch) ]
[ -l lib (library extract: use $INSTALL_LIB/lib as source) ]
[ -D libdir (default: $HOME/LibInstall) ]
[ -d tempdir (Install work area (default: /tmp)) ]
[ -i impl (e.g. sunfire; recommended with -G) ]
[ -x (update /etc/name_to_major et al) ]
[ -X (do not update /etc/name_to_major et al (default)) ]
[ -P (update /etc/path_to_inst -- generally not advisable) ]
[ -h (help -- prints this message) ]
[ -R (recover a previous Install) ]
[ -o objdir (object directory - either obj or debug (the default)) ]
[ -K (do not copy kmdb) ]
[ -3 32-bit modules only ]
[ -6 64-bit modules only ]
[ list of modules to install ]
For full details:
man -M /ws/on297-gate/public/docs Install
'
exit 1
}
#
# Save the current state of Install
#
function save_state {
rm -f $INSTALL_STATE
(echo "# State of previous Install
TARGET=$TARGET
ENV_PATH=$ENV_PATH
ENV_NAME=$ENV_NAME
KARCH=$KARCH
UTS=$UTS
INSTALL_DIR=$INSTALL_DIR
INSTALL_LIB=$INSTALL_LIB
IMODE=$IMODE
LIBCREATE=$LIBCREATE
LIBSRC=$LIBSRC
VERBOSE=$VERBOSE
CLEANUP=$CLEANUP
GLOM=$GLOM
GLOMNAME=$GLOMNAME
KMDB=$KMDB
files='$files'
}
#
# Restore the previous state of Install
#
function restore_state {
test -s $INSTALL_STATE || fail "Can't find $INSTALL_STATE"
}
#
# Install failed -- print error messages and exit 2
#
function fail {
#
# We might have gotten here via a trap. So wait for any
# children (especially "make modlist") to exit before giving
# the error message or cleaning up.
#
wait
while [ $# -gt 0 ]
do
echo $1
shift
done
echo "Install failed"
exit 2
}
#
# Echo a string in verbose mode only
#
function verbose {
}
#
# hack for tmpfs bug -- remove files gradually
#
function remove_dir {
test -d $1 || return
local_dot=`pwd`
cd $1
cd $local_dot
}
#
# Create a directory if it doesn't already exist.
# mkdir will provide an error message, so don't provide an additional
# message.
#
function tstmkdir {
}
#
# Patch up target directories for glommed kernel.
# usage: fixglom listfile glomname
#
function fixglom {
nawk \
-v glomname=$2 \
$1 == "MOD" || $1 == "SYMLINK" {
sub(/^platform.*kernel/, "platform/" karch "/" glomname, $4)
sub(/^kernel/, "platform/" karch "/" glomname, $4)
sub(/^usr.kernel/, "platform/" karch "/" glomname, $4)
print
}
$1 == "LINK" {
sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3)
sub(/^kernel/, "platform/" karch "/" glomname, $3)
sub(/^usr.kernel/, "platform/" karch "/" glomname, $3)
sub(/^platform.*kernel/, "platform/" karch "/" glomname, $5)
sub(/^kernel/, "platform/" karch "/" glomname, $5)
sub(/^usr.kernel/, "platform/" karch "/" glomname, $5)
print
}
$1 == "CONF" {
sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3)
sub(/^kernel/, "platform/" karch "/" glomname, $3)
sub(/^usr.kernel/, "platform/" karch "/" glomname, $3)
print
}
' $1 > $1.new
}
#
# Filter out implementation-specific modules, unless that
# implementation was requested by the user.
# usage: filtimpl listfile implname
#
function filtimpl {
nawk \
-v impl=$2 '
$1 == "MOD" || $1 == "SYMLINK" {
if ($6 == "all" || $6 == impl)
print
}
$1 == "CONF" {
if ($5 == "all" || $5 == impl)
print
}
$1 == "LINK" {
if ($7 == "all" || $7 == impl)
print
}
' $1 > $1.new
}
#
# Filter the module list to match the user's request.
# Usage: filtmod listfile modules
#
function filtmod {
function modmatch(modname) {
if (reqstring == "All") {
return (1)
} else if (reqstring == "Modules") {
if (modname != "unix" && modname != "genunix")
return (1)
} else {
if (modname in reqmods)
return (1)
}
return (0)
}
BEGIN {
#
# The split call creates indexes 1, 2, 3, ... We want
# the module names as indexes.
#
split(reqstring, tmpmods)
for (i in tmpmods)
reqmods[tmpmods[i]] = 1
}
$1 == "MOD" {
if (modmatch($3))
print
}
$1 == "CONF" {
if (modmatch($6))
print
}
$1 == "SYMLINK" {
if (modmatch($7))
print
}
$1 == "LINK" {
if (modmatch($4))
print
}
' $1 > $1.new
}
#
# Unpack the crypto tarball into the given tree, then massage the
# tree so that the binaries are all in objNN or debugNN directories.
#
function unpack_crypto {
typeset tarfile=$1
typeset ctop=$2
[ ! -d $d ] && continue
find $d -type f -print
done) | while read file; do
else
fi
done
}
#
# Copy a module, or create a link, as needed.
#
function copymod {
case $1 in
MOD)
verbose "$INSTALL_CP $2/${OBJD}$5/$3 $target"
$INSTALL_CP $2/${OBJD}$5/$3 $target || \
;;
;;
LINK)
verbose "ln $INSTALL_FILES/$3/$4 $target"
ln $INSTALL_FILES/$3/$4 $target || fail "can't create $target"
;;
CONF)
;;
*)
fail "unrecognized modlist entry: $*"
;;
esac
}
# Sanity-check the given module list.
function check_modlist {
nawk '
BEGIN {
nfields["MOD"] = 6
nfields["CONF"] = 6
nfields["LINK"] = 7
nfields["SYMLINK"] = 7
}
{
# This also catches unknown tags.
if (nfields[$1] != NF) {
print "error: invalid modlist record:"
print $0
print "expected", nfields[$1], "fields, found", NF
status=1
}
}
END {
exit status
}
}
#
# Copy kernel modules to $INSTALL_DIR
#
function copy_kernel {
esac
export MACH
else
fi
export MODSTATE=$modstatedir/state
#
# Figure out which "make" to use. dmake is faster than serial
# make, but dmake 7.3 has a bug that causes it to lose log
# output, which means the modlist might be incomplete.
#
if [ $? -ne 0 ]; then
elif [[ $dmvers = *Distributed?Make?7.3* ]]; then
unset make
for dmpath in $searchpath; do
if [[ $dmvers != *Distributed?Make?7.3* ]]; then
break;
fi
fi
done
if [ -z $make ]; then
echo "Warning: dmake 7.3 doesn't work with Install;" \
"using $make"
fi
fi
#
# Get a list of all modules, configuration files, and links
# that we might want to install.
#
verbose "Building module list..."
fi
fi
#
# Copy modules and create links. For architectures with both
# 32- and 64-bit modules, we'll likely have duplicate
# configuration files, so do those after filtering out the
# duplicates.
#
verbose "Copying files to ${INSTALL_FILES}..."
#
# The IFS is reset to the newline character so we can buffer the
# output of grep without piping it directly to copymod, otherwise
# if fail() is called, then it will deadlock in fail()'s wait call
#
IFS="
"
done
IFS="
"
done
#
# Add the glommed kernel name to the root archive
#
then
fi
STATE=1 # all kernel modules copied correctly
}
function kmdb_copy {
typeset src="$1"
typeset destdir="$2"
if [[ ! -d $dest ]] ; then
fi
}
function kmdb_copy_machkmods {
typeset modbase="$1"
typeset destdir="$2"
typeset dir=
typeset kmod=
[[ ! -d $modbase ]] && return
shift $(($# - 2))
kmod=$1
done
}
function kmdb_copy_karchkmods {
typeset modbase="$1"
typeset destdir="$2"
typeset bitdir="$3"
typeset dir=
typeset kmod=
typeset karch=
[[ ! -d $modbase ]] && return
shift $(($# - 3))
kmod=$1
bdir=$2
[[ ! -f $dir/$1 ]] && continue
done
}
function kmdb_copy_kmdbmod {
typeset kmdbpath="$1"
typeset destdir="$2"
[[ ! -f $kmdbpath ]] && return 1
return 0
}
function copy_kmdb {
typeset kmdbtgtdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME/misc
typeset bitdirs=
typeset isadir=
typeset b64srcdir=
typeset b64tgtdir=
typeset b32srcdir=
typeset b32tgtdir=
typeset machdir=
typeset platdir=
# The kmdb copy was suppressed or the workspace doesn't contain
# the mdb subtree. Either way, there's nothing to do.
STATE=2
return
fi
isadir="intel"
b64srcdir="amd64"
b64tgtdir="amd64"
b32srcdir="ia32"
b32tgtdir="."
else
isadir="sparc"
b64srcdir="v9"
b64tgtdir="sparcv9"
b32srcdir="v7"
b32tgtdir="."
fi
typeset kmdbpath=
typeset destdir=
else
fi
# kmdbmod for sparc and x86 are built and installed
# in different places
else
fi
if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
foundkmdb="yes"
done
fi
fi
if kmdb_copy_kmdbmod $kmdbpath $destdir ; then
foundkmdb="yes"
done
fi
fi
# A kmdb-less workspace isn't fatal, but it is potentially problematic,
# as the changes made to uts may have altered something upon which kmdb
# depends. We will therefore remind the user that they haven't built it
# yet.
echo "WARNING: kmdb isn't built, and won't be included"
fi
STATE=2
return
}
#
# Make tarfile
#
function make_tarfile {
echo "Creating tarfile $TARFILE"
test -d $INSTALL_FILES || fail "Can't find $INSTALL_FILES"
# We don't want to change the permissions or ownership of pre-existing
# directories on the target machine, so we're going to take care to
# avoid including directories in the tarfile. On extraction, tar won't
# modify pre-existing directories, and will create non-existent ones as
# the user doing the extraction.
STATE=3
}
#
# Routines to copy files to the target machine
#
function remote_fail {
"Check .rhosts in the home directory of user $TARGET_USER on $TARGET_MACHINE." \
"Then, use \"$INSTALL -R\" to resume the install." ""
}
function remote_install {
STATE=4
return 0
fi
test -d $INSTALL_DIR || fail "Can't find $INSTALL_DIR"
cd $INSTALL_DIR
sh -e${SHV}c "$INSTALL_RCP $TARFILE $TARGET/Install.tar"
else
EMESG="Can't rsh to $TARGET_MACHINE"
fi
test $? -ne 0 && remote_fail "$EMESG"
cd $INSTALL_DIR
if [ -s fatal ]; then
echo "Fatal errors from rsh:"
remote_fail "Can't install on $TARGET_MACHINE"
fi
echo "Non-fatal errors from rsh:"
fi
$TARGET_MACHINE using 'tar xvf $TARGET_DIR/Install.tar'"
STATE=4
}
function okexit {
cd /tmp
verbose "Install complete"
exit 0
}
#
# Process options
#
RCOPTS=""
LIBCREATE="no"
LIBSRC=""
OBJD="debug"
KMDB="yes"
shift
do
u) files="unix genunix";;
m) files="Modules";;
a) files="All";;
D) INSTALL_LIB="$OPTARG";;
d) INSTALL_DIR="$OPTARG/$TRAILER";;
P|X|x) echo "-$opt is obsolete; ignored";;
h) usage "${INSTALL}: installs unix and modules";;
K) KMDB="no";;
\?) usage "Illegal option";;
esac
done
#
# The rest of the command line is a list of individual files to copy.
# If non-null, this list overrides the -uma options.
#
if [[ $# -gt 0 ]] ; then
files="$*"
KMDB="no"
fi
esac
#
# Create temp directory for Install's files
#
#
# Extract the target machine and target directory from a target of the
# form [user@]machine:/dir .
#
if [ "$IMODE" != "n" ]; then
if (NF != 2 || !length($1) || !length($2))
print "usage \"Invalid target\""
m = $1; d = $2
if ($1 ~ /@/) {
k = split($1, f, "@");
if (k != 2 || !length(f[1]) || !length (f[2]))
print "usage \"Invalid target\""
u = f[1]; m = f[2]
}
print "TARGET_USER=" u ";"
print "TARGET_MACHINE=" m ";"
print "TARGET_DIR=" d ";"
}'`
if [ -z "$TARGET_USER" ]; then
fi
fi
#
# Allow the use of library source or target for the install
#
if [ -n "$LIBSRC" ]; then
STATE=3
elif [ "$LIBCREATE" = "yes" ]; then
TARFILE="$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar"
fi
#
# The next few lines allow recovery and activation with -R,
# and library installs with -l.
#
cd $DOT
DOTDOT=`cd ..; pwd`
#
# Try to be smart: if DOTDOT ends in uts, then infer UTS and KARCH from DOT
#
if [ ! -n "$SRC" ]; then
fi
export SRC
fi
UTS="${SRC}/uts"
fi
if [ "$LIBCREATE" = "yes" ]; then
else
fi
cd $DOT
#
# Convert UTS into an absolute path.
#
cd $UTS
UTS=`pwd`
copy_kernel # sets STATE=1 if successful
copy_kmdb # sets STATE=2 if successful
make_tarfile # sets STATE=3 if successful
remote_install # sets STATE=4 if successful