xref: /onnv-gate/usr/src/lib/brand/shared/zone/common.ksh (revision 12773:f0d486d64936)
112199Sgerald.jelinek@sun.com#
212199Sgerald.jelinek@sun.com# CDDL HEADER START
312199Sgerald.jelinek@sun.com#
412199Sgerald.jelinek@sun.com# The contents of this file are subject to the terms of the
512199Sgerald.jelinek@sun.com# Common Development and Distribution License (the "License").
612199Sgerald.jelinek@sun.com# You may not use this file except in compliance with the License.
712199Sgerald.jelinek@sun.com#
812199Sgerald.jelinek@sun.com# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912199Sgerald.jelinek@sun.com# or http://www.opensolaris.org/os/licensing.
1012199Sgerald.jelinek@sun.com# See the License for the specific language governing permissions
1112199Sgerald.jelinek@sun.com# and limitations under the License.
1212199Sgerald.jelinek@sun.com#
1312199Sgerald.jelinek@sun.com# When distributing Covered Code, include this CDDL HEADER in each
1412199Sgerald.jelinek@sun.com# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512199Sgerald.jelinek@sun.com# If applicable, add the following below this CDDL HEADER, with the
1612199Sgerald.jelinek@sun.com# fields enclosed by brackets "[]" replaced with your own identifying
1712199Sgerald.jelinek@sun.com# information: Portions Copyright [yyyy] [name of copyright owner]
1812199Sgerald.jelinek@sun.com#
1912199Sgerald.jelinek@sun.com# CDDL HEADER END
2012199Sgerald.jelinek@sun.com#
2112734Sgary.pennington@oracle.com# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2212199Sgerald.jelinek@sun.com#
2312199Sgerald.jelinek@sun.com
2412199Sgerald.jelinek@sun.com#
2512199Sgerald.jelinek@sun.com# Send the error message to the screen and to the logfile.
2612199Sgerald.jelinek@sun.com#
2712199Sgerald.jelinek@sun.comerror()
2812199Sgerald.jelinek@sun.com{
2912199Sgerald.jelinek@sun.com        typeset fmt="$1"
3012199Sgerald.jelinek@sun.com        shift
3112199Sgerald.jelinek@sun.com
3212199Sgerald.jelinek@sun.com        printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
3312199Sgerald.jelinek@sun.com        [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
3412199Sgerald.jelinek@sun.com}
3512199Sgerald.jelinek@sun.com
3612199Sgerald.jelinek@sun.comfatal()
3712199Sgerald.jelinek@sun.com{
3812199Sgerald.jelinek@sun.com        typeset fmt="$1"
3912199Sgerald.jelinek@sun.com        shift
4012199Sgerald.jelinek@sun.com
4112199Sgerald.jelinek@sun.com	error "$fmt" "$@"
4212199Sgerald.jelinek@sun.com	exit $EXIT_CODE
4312199Sgerald.jelinek@sun.com}
4412199Sgerald.jelinek@sun.com
4512199Sgerald.jelinek@sun.comfail_fatal() {
46*12773Sgerald.jelinek@sun.com        typeset fmt="$1"
47*12773Sgerald.jelinek@sun.com        shift
48*12773Sgerald.jelinek@sun.com
49*12773Sgerald.jelinek@sun.com	error "$fmt" "$@"
5012199Sgerald.jelinek@sun.com	exit $ZONE_SUBPROC_FATAL
5112199Sgerald.jelinek@sun.com}
5212199Sgerald.jelinek@sun.com
5312199Sgerald.jelinek@sun.com#
5412199Sgerald.jelinek@sun.com# Send the provided printf()-style arguments to the screen and to the logfile.
5512199Sgerald.jelinek@sun.com#
5612199Sgerald.jelinek@sun.comlog()
5712199Sgerald.jelinek@sun.com{
5812199Sgerald.jelinek@sun.com        typeset fmt="$1"
5912199Sgerald.jelinek@sun.com        shift
6012199Sgerald.jelinek@sun.com
6112199Sgerald.jelinek@sun.com        printf "${MSG_PREFIX}${fmt}\n" "$@"
6212199Sgerald.jelinek@sun.com        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
6312199Sgerald.jelinek@sun.com}
6412199Sgerald.jelinek@sun.com
6512199Sgerald.jelinek@sun.com#
6612199Sgerald.jelinek@sun.com# Print provided text to the screen if the shell variable "OPT_V" is set.
6712199Sgerald.jelinek@sun.com# The text is always sent to the logfile.
6812199Sgerald.jelinek@sun.com#
6912199Sgerald.jelinek@sun.comvlog()
7012199Sgerald.jelinek@sun.com{
7112199Sgerald.jelinek@sun.com        typeset fmt="$1"
7212199Sgerald.jelinek@sun.com        shift
7312199Sgerald.jelinek@sun.com
7412199Sgerald.jelinek@sun.com        [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
7512199Sgerald.jelinek@sun.com        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
7612199Sgerald.jelinek@sun.com}
7712199Sgerald.jelinek@sun.com
7812199Sgerald.jelinek@sun.com#
7912199Sgerald.jelinek@sun.com# Validate that the directory is safe.
8012199Sgerald.jelinek@sun.com#
8112199Sgerald.jelinek@sun.com# It is possible for a malicious zone root user to modify a zone's filesystem
8212199Sgerald.jelinek@sun.com# so that modifications made to the zone's filesystem by administrators in the
8312199Sgerald.jelinek@sun.com# global zone modify the global zone's filesystem.  We can prevent this by
8412199Sgerald.jelinek@sun.com# ensuring that all components of paths accessed by scripts are real (i.e.,
8512199Sgerald.jelinek@sun.com# non-symlink) directories.
8612199Sgerald.jelinek@sun.com#
8712199Sgerald.jelinek@sun.com# NOTE: The specified path should be an absolute path as would be seen from
8812199Sgerald.jelinek@sun.com# within the zone.  Also, this function does not check parent directories.
8912199Sgerald.jelinek@sun.com# If, for example, you need to ensure that every component of the path
9012199Sgerald.jelinek@sun.com# '/foo/bar/baz' is a directory and not a symlink, then do the following:
9112199Sgerald.jelinek@sun.com#
9212199Sgerald.jelinek@sun.com#	safe_dir /foo
9312199Sgerald.jelinek@sun.com#	safe_dir /foo/bar
9412199Sgerald.jelinek@sun.com#	safe_dir /foo/bar/baz
9512199Sgerald.jelinek@sun.com#
9612199Sgerald.jelinek@sun.comsafe_dir()
9712199Sgerald.jelinek@sun.com{
9812199Sgerald.jelinek@sun.com	typeset dir="$1"
9912199Sgerald.jelinek@sun.com
10012199Sgerald.jelinek@sun.com	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
10112199Sgerald.jelinek@sun.com		fatal "$e_baddir" "$dir"
10212199Sgerald.jelinek@sun.com	fi
10312199Sgerald.jelinek@sun.com}
10412199Sgerald.jelinek@sun.com
10512199Sgerald.jelinek@sun.com# Like safe_dir except the dir doesn't have to exist.
10612199Sgerald.jelinek@sun.comsafe_opt_dir()
10712199Sgerald.jelinek@sun.com{
10812199Sgerald.jelinek@sun.com	typeset dir="$1"
10912199Sgerald.jelinek@sun.com
11012199Sgerald.jelinek@sun.com	[[ ! -e $ZONEROOT/$dir ]] && return
11112199Sgerald.jelinek@sun.com
11212199Sgerald.jelinek@sun.com	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
11312199Sgerald.jelinek@sun.com		fatal "$e_baddir" "$dir"
11412199Sgerald.jelinek@sun.com	fi
11512199Sgerald.jelinek@sun.com}
11612199Sgerald.jelinek@sun.com
11712199Sgerald.jelinek@sun.com# Only make a copy if we haven't already done so.
11812199Sgerald.jelinek@sun.comsafe_backup()
11912199Sgerald.jelinek@sun.com{
12012199Sgerald.jelinek@sun.com	typeset src="$1"
12112199Sgerald.jelinek@sun.com	typeset dst="$2"
12212199Sgerald.jelinek@sun.com
12312199Sgerald.jelinek@sun.com	if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
12412199Sgerald.jelinek@sun.com		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
12512199Sgerald.jelinek@sun.com	fi
12612199Sgerald.jelinek@sun.com}
12712199Sgerald.jelinek@sun.com
12812199Sgerald.jelinek@sun.com# Make a copy even if the destination already exists.
12912199Sgerald.jelinek@sun.comsafe_copy()
13012199Sgerald.jelinek@sun.com{
13112199Sgerald.jelinek@sun.com	typeset src="$1"
13212199Sgerald.jelinek@sun.com	typeset dst="$2"
13312199Sgerald.jelinek@sun.com
13412199Sgerald.jelinek@sun.com	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
13512199Sgerald.jelinek@sun.com		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
13612199Sgerald.jelinek@sun.com	fi
13712199Sgerald.jelinek@sun.com}
13812199Sgerald.jelinek@sun.com
13912199Sgerald.jelinek@sun.com# Move a file
14012199Sgerald.jelinek@sun.comsafe_move()
14112199Sgerald.jelinek@sun.com{
14212199Sgerald.jelinek@sun.com	typeset src="$1"
14312199Sgerald.jelinek@sun.com	typeset dst="$2"
14412199Sgerald.jelinek@sun.com
14512199Sgerald.jelinek@sun.com	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
14612199Sgerald.jelinek@sun.com		/usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
14712199Sgerald.jelinek@sun.com	fi
14812199Sgerald.jelinek@sun.com}
14912199Sgerald.jelinek@sun.com
15012199Sgerald.jelinek@sun.comsafe_rm()
15112199Sgerald.jelinek@sun.com{
15212199Sgerald.jelinek@sun.com	if [[ ! -h $ZONEROOT/$1 && -f $ZONEROOT/$1 ]]; then
15312199Sgerald.jelinek@sun.com		rm -f "$ZONEROOT/$1"
15412199Sgerald.jelinek@sun.com	fi
15512199Sgerald.jelinek@sun.com}
15612199Sgerald.jelinek@sun.com
15712199Sgerald.jelinek@sun.com#
15812199Sgerald.jelinek@sun.com# Replace the file with a wrapper pointing to the native brand code.
15912199Sgerald.jelinek@sun.com# However, we only do the replacement if the file hasn't already been
16012199Sgerald.jelinek@sun.com# replaced with our wrapper.  This function expects the cwd to be the
16112199Sgerald.jelinek@sun.com# location of the file we're replacing.
16212199Sgerald.jelinek@sun.com#
16312199Sgerald.jelinek@sun.com# Some of the files we're replacing are hardlinks to isaexec so we need to 'rm'
16412199Sgerald.jelinek@sun.com# the file before we setup the wrapper while others are hardlinks to rc scripts
16512199Sgerald.jelinek@sun.com# that we need to maintain.
16612199Sgerald.jelinek@sun.com#
16712199Sgerald.jelinek@sun.comsafe_replace()
16812199Sgerald.jelinek@sun.com{
16912199Sgerald.jelinek@sun.com	typeset filename="$1"
17012199Sgerald.jelinek@sun.com	typeset runname="$2"
17112199Sgerald.jelinek@sun.com	typeset mode="$3"
17212199Sgerald.jelinek@sun.com	typeset own="$4"
17312199Sgerald.jelinek@sun.com	typeset rem="$5"
17412199Sgerald.jelinek@sun.com
17512199Sgerald.jelinek@sun.com	if [ -h $filename -o ! -f $filename ]; then
17612199Sgerald.jelinek@sun.com		return
17712199Sgerald.jelinek@sun.com	fi
17812199Sgerald.jelinek@sun.com
17912199Sgerald.jelinek@sun.com	egrep -s "Solaris Brand Replacement" $filename
18012199Sgerald.jelinek@sun.com	if [ $? -eq 0 ]; then
18112199Sgerald.jelinek@sun.com		return
18212199Sgerald.jelinek@sun.com	fi
18312199Sgerald.jelinek@sun.com
18412199Sgerald.jelinek@sun.com	safe_backup $filename $filename.pre_p2v
18512199Sgerald.jelinek@sun.com	if [ $rem = "remove" ]; then
18612199Sgerald.jelinek@sun.com		rm -f $filename
18712199Sgerald.jelinek@sun.com	fi
18812199Sgerald.jelinek@sun.com
18912199Sgerald.jelinek@sun.com	cat <<-END >$filename || exit 1
19012651Sgerald.jelinek@sun.com	#!/bin/sh -p
19112199Sgerald.jelinek@sun.com	#
19212199Sgerald.jelinek@sun.com	# Solaris Brand Replacement
19312199Sgerald.jelinek@sun.com	#
19412199Sgerald.jelinek@sun.com	# Attention.  This file has been replaced with a new version for
19512199Sgerald.jelinek@sun.com	# use in a virtualized environment.  Modification of this script is not
19612199Sgerald.jelinek@sun.com	# supported and all changes will be lost upon reboot.  The
19712199Sgerald.jelinek@sun.com	# {name}.pre_p2v version of this file is a backup copy of the
19812199Sgerald.jelinek@sun.com	# original and should not be deleted.
19912199Sgerald.jelinek@sun.com	#
20012199Sgerald.jelinek@sun.com	END
20112199Sgerald.jelinek@sun.com
20212199Sgerald.jelinek@sun.com	echo ". $runname \"\$@\"" >>$filename || exit 1
20312199Sgerald.jelinek@sun.com
20412199Sgerald.jelinek@sun.com	chmod $mode $filename
20512199Sgerald.jelinek@sun.com	chown $own $filename
20612199Sgerald.jelinek@sun.com}
20712199Sgerald.jelinek@sun.com
20812199Sgerald.jelinek@sun.comsafe_wrap()
20912199Sgerald.jelinek@sun.com{
21012199Sgerald.jelinek@sun.com	typeset filename="$1"
21112199Sgerald.jelinek@sun.com	typeset runname="$2"
21212199Sgerald.jelinek@sun.com	typeset mode="$3"
21312199Sgerald.jelinek@sun.com	typeset own="$4"
21412199Sgerald.jelinek@sun.com
21512199Sgerald.jelinek@sun.com	if [ -f $filename ]; then
21612199Sgerald.jelinek@sun.com		log "$e_cannot_wrap" "$filename"
21712199Sgerald.jelinek@sun.com		exit 1
21812199Sgerald.jelinek@sun.com	fi
21912199Sgerald.jelinek@sun.com
22012199Sgerald.jelinek@sun.com	cat <<-END >$filename || exit 1
22112199Sgerald.jelinek@sun.com	#!/bin/sh
22212199Sgerald.jelinek@sun.com	#
22312199Sgerald.jelinek@sun.com	# Solaris Brand Wrapper
22412199Sgerald.jelinek@sun.com	#
22512199Sgerald.jelinek@sun.com	# Attention.  This file has been created for use in a
22612199Sgerald.jelinek@sun.com	# virtualized environment.  Modification of this script
22712199Sgerald.jelinek@sun.com	# is not supported and all changes will be lost upon reboot.
22812199Sgerald.jelinek@sun.com	#
22912199Sgerald.jelinek@sun.com	END
23012199Sgerald.jelinek@sun.com
23112199Sgerald.jelinek@sun.com	echo ". $runname \"\$@\"" >>$filename || exit 1
23212199Sgerald.jelinek@sun.com
23312199Sgerald.jelinek@sun.com	chmod $mode $filename
23412199Sgerald.jelinek@sun.com	chown $own $filename
23512199Sgerald.jelinek@sun.com}
23612199Sgerald.jelinek@sun.com
23712199Sgerald.jelinek@sun.com#
23812734Sgary.pennington@oracle.com# Read zonecfg fs entries and save the relevant data, one entry per
23912199Sgerald.jelinek@sun.com# line.
24012199Sgerald.jelinek@sun.com# This assumes the properties from the zonecfg output, e.g.:
24112199Sgerald.jelinek@sun.com#	fs:
24212199Sgerald.jelinek@sun.com#		dir: /opt
24312199Sgerald.jelinek@sun.com#		special: /opt
24412199Sgerald.jelinek@sun.com#		raw not specified
24512199Sgerald.jelinek@sun.com#		type: lofs
24612199Sgerald.jelinek@sun.com#		options: [noexec,ro,noatime]
24712199Sgerald.jelinek@sun.com#
24812734Sgary.pennington@oracle.com# and it assumes the order of the fs properties as above.
24912199Sgerald.jelinek@sun.com#
25012199Sgerald.jelinek@sun.comget_fs_info()
25112199Sgerald.jelinek@sun.com{
25212199Sgerald.jelinek@sun.com	zonecfg -z $zonename info fs | nawk '{
25312199Sgerald.jelinek@sun.com		if ($1 == "options:") {
25412199Sgerald.jelinek@sun.com			# Remove brackets.
25512199Sgerald.jelinek@sun.com			options=substr($2, 2, length($2) - 2);
25612199Sgerald.jelinek@sun.com			printf("%s %s %s %s\n", dir, type, special, options);
25712199Sgerald.jelinek@sun.com		} else if ($1 == "dir:") {
25812199Sgerald.jelinek@sun.com			dir=$2;
25912199Sgerald.jelinek@sun.com		} else if ($1 == "special:") {
26012199Sgerald.jelinek@sun.com			special=$2;
26112199Sgerald.jelinek@sun.com		} else if ($1 == "type:") {
26212199Sgerald.jelinek@sun.com			type=$2
26312199Sgerald.jelinek@sun.com		}
26412199Sgerald.jelinek@sun.com	}' >> $fstmpfile
26512199Sgerald.jelinek@sun.com}
26612199Sgerald.jelinek@sun.com
26712199Sgerald.jelinek@sun.com#
26812199Sgerald.jelinek@sun.com# Mount zonecfg fs entries into the zonepath.
26912199Sgerald.jelinek@sun.com#
27012199Sgerald.jelinek@sun.commnt_fs()
27112199Sgerald.jelinek@sun.com{
27212199Sgerald.jelinek@sun.com	if [ ! -s $fstmpfile ]; then
27312199Sgerald.jelinek@sun.com		return;
27412199Sgerald.jelinek@sun.com	fi
27512199Sgerald.jelinek@sun.com
27612199Sgerald.jelinek@sun.com	# Sort the fs entries so we can handle nested mounts.
27712199Sgerald.jelinek@sun.com	sort $fstmpfile | nawk -v zonepath=$zonepath '{
27812199Sgerald.jelinek@sun.com		if (NF == 4)
27912199Sgerald.jelinek@sun.com			options="-o " $4;
28012199Sgerald.jelinek@sun.com		else
28112199Sgerald.jelinek@sun.com			options=""
28212199Sgerald.jelinek@sun.com
28312199Sgerald.jelinek@sun.com		# Create the mount point.  Ignore errors since we might have
28412199Sgerald.jelinek@sun.com		# a nested mount with a pre-existing mount point.
28512199Sgerald.jelinek@sun.com		cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
28612199Sgerald.jelinek@sun.com		system(cmd);
28712199Sgerald.jelinek@sun.com
28812199Sgerald.jelinek@sun.com		cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
28912199Sgerald.jelinek@sun.com		    zonepath "/root" $1;
29012199Sgerald.jelinek@sun.com		if (system(cmd) != 0) {
29112199Sgerald.jelinek@sun.com			printf("command failed: %s\n", cmd);
29212199Sgerald.jelinek@sun.com			exit 1;
29312199Sgerald.jelinek@sun.com		}
29412199Sgerald.jelinek@sun.com	}' >>$LOGFILE
29512199Sgerald.jelinek@sun.com}
29612199Sgerald.jelinek@sun.com
29712199Sgerald.jelinek@sun.com#
29812199Sgerald.jelinek@sun.com# Unmount zonecfg fs entries from the zonepath.
29912199Sgerald.jelinek@sun.com#
30012199Sgerald.jelinek@sun.comumnt_fs()
30112199Sgerald.jelinek@sun.com{
30212199Sgerald.jelinek@sun.com	if [ ! -s $fstmpfile ]; then
30312199Sgerald.jelinek@sun.com		return;
30412199Sgerald.jelinek@sun.com	fi
30512199Sgerald.jelinek@sun.com
30612199Sgerald.jelinek@sun.com	# Reverse sort the fs entries so we can handle nested unmounts.
30712199Sgerald.jelinek@sun.com	sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
30812199Sgerald.jelinek@sun.com		cmd="/usr/sbin/umount " zonepath "/root" $1
30912199Sgerald.jelinek@sun.com		if (system(cmd) != 0) {
31012199Sgerald.jelinek@sun.com			printf("command failed: %s\n", cmd);
31112199Sgerald.jelinek@sun.com		}
31212199Sgerald.jelinek@sun.com	}' >>$LOGFILE
31312199Sgerald.jelinek@sun.com}
31412199Sgerald.jelinek@sun.com
31512199Sgerald.jelinek@sun.com# Find the dataset mounted on the zonepath.
31612199Sgerald.jelinek@sun.comget_zonepath_ds() {
31712199Sgerald.jelinek@sun.com	ZONEPATH_DS=`/usr/sbin/zfs list -H -t filesystem -o name,mountpoint | \
31812199Sgerald.jelinek@sun.com	    /usr/bin/nawk -v zonepath=$1 '{
31912199Sgerald.jelinek@sun.com		if ($2 == zonepath)
32012199Sgerald.jelinek@sun.com			print $1
32112199Sgerald.jelinek@sun.com	}'`
32212199Sgerald.jelinek@sun.com
32312199Sgerald.jelinek@sun.com	if [ -z "$ZONEPATH_DS" ]; then
32412199Sgerald.jelinek@sun.com		fail_fatal "$f_no_ds"
32512199Sgerald.jelinek@sun.com	fi
32612199Sgerald.jelinek@sun.com}
32712199Sgerald.jelinek@sun.com
32812199Sgerald.jelinek@sun.com#
329*12773Sgerald.jelinek@sun.com# Perform validation and cleanup in the zoneroot after unpacking the archive.
33012199Sgerald.jelinek@sun.com#
33112199Sgerald.jelinek@sun.compost_unpack()
33212199Sgerald.jelinek@sun.com{
333*12773Sgerald.jelinek@sun.com	#
334*12773Sgerald.jelinek@sun.com	# Check if the image was created with a valid libc.so.1.
335*12773Sgerald.jelinek@sun.com	#
336*12773Sgerald.jelinek@sun.com	hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1`
337*12773Sgerald.jelinek@sun.com	if (( $? != 0 )); then
338*12773Sgerald.jelinek@sun.com		vlog "$f_hwcap_info" "$hwcap"
339*12773Sgerald.jelinek@sun.com		fail_fatal "$f_sanity_hwcap"
340*12773Sgerald.jelinek@sun.com	fi
341*12773Sgerald.jelinek@sun.com
34212199Sgerald.jelinek@sun.com	( cd "$ZONEROOT" && \
34312199Sgerald.jelinek@sun.com	    find . \( -type b -o -type c \) -exec rm -f "{}" \; )
34412199Sgerald.jelinek@sun.com}
34512199Sgerald.jelinek@sun.com
34612199Sgerald.jelinek@sun.com#
34712199Sgerald.jelinek@sun.com# Determine flar compression style from identification file.
34812199Sgerald.jelinek@sun.com#
34912199Sgerald.jelinek@sun.comget_compression()
35012199Sgerald.jelinek@sun.com{
35112199Sgerald.jelinek@sun.com	typeset ident=$1
35212199Sgerald.jelinek@sun.com	typeset line=$(grep "^files_compressed_method=" $ident)
35312199Sgerald.jelinek@sun.com
35412199Sgerald.jelinek@sun.com	print ${line##*=}
35512199Sgerald.jelinek@sun.com}
35612199Sgerald.jelinek@sun.com
35712199Sgerald.jelinek@sun.com#
35812199Sgerald.jelinek@sun.com# Determine flar archive style from identification file.
35912199Sgerald.jelinek@sun.com#
36012199Sgerald.jelinek@sun.comget_archiver()
36112199Sgerald.jelinek@sun.com{
36212199Sgerald.jelinek@sun.com        typeset ident=$1
36312199Sgerald.jelinek@sun.com        typeset line=$(grep "^files_archived_method=" $ident)
36412199Sgerald.jelinek@sun.com
36512199Sgerald.jelinek@sun.com        print ${line##*=}
36612199Sgerald.jelinek@sun.com}
36712199Sgerald.jelinek@sun.com
36812199Sgerald.jelinek@sun.com#
36912199Sgerald.jelinek@sun.com# Unpack flar into current directory (which should be zoneroot).  The flash
37012199Sgerald.jelinek@sun.com# archive is standard input.  See flash_archive(4) man page.
37112199Sgerald.jelinek@sun.com#
37212199Sgerald.jelinek@sun.com# We can't use "flar split" since it will only unpack into a directory called
37312199Sgerald.jelinek@sun.com# "archive".  We need to unpack in place in order to properly handle nested
37412199Sgerald.jelinek@sun.com# fs mounts within the zone root.  This function does the unpacking into the
37512199Sgerald.jelinek@sun.com# current directory.
37612199Sgerald.jelinek@sun.com#
37712199Sgerald.jelinek@sun.com# This code is derived from the gen_split() function in /usr/sbin/flar so
37812199Sgerald.jelinek@sun.com# we keep the same style as the original.
37912199Sgerald.jelinek@sun.com#
38012199Sgerald.jelinek@sun.cominstall_flar()
38112199Sgerald.jelinek@sun.com{
38212199Sgerald.jelinek@sun.com	typeset result
38312199Sgerald.jelinek@sun.com        typeset archiver_command
38412199Sgerald.jelinek@sun.com        typeset archiver_arguments
38512199Sgerald.jelinek@sun.com
38612199Sgerald.jelinek@sun.com	vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar"
38712199Sgerald.jelinek@sun.com
38812199Sgerald.jelinek@sun.com	# Read cookie
38912199Sgerald.jelinek@sun.com	read -r input_line
39012199Sgerald.jelinek@sun.com	if (( $? != 0 )); then
39112199Sgerald.jelinek@sun.com		log "$not_readable" "$install_media"
39212199Sgerald.jelinek@sun.com		return 1
39312199Sgerald.jelinek@sun.com	fi
39412199Sgerald.jelinek@sun.com	# The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
39512199Sgerald.jelinek@sun.com	if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
39612199Sgerald.jelinek@sun.com		log "$not_flar"
39712199Sgerald.jelinek@sun.com		return 1
39812199Sgerald.jelinek@sun.com	fi
39912199Sgerald.jelinek@sun.com
40012199Sgerald.jelinek@sun.com	while [ true ]
40112199Sgerald.jelinek@sun.com	do
40212199Sgerald.jelinek@sun.com		# We should always be at the start of a section here
40312199Sgerald.jelinek@sun.com		read -r input_line
40412199Sgerald.jelinek@sun.com		if [[ ${input_line%%=*} != "section_begin" ]]; then
40512199Sgerald.jelinek@sun.com			log "$bad_flar"
40612199Sgerald.jelinek@sun.com			return 1
40712199Sgerald.jelinek@sun.com		fi
40812199Sgerald.jelinek@sun.com		section_name=${input_line##*=}
40912199Sgerald.jelinek@sun.com
41012199Sgerald.jelinek@sun.com		# If we're at the archive, we're done skipping sections.
41112199Sgerald.jelinek@sun.com		if [[ "$section_name" == "archive" ]]; then
41212199Sgerald.jelinek@sun.com			break
41312199Sgerald.jelinek@sun.com		fi
41412199Sgerald.jelinek@sun.com
41512199Sgerald.jelinek@sun.com		#
41612199Sgerald.jelinek@sun.com		# Save identification section to a file so we can determine
41712199Sgerald.jelinek@sun.com		# how to unpack the archive.
41812199Sgerald.jelinek@sun.com		#
41912199Sgerald.jelinek@sun.com		if [[ "$section_name" == "identification" ]]; then
42012199Sgerald.jelinek@sun.com			/usr/bin/rm -f identification
42112199Sgerald.jelinek@sun.com			while read -r input_line
42212199Sgerald.jelinek@sun.com			do
42312199Sgerald.jelinek@sun.com				if [[ ${input_line%%=*} == \
42412199Sgerald.jelinek@sun.com				    "section_begin" ]]; then
42512199Sgerald.jelinek@sun.com					/usr/bin/rm -f identification
42612199Sgerald.jelinek@sun.com					log "$bad_flar"
42712199Sgerald.jelinek@sun.com					return 1
42812199Sgerald.jelinek@sun.com				fi
42912199Sgerald.jelinek@sun.com
43012199Sgerald.jelinek@sun.com				if [[ $input_line == \
43112199Sgerald.jelinek@sun.com				    "section_end=$section_name" ]]; then
43212199Sgerald.jelinek@sun.com					break;
43312199Sgerald.jelinek@sun.com				fi
43412199Sgerald.jelinek@sun.com				echo $input_line >> identification
43512199Sgerald.jelinek@sun.com			done
43612199Sgerald.jelinek@sun.com
43712199Sgerald.jelinek@sun.com			continue
43812199Sgerald.jelinek@sun.com		fi
43912199Sgerald.jelinek@sun.com
44012199Sgerald.jelinek@sun.com		#
44112199Sgerald.jelinek@sun.com		# Otherwise skip past this section; read lines until detecting
44212199Sgerald.jelinek@sun.com		# section_end.  According to flash_archive(4) we can have
44312199Sgerald.jelinek@sun.com		# an arbitrary number of sections but the archive section
44412199Sgerald.jelinek@sun.com		# must be last.
44512199Sgerald.jelinek@sun.com		#
44612199Sgerald.jelinek@sun.com		success=0
44712199Sgerald.jelinek@sun.com		while read -r input_line
44812199Sgerald.jelinek@sun.com		do
44912199Sgerald.jelinek@sun.com			if [[ $input_line == "section_end=$section_name" ]];
45012199Sgerald.jelinek@sun.com			then
45112199Sgerald.jelinek@sun.com				success=1
45212199Sgerald.jelinek@sun.com				break
45312199Sgerald.jelinek@sun.com			fi
45412199Sgerald.jelinek@sun.com			# Fail if we miss the end of the section
45512199Sgerald.jelinek@sun.com			if [[ ${input_line%%=*} == "section_begin" ]]; then
45612199Sgerald.jelinek@sun.com				/usr/bin/rm -f identification
45712199Sgerald.jelinek@sun.com				log "$bad_flar"
45812199Sgerald.jelinek@sun.com				return 1
45912199Sgerald.jelinek@sun.com			fi
46012199Sgerald.jelinek@sun.com		done
46112199Sgerald.jelinek@sun.com		if (( $success == 0 )); then
46212199Sgerald.jelinek@sun.com			#
46312199Sgerald.jelinek@sun.com			# If we get here we read to the end of the file before
46412199Sgerald.jelinek@sun.com			# seeing the end of the section we were reading.
46512199Sgerald.jelinek@sun.com			#
46612199Sgerald.jelinek@sun.com			/usr/bin/rm -f identification
46712199Sgerald.jelinek@sun.com			log "$bad_flar"
46812199Sgerald.jelinek@sun.com			return 1
46912199Sgerald.jelinek@sun.com		fi
47012199Sgerald.jelinek@sun.com	done
47112199Sgerald.jelinek@sun.com
47212199Sgerald.jelinek@sun.com	# Check for an archive made from a ZFS root pool.
47312199Sgerald.jelinek@sun.com	egrep -s "^rootpool=" identification
47412199Sgerald.jelinek@sun.com        if (( $? == 0 )); then
47512199Sgerald.jelinek@sun.com		/usr/bin/rm -f identification
47612199Sgerald.jelinek@sun.com                log "$bad_zfs_flar"
47712199Sgerald.jelinek@sun.com                return 1
47812199Sgerald.jelinek@sun.com        fi
47912199Sgerald.jelinek@sun.com
48012199Sgerald.jelinek@sun.com	# Get the information needed to unpack the archive.
48112199Sgerald.jelinek@sun.com	archiver=$(get_archiver identification)
48212199Sgerald.jelinek@sun.com	if [[ $archiver == "pax" ]]; then
48312199Sgerald.jelinek@sun.com		# pax archiver specified
48412199Sgerald.jelinek@sun.com		archiver_command="/usr/bin/pax"
48512734Sgary.pennington@oracle.com		if [[ -s $fspaxfile ]]; then
48612199Sgerald.jelinek@sun.com			archiver_arguments="-r -p e -c \
48712734Sgary.pennington@oracle.com			    $(/usr/bin/cat $fspaxfile)"
48812199Sgerald.jelinek@sun.com		else
48912199Sgerald.jelinek@sun.com			archiver_arguments="-r -p e"
49012199Sgerald.jelinek@sun.com		fi
49112199Sgerald.jelinek@sun.com	elif [[ $archiver == "cpio" || -z $archiver ]]; then
49212199Sgerald.jelinek@sun.com		# cpio archived specified OR no archiver specified - use default
49312199Sgerald.jelinek@sun.com		archiver_command="/usr/bin/cpio"
49412734Sgary.pennington@oracle.com		archiver_arguments="-icdumfE $fscpiofile"
49512199Sgerald.jelinek@sun.com	else
49612199Sgerald.jelinek@sun.com		# unknown archiver specified
49712199Sgerald.jelinek@sun.com		log "$unknown_archiver" $archiver
49812199Sgerald.jelinek@sun.com		return 1
49912199Sgerald.jelinek@sun.com	fi
50012199Sgerald.jelinek@sun.com
50112199Sgerald.jelinek@sun.com	if [[ ! -x $archiver_command ]]; then
50212199Sgerald.jelinek@sun.com		/usr/bin/rm -f identification
50312199Sgerald.jelinek@sun.com		log "$cmd_not_exec" $archiver_command
50412199Sgerald.jelinek@sun.com		return 1
50512199Sgerald.jelinek@sun.com	fi
50612199Sgerald.jelinek@sun.com
50712199Sgerald.jelinek@sun.com	compression=$(get_compression identification)
50812199Sgerald.jelinek@sun.com
50912199Sgerald.jelinek@sun.com	# We're done with the identification file
51012199Sgerald.jelinek@sun.com	/usr/bin/rm -f identification
51112199Sgerald.jelinek@sun.com
51212199Sgerald.jelinek@sun.com	# Extract archive
51312199Sgerald.jelinek@sun.com	if [[ $compression == "compress" ]]; then
51412199Sgerald.jelinek@sun.com		/usr/bin/zcat | \
51512199Sgerald.jelinek@sun.com		    $archiver_command $archiver_arguments 2>/dev/null
51612199Sgerald.jelinek@sun.com	else
51712199Sgerald.jelinek@sun.com		$archiver_command $archiver_arguments 2>/dev/null
51812199Sgerald.jelinek@sun.com	fi
51912199Sgerald.jelinek@sun.com	result=$?
52012199Sgerald.jelinek@sun.com
52112199Sgerald.jelinek@sun.com	post_unpack
52212199Sgerald.jelinek@sun.com
52312199Sgerald.jelinek@sun.com	(( $result != 0 )) && return 1
52412199Sgerald.jelinek@sun.com
52512199Sgerald.jelinek@sun.com	return 0
52612199Sgerald.jelinek@sun.com}
52712199Sgerald.jelinek@sun.com
52812199Sgerald.jelinek@sun.com#
52912199Sgerald.jelinek@sun.com# Get the archive base.
53012199Sgerald.jelinek@sun.com#
53112199Sgerald.jelinek@sun.com# We must unpack the archive in the right place within the zonepath so
53212199Sgerald.jelinek@sun.com# that files are installed into the various mounted filesystems that are set
53312199Sgerald.jelinek@sun.com# up in the zone's configuration.  These are already mounted for us by the
53412199Sgerald.jelinek@sun.com# mntfs function.
53512199Sgerald.jelinek@sun.com#
53612199Sgerald.jelinek@sun.com# Archives can be made of either a physical host's root file system or a
53712199Sgerald.jelinek@sun.com# zone's zonepath.  For a physical system, if the archive is made using an
53812199Sgerald.jelinek@sun.com# absolute path (/...) we can't use it.  For a zone the admin can make the
53912199Sgerald.jelinek@sun.com# archive from a variety of locations;
54012199Sgerald.jelinek@sun.com#
54112199Sgerald.jelinek@sun.com#   a) zonepath itself: This will be a single dir, probably named with the
54212199Sgerald.jelinek@sun.com#      zone name, it will contain a root dir and under the root we'll see all
54312199Sgerald.jelinek@sun.com#      the top level dirs; etc, var, usr...  We must be above the ZONEPATH
54412199Sgerald.jelinek@sun.com#      when we unpack the archive but this will only work if the the archive's
54512199Sgerald.jelinek@sun.com#      top-level dir name matches the ZONEPATH base-level dir name.  If not,
54612199Sgerald.jelinek@sun.com#      this is an error.
54712199Sgerald.jelinek@sun.com#
54812199Sgerald.jelinek@sun.com#   b) inside the zonepath: We'll see root and it will contain all the top
54912199Sgerald.jelinek@sun.com#      level dirs; etc, var, usr....  We must be in the ZONEPATH when we unpack
55012199Sgerald.jelinek@sun.com#      the archive.
55112199Sgerald.jelinek@sun.com#
55212199Sgerald.jelinek@sun.com#   c) inside the zonepath root: We'll see all the top level dirs, ./etc,
55312199Sgerald.jelinek@sun.com#      ./var, ./usr....  This is also the case we see when we get an archive
55412199Sgerald.jelinek@sun.com#      of a physical sytem.  We must be in ZONEROOT when we unpack the archive.
55512199Sgerald.jelinek@sun.com#
55612199Sgerald.jelinek@sun.com# Note that there can be a directory named "root" under the ZONEPATH/root
55712199Sgerald.jelinek@sun.com# directory.
55812199Sgerald.jelinek@sun.com#
55912199Sgerald.jelinek@sun.com# This function handles the above possibilities so that we reject absolute
56012199Sgerald.jelinek@sun.com# path archives and figure out where in the file system we need to be to
56112199Sgerald.jelinek@sun.com# properly unpack the archive into the zone.  It sets the ARCHIVE_BASE
56212199Sgerald.jelinek@sun.com# variable to the location where the achive should be unpacked.
56312199Sgerald.jelinek@sun.com#
56412199Sgerald.jelinek@sun.comget_archive_base()
56512199Sgerald.jelinek@sun.com{
56612199Sgerald.jelinek@sun.com	stage1=$1
56712199Sgerald.jelinek@sun.com	archive=$2
56812199Sgerald.jelinek@sun.com	stage2=$3
56912199Sgerald.jelinek@sun.com
57012199Sgerald.jelinek@sun.com	vlog "$m_analyse_archive"
57112199Sgerald.jelinek@sun.com
57212199Sgerald.jelinek@sun.com	base=`$stage1 $archive | $stage2 2>/dev/null | nawk -F/ '{
57312199Sgerald.jelinek@sun.com		# Check for an absolute path archive
57412199Sgerald.jelinek@sun.com		if (substr($0, 1, 1) == "/")
57512199Sgerald.jelinek@sun.com			exit 1
57612199Sgerald.jelinek@sun.com
57712199Sgerald.jelinek@sun.com		if ($1 != ".")
57812199Sgerald.jelinek@sun.com			dirs[$1] = 1
57912199Sgerald.jelinek@sun.com		else
58012199Sgerald.jelinek@sun.com			dirs[$2] = 1
58112199Sgerald.jelinek@sun.com	}
58212199Sgerald.jelinek@sun.com	END {
58312199Sgerald.jelinek@sun.com		for (d in dirs) {
58412199Sgerald.jelinek@sun.com			cnt++
58512199Sgerald.jelinek@sun.com			if (d == "bin")  sawbin = 1
58612199Sgerald.jelinek@sun.com			if (d == "etc")  sawetc = 1
58712199Sgerald.jelinek@sun.com			if (d == "root") sawroot = 1
58812199Sgerald.jelinek@sun.com			if (d == "var")  sawvar = 1
58912199Sgerald.jelinek@sun.com                }
59012199Sgerald.jelinek@sun.com
59112199Sgerald.jelinek@sun.com		if (cnt == 1) {
59212199Sgerald.jelinek@sun.com			# If only one top-level dir named root, we are in the
59312199Sgerald.jelinek@sun.com			# zonepath, otherwise this must be an archive *of*
59412199Sgerald.jelinek@sun.com			# the zonepath so print the top-level dir name.
59512199Sgerald.jelinek@sun.com			if (sawroot)
59612199Sgerald.jelinek@sun.com				print "*zonepath*"
59712199Sgerald.jelinek@sun.com			else
59812199Sgerald.jelinek@sun.com				for (d in dirs) print d
59912199Sgerald.jelinek@sun.com		} else {
60012199Sgerald.jelinek@sun.com			# We are either in the zonepath or in the zonepath/root
60112199Sgerald.jelinek@sun.com			# (or at the top level of a full system archive which
60212199Sgerald.jelinek@sun.com			# looks like the zonepath/root case).  Figure out which
60312199Sgerald.jelinek@sun.com			# one.
60412199Sgerald.jelinek@sun.com			if (sawroot && !sawbin && !sawetc && !sawvar)
60512199Sgerald.jelinek@sun.com				print "*zonepath*"
60612199Sgerald.jelinek@sun.com			else
60712199Sgerald.jelinek@sun.com				print "*zoneroot*"
60812199Sgerald.jelinek@sun.com		}
60912199Sgerald.jelinek@sun.com	}'`
61012199Sgerald.jelinek@sun.com
61112199Sgerald.jelinek@sun.com	if (( $? != 0 )); then
61212199Sgerald.jelinek@sun.com		umnt_fs
61312199Sgerald.jelinek@sun.com		fatal "$e_absolute_archive"
61412199Sgerald.jelinek@sun.com	fi
61512199Sgerald.jelinek@sun.com
61612199Sgerald.jelinek@sun.com	if [[ "$base" == "*zoneroot*" ]]; then
61712199Sgerald.jelinek@sun.com		ARCHIVE_BASE=$ZONEROOT
61812199Sgerald.jelinek@sun.com	elif [[ "$base" == "*zonepath*" ]]; then
61912199Sgerald.jelinek@sun.com		ARCHIVE_BASE=$ZONEPATH
62012199Sgerald.jelinek@sun.com	else
62112199Sgerald.jelinek@sun.com		# We need to be in the dir above the ZONEPATH but we need to
62212199Sgerald.jelinek@sun.com		# validate that $base matches the final component of ZONEPATH.
62312199Sgerald.jelinek@sun.com		bname=`basename $ZONEPATH`
62412199Sgerald.jelinek@sun.com
62512199Sgerald.jelinek@sun.com		if [[ "$bname" != "$base" ]]; then
62612199Sgerald.jelinek@sun.com			umnt_fs
62712199Sgerald.jelinek@sun.com			fatal "$e_mismatch_archive" "$base" "$bname"
62812199Sgerald.jelinek@sun.com		fi
62912199Sgerald.jelinek@sun.com		ARCHIVE_BASE=`dirname $ZONEPATH`
63012199Sgerald.jelinek@sun.com	fi
63112199Sgerald.jelinek@sun.com}
63212199Sgerald.jelinek@sun.com
63312199Sgerald.jelinek@sun.com#
63412199Sgerald.jelinek@sun.com# Unpack cpio archive into zoneroot.
63512199Sgerald.jelinek@sun.com#
63612199Sgerald.jelinek@sun.cominstall_cpio()
63712199Sgerald.jelinek@sun.com{
63812199Sgerald.jelinek@sun.com	stage1=$1
63912199Sgerald.jelinek@sun.com	archive=$2
64012199Sgerald.jelinek@sun.com
64112199Sgerald.jelinek@sun.com	get_archive_base "$stage1" "$archive" "cpio -it"
64212199Sgerald.jelinek@sun.com
64312734Sgary.pennington@oracle.com	cpioopts="-idmfE $fscpiofile"
64412199Sgerald.jelinek@sun.com
64512199Sgerald.jelinek@sun.com	vlog "cd \"$ARCHIVE_BASE\" && $stage1 \"$archive\" | cpio $cpioopts"
64612199Sgerald.jelinek@sun.com
64712199Sgerald.jelinek@sun.com	# Ignore errors from cpio since we expect some errors depending on
64812199Sgerald.jelinek@sun.com	# how the archive was made.
64912199Sgerald.jelinek@sun.com	( cd "$ARCHIVE_BASE" && $stage1 "$archive" | cpio $cpioopts )
65012199Sgerald.jelinek@sun.com
65112199Sgerald.jelinek@sun.com	post_unpack
65212199Sgerald.jelinek@sun.com
65312199Sgerald.jelinek@sun.com	return 0
65412199Sgerald.jelinek@sun.com}
65512199Sgerald.jelinek@sun.com
65612199Sgerald.jelinek@sun.com#
65712199Sgerald.jelinek@sun.com# Unpack pax archive into zoneroot.
65812199Sgerald.jelinek@sun.com#
65912199Sgerald.jelinek@sun.cominstall_pax()
66012199Sgerald.jelinek@sun.com{
66112199Sgerald.jelinek@sun.com	archive=$1
66212199Sgerald.jelinek@sun.com
66312199Sgerald.jelinek@sun.com	get_archive_base "cat" "$archive" "pax"
66412199Sgerald.jelinek@sun.com
66512734Sgary.pennington@oracle.com	if [[ -s $fspaxfile ]]; then
66612734Sgary.pennington@oracle.com		filtopt="-c $(/usr/bin/cat $fspaxfile)"
66712199Sgerald.jelinek@sun.com	fi
66812199Sgerald.jelinek@sun.com
66912199Sgerald.jelinek@sun.com	vlog "cd \"$ARCHIVE_BASE\" && pax -r -f \"$archive\" $filtopt"
67012199Sgerald.jelinek@sun.com
67112199Sgerald.jelinek@sun.com	# Ignore errors from pax since we expect some errors depending on
67212199Sgerald.jelinek@sun.com	# how the archive was made.
67312199Sgerald.jelinek@sun.com	( cd "$ARCHIVE_BASE" && pax -r -f "$archive" $filtopt )
67412199Sgerald.jelinek@sun.com
67512199Sgerald.jelinek@sun.com	post_unpack
67612199Sgerald.jelinek@sun.com
67712199Sgerald.jelinek@sun.com	return 0
67812199Sgerald.jelinek@sun.com}
67912199Sgerald.jelinek@sun.com
68012199Sgerald.jelinek@sun.com#
68112199Sgerald.jelinek@sun.com# Unpack UFS dump into zoneroot.
68212199Sgerald.jelinek@sun.com#
68312199Sgerald.jelinek@sun.cominstall_ufsdump()
68412199Sgerald.jelinek@sun.com{
68512199Sgerald.jelinek@sun.com	archive=$1
68612199Sgerald.jelinek@sun.com
68712199Sgerald.jelinek@sun.com	vlog "cd \"$ZONEROOT\" && ufsrestore rf \"$archive\""
68812199Sgerald.jelinek@sun.com
68912199Sgerald.jelinek@sun.com	#
69012199Sgerald.jelinek@sun.com	# ufsrestore goes interactive if you ^C it.  To prevent that,
69112199Sgerald.jelinek@sun.com	# we make sure its stdin is not a terminal.
69212199Sgerald.jelinek@sun.com	#
69312199Sgerald.jelinek@sun.com	( cd "$ZONEROOT" && ufsrestore rf "$archive" < /dev/null )
69412199Sgerald.jelinek@sun.com	result=$?
69512199Sgerald.jelinek@sun.com
69612199Sgerald.jelinek@sun.com	post_unpack
69712199Sgerald.jelinek@sun.com
69812199Sgerald.jelinek@sun.com	return $result
69912199Sgerald.jelinek@sun.com}
70012199Sgerald.jelinek@sun.com
70112199Sgerald.jelinek@sun.com#
70212199Sgerald.jelinek@sun.com# Copy directory hierarchy into zoneroot.
70312199Sgerald.jelinek@sun.com#
70412199Sgerald.jelinek@sun.cominstall_dir()
70512199Sgerald.jelinek@sun.com{
70612199Sgerald.jelinek@sun.com	source_dir=$1
70712199Sgerald.jelinek@sun.com
70812199Sgerald.jelinek@sun.com	cpioopts="-pdm"
70912199Sgerald.jelinek@sun.com
71012199Sgerald.jelinek@sun.com	first=1
71112734Sgary.pennington@oracle.com	filt=$(for i in $(cat $fspaxfile)
71212199Sgerald.jelinek@sun.com		do
71312199Sgerald.jelinek@sun.com			echo $i | egrep -s "/" && continue
71412199Sgerald.jelinek@sun.com			if [[ $first == 1 ]]; then
71512199Sgerald.jelinek@sun.com				printf "^%s" $i
71612199Sgerald.jelinek@sun.com				first=0
71712199Sgerald.jelinek@sun.com			else
71812199Sgerald.jelinek@sun.com				printf "|^%s" $i
71912199Sgerald.jelinek@sun.com			fi
72012199Sgerald.jelinek@sun.com		done)
72112199Sgerald.jelinek@sun.com
72212199Sgerald.jelinek@sun.com	list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
72312199Sgerald.jelinek@sun.com	flist=$(for i in $list
72412199Sgerald.jelinek@sun.com	do
72512199Sgerald.jelinek@sun.com		printf "%s " "$i"
72612199Sgerald.jelinek@sun.com	done)
72712199Sgerald.jelinek@sun.com	findopts="-xdev ( -type d -o -type f -o -type l ) -print"
72812199Sgerald.jelinek@sun.com
72912199Sgerald.jelinek@sun.com	vlog "cd \"$source_dir\" && find $flist $findopts | "
73012199Sgerald.jelinek@sun.com	vlog "cpio $cpioopts \"$ZONEROOT\""
73112199Sgerald.jelinek@sun.com
73212199Sgerald.jelinek@sun.com	# Ignore errors from cpio since we expect some errors depending on
73312199Sgerald.jelinek@sun.com	# how the archive was made.
73412199Sgerald.jelinek@sun.com	( cd "$source_dir" && find $flist $findopts | \
73512199Sgerald.jelinek@sun.com	    cpio $cpioopts "$ZONEROOT" )
73612199Sgerald.jelinek@sun.com
73712199Sgerald.jelinek@sun.com	post_unpack
73812199Sgerald.jelinek@sun.com
73912199Sgerald.jelinek@sun.com	return 0
74012199Sgerald.jelinek@sun.com}
74112199Sgerald.jelinek@sun.com
74212199Sgerald.jelinek@sun.com#
74312199Sgerald.jelinek@sun.com# This is a common function for laying down a zone image from a variety of
74412199Sgerald.jelinek@sun.com# different sources.  This can be used to either install a fresh zone or as
74512199Sgerald.jelinek@sun.com# part of zone migration during attach.
74612199Sgerald.jelinek@sun.com#
74712199Sgerald.jelinek@sun.com# The first argument specifies the type of image: archive, directory or stdin.
74812199Sgerald.jelinek@sun.com# The second argument specifies the image itself.  In the case of stdin, the
74912199Sgerald.jelinek@sun.com# second argument specifies the format of the stream (cpio, flar, etc.).
75012199Sgerald.jelinek@sun.com# Any validation or post-processing on the image is done elsewhere.
75112199Sgerald.jelinek@sun.com#
75212199Sgerald.jelinek@sun.com# This function calls a 'sanity_check' function which must be provided by
75312199Sgerald.jelinek@sun.com# the script which includes this code.
75412199Sgerald.jelinek@sun.com#
75512199Sgerald.jelinek@sun.cominstall_image()
75612199Sgerald.jelinek@sun.com{
75712199Sgerald.jelinek@sun.com	intype=$1
75812199Sgerald.jelinek@sun.com	insrc=$2
75912199Sgerald.jelinek@sun.com
76012199Sgerald.jelinek@sun.com	if [[ -z "$intype" || -z "$insrc" ]]; then
76112199Sgerald.jelinek@sun.com		return 1
76212199Sgerald.jelinek@sun.com	fi
76312199Sgerald.jelinek@sun.com
76412199Sgerald.jelinek@sun.com	filetype="unknown"
76512199Sgerald.jelinek@sun.com	filetypename="unknown"
76612199Sgerald.jelinek@sun.com	stage1="cat"
76712199Sgerald.jelinek@sun.com
76812199Sgerald.jelinek@sun.com	if [[ "$intype" == "directory" ]]; then
76912199Sgerald.jelinek@sun.com		if [[ "$insrc" == "-" ]]; then
77012199Sgerald.jelinek@sun.com			# Indicates that the existing zonepath is prepopulated.
77112199Sgerald.jelinek@sun.com			filetype="existing"
77212199Sgerald.jelinek@sun.com			filetypename="existing"
77312199Sgerald.jelinek@sun.com		else
77412199Sgerald.jelinek@sun.com			if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then
77512199Sgerald.jelinek@sun.com				fatal "$e_path_abs" "$insrc"
77612199Sgerald.jelinek@sun.com			fi
77712199Sgerald.jelinek@sun.com
77812199Sgerald.jelinek@sun.com			if [[ ! -e "$insrc" ]]; then
77912199Sgerald.jelinek@sun.com				log "$e_not_found" "$insrc"
78012199Sgerald.jelinek@sun.com				fatal "$e_install_abort"
78112199Sgerald.jelinek@sun.com			fi
78212199Sgerald.jelinek@sun.com
78312199Sgerald.jelinek@sun.com			if [[ ! -r "$insrc" ]]; then
78412199Sgerald.jelinek@sun.com				log "$e_not_readable" "$insrc"
78512199Sgerald.jelinek@sun.com				fatal "$e_install_abort"
78612199Sgerald.jelinek@sun.com			fi
78712199Sgerald.jelinek@sun.com
78812199Sgerald.jelinek@sun.com			if [[ ! -d "$insrc" ]]; then
78912199Sgerald.jelinek@sun.com				log "$e_not_dir"
79012199Sgerald.jelinek@sun.com				fatal "$e_install_abort"
79112199Sgerald.jelinek@sun.com			fi
79212199Sgerald.jelinek@sun.com
79312199Sgerald.jelinek@sun.com			sanity_check $insrc
79412199Sgerald.jelinek@sun.com
79512199Sgerald.jelinek@sun.com			filetype="directory"
79612199Sgerald.jelinek@sun.com			filetypename="directory"
79712199Sgerald.jelinek@sun.com		fi
79812199Sgerald.jelinek@sun.com
79912199Sgerald.jelinek@sun.com	else
80012199Sgerald.jelinek@sun.com		# Common code for both archive and stdin stream.
80112199Sgerald.jelinek@sun.com
80212199Sgerald.jelinek@sun.com		if [[ "$intype" == "archive" ]]; then
80312199Sgerald.jelinek@sun.com			if [[ ! -f "$insrc" ]]; then
80412199Sgerald.jelinek@sun.com				log "$e_unknown_archive"
80512199Sgerald.jelinek@sun.com				fatal "$e_install_abort"
80612199Sgerald.jelinek@sun.com			fi
80712199Sgerald.jelinek@sun.com			ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)"
80812199Sgerald.jelinek@sun.com		else
80912199Sgerald.jelinek@sun.com			# For intype == stdin, the insrc parameter specifies
81012199Sgerald.jelinek@sun.com			# the stream format coming on stdin.
81112199Sgerald.jelinek@sun.com			ftype="$insrc"
81212199Sgerald.jelinek@sun.com			insrc="-"
81312199Sgerald.jelinek@sun.com		fi
81412199Sgerald.jelinek@sun.com
81512199Sgerald.jelinek@sun.com		# Setup vars for the archive type we have.
81612199Sgerald.jelinek@sun.com		case "$ftype" in
81712199Sgerald.jelinek@sun.com		*cpio*)		filetype="cpio"
81812199Sgerald.jelinek@sun.com				filetypename="cpio archive"
81912199Sgerald.jelinek@sun.com			;;
82012199Sgerald.jelinek@sun.com		*bzip2*)	filetype="bzip2"
82112199Sgerald.jelinek@sun.com				filetypename="bzipped cpio archive"
82212199Sgerald.jelinek@sun.com			;;
82312199Sgerald.jelinek@sun.com		*gzip*)		filetype="gzip"
82412199Sgerald.jelinek@sun.com				filetypename="gzipped cpio archive"
82512199Sgerald.jelinek@sun.com			;;
82612199Sgerald.jelinek@sun.com		*ufsdump*)	filetype="ufsdump"
82712199Sgerald.jelinek@sun.com				filetypename="ufsdump archive"
82812199Sgerald.jelinek@sun.com			;;
82912199Sgerald.jelinek@sun.com		"flar")
83012199Sgerald.jelinek@sun.com				filetype="flar"
83112199Sgerald.jelinek@sun.com				filetypename="flash archive"
83212199Sgerald.jelinek@sun.com			;;
83312199Sgerald.jelinek@sun.com		"flash")
83412199Sgerald.jelinek@sun.com				filetype="flar"
83512199Sgerald.jelinek@sun.com				filetypename="flash archive"
83612199Sgerald.jelinek@sun.com			;;
83712199Sgerald.jelinek@sun.com		*Flash\ Archive*)
83812199Sgerald.jelinek@sun.com				filetype="flar"
83912199Sgerald.jelinek@sun.com				filetypename="flash archive"
84012199Sgerald.jelinek@sun.com			;;
84112199Sgerald.jelinek@sun.com		"tar")
84212199Sgerald.jelinek@sun.com				filetype="tar"
84312199Sgerald.jelinek@sun.com				filetypename="tar archive"
84412199Sgerald.jelinek@sun.com			;;
84512199Sgerald.jelinek@sun.com		*USTAR\ tar\ archive)
84612199Sgerald.jelinek@sun.com				filetype="tar"
84712199Sgerald.jelinek@sun.com				filetypename="tar archive"
84812199Sgerald.jelinek@sun.com			;;
84912199Sgerald.jelinek@sun.com		"pax")
85012199Sgerald.jelinek@sun.com				filetype="xustar"
85112199Sgerald.jelinek@sun.com				filetypename="pax (xustar) archive"
85212199Sgerald.jelinek@sun.com			;;
85312199Sgerald.jelinek@sun.com		*USTAR\ tar\ archive\ extended\ format*)
85412199Sgerald.jelinek@sun.com				filetype="xustar"
85512199Sgerald.jelinek@sun.com				filetypename="pax (xustar) archive"
85612199Sgerald.jelinek@sun.com			;;
85712199Sgerald.jelinek@sun.com		"zfs")
85812199Sgerald.jelinek@sun.com				filetype="zfs"
85912199Sgerald.jelinek@sun.com				filetypename="ZFS send stream"
86012199Sgerald.jelinek@sun.com			;;
86112199Sgerald.jelinek@sun.com		*ZFS\ snapshot\ stream*)
86212199Sgerald.jelinek@sun.com				filetype="zfs"
86312199Sgerald.jelinek@sun.com				filetypename="ZFS send stream"
86412199Sgerald.jelinek@sun.com			;;
86512199Sgerald.jelinek@sun.com		*)		log "$e_unknown_archive"
86612199Sgerald.jelinek@sun.com				fatal "$e_install_abort"
86712199Sgerald.jelinek@sun.com			;;
86812199Sgerald.jelinek@sun.com		esac
86912199Sgerald.jelinek@sun.com	fi
87012199Sgerald.jelinek@sun.com
87112199Sgerald.jelinek@sun.com	vlog "$filetypename"
87212199Sgerald.jelinek@sun.com
87312199Sgerald.jelinek@sun.com	# Check for a non-empty root if no '-d -' option.
87412199Sgerald.jelinek@sun.com	if [[ "$filetype" != "existing" ]]; then
87512199Sgerald.jelinek@sun.com		cnt=$(ls $ZONEROOT | wc -l)
87612199Sgerald.jelinek@sun.com		if (( $cnt != 0 )); then
87712199Sgerald.jelinek@sun.com			fatal "$e_root_full" "$ZONEROOT"
87812199Sgerald.jelinek@sun.com		fi
87912199Sgerald.jelinek@sun.com	fi
88012199Sgerald.jelinek@sun.com
88112199Sgerald.jelinek@sun.com	fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
88212199Sgerald.jelinek@sun.com	if [[ -z "$fstmpfile" ]]; then
88312199Sgerald.jelinek@sun.com		fatal "$e_tmpfile"
88412199Sgerald.jelinek@sun.com	fi
88512199Sgerald.jelinek@sun.com
88612199Sgerald.jelinek@sun.com	# Make sure we always have the files holding the directories to filter
88712199Sgerald.jelinek@sun.com	# out when extracting from a CPIO or PAX archive.  We'll add the fs
88812734Sgary.pennington@oracle.com	# entries to these files in get_fs_info()
88912734Sgary.pennington@oracle.com	fscpiofile=$(/usr/bin/mktemp -t -p /var/tmp fs.cpio.XXXXXX)
89012734Sgary.pennington@oracle.com	if [[ -z "$fscpiofile" ]]; then
89112199Sgerald.jelinek@sun.com		rm -f $fstmpfile
89212199Sgerald.jelinek@sun.com		fatal "$e_tmpfile"
89312199Sgerald.jelinek@sun.com	fi
89412199Sgerald.jelinek@sun.com
89512734Sgary.pennington@oracle.com	# Filter out these directories.
89612734Sgary.pennington@oracle.com	echo 'dev/*' >>$fscpiofile
89712734Sgary.pennington@oracle.com	echo 'devices/*' >>$fscpiofile
89812734Sgary.pennington@oracle.com	echo 'devices' >>$fscpiofile
89912734Sgary.pennington@oracle.com	echo 'proc/*' >>$fscpiofile
90012734Sgary.pennington@oracle.com	echo 'tmp/*' >>$fscpiofile
90112734Sgary.pennington@oracle.com	echo 'var/run/*' >>$fscpiofile
90212734Sgary.pennington@oracle.com	echo 'system/contract/*' >>$fscpiofile
90312734Sgary.pennington@oracle.com	echo 'system/object/*' >>$fscpiofile
90412199Sgerald.jelinek@sun.com
90512734Sgary.pennington@oracle.com	fspaxfile=$(/usr/bin/mktemp -t -p /var/tmp fs.pax.XXXXXX)
90612734Sgary.pennington@oracle.com	if [[ -z "$fspaxfile" ]]; then
90712734Sgary.pennington@oracle.com		rm -f $fstmpfile $fscpiofile
90812199Sgerald.jelinek@sun.com		fatal "$e_tmpfile"
90912199Sgerald.jelinek@sun.com	fi
91012199Sgerald.jelinek@sun.com
91112199Sgerald.jelinek@sun.com	printf "%s " \
91212199Sgerald.jelinek@sun.com	    "dev devices proc tmp var/run system/contract system/object" \
91312734Sgary.pennington@oracle.com	    >>$fspaxfile
91412199Sgerald.jelinek@sun.com
91512199Sgerald.jelinek@sun.com	# Set up any fs mounts so the archive will install into the correct
91612199Sgerald.jelinek@sun.com	# locations.
91712199Sgerald.jelinek@sun.com	get_fs_info
91812199Sgerald.jelinek@sun.com	mnt_fs
91912199Sgerald.jelinek@sun.com	if (( $? != 0 )); then
92012199Sgerald.jelinek@sun.com		umnt_fs >/dev/null 2>&1
92112734Sgary.pennington@oracle.com		rm -f $fstmpfile $fscpiofile $fspaxfile
92212199Sgerald.jelinek@sun.com		fatal "$mount_failed"
92312199Sgerald.jelinek@sun.com	fi
92412199Sgerald.jelinek@sun.com
92512199Sgerald.jelinek@sun.com	if [[ "$filetype" == "existing" ]]; then
92612199Sgerald.jelinek@sun.com		log "$no_installing"
92712199Sgerald.jelinek@sun.com	else
92812199Sgerald.jelinek@sun.com		log "$installing"
92912199Sgerald.jelinek@sun.com	fi
93012199Sgerald.jelinek@sun.com
93112199Sgerald.jelinek@sun.com	#
93212199Sgerald.jelinek@sun.com	# Install the image into the zonepath.
93312199Sgerald.jelinek@sun.com	#
93412199Sgerald.jelinek@sun.com	unpack_result=0
93512199Sgerald.jelinek@sun.com	stage1="cat"
93612199Sgerald.jelinek@sun.com	if [[ "$filetype" == "gzip" ]]; then
93712199Sgerald.jelinek@sun.com		stage1="gzcat"
93812199Sgerald.jelinek@sun.com		filetype="cpio"
93912199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "bzip2" ]]; then
94012199Sgerald.jelinek@sun.com		stage1="bzcat"
94112199Sgerald.jelinek@sun.com		filetype="cpio"
94212199Sgerald.jelinek@sun.com	fi
94312199Sgerald.jelinek@sun.com
94412199Sgerald.jelinek@sun.com	if [[ "$filetype" == "cpio" ]]; then
94512199Sgerald.jelinek@sun.com		install_cpio "$stage1" "$insrc"
94612199Sgerald.jelinek@sun.com		unpack_result=$?
94712199Sgerald.jelinek@sun.com
94812199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "flar" ]]; then
94912199Sgerald.jelinek@sun.com		( cd "$ZONEROOT" && $stage1 $insrc | install_flar )
95012199Sgerald.jelinek@sun.com		unpack_result=$?
95112199Sgerald.jelinek@sun.com
95212199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "xustar" ]]; then
95312199Sgerald.jelinek@sun.com		install_pax "$insrc"
95412199Sgerald.jelinek@sun.com		unpack_result=$?
95512199Sgerald.jelinek@sun.com
95612199Sgerald.jelinek@sun.com	elif [[ "$filetype" = "tar" ]]; then
95712199Sgerald.jelinek@sun.com		vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\""
95812199Sgerald.jelinek@sun.com		# Ignore errors from tar since we expect some errors depending
95912199Sgerald.jelinek@sun.com		# on how the archive was made.
96012199Sgerald.jelinek@sun.com		( cd "$ZONEROOT" && tar -xf "$insrc" )
96112199Sgerald.jelinek@sun.com		unpack_result=0
96212199Sgerald.jelinek@sun.com		post_unpack
96312199Sgerald.jelinek@sun.com
96412199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "ufsdump" ]]; then
96512199Sgerald.jelinek@sun.com		install_ufsdump "$insrc"
96612199Sgerald.jelinek@sun.com		unpack_result=$?
96712199Sgerald.jelinek@sun.com
96812199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "directory" ]]; then
96912199Sgerald.jelinek@sun.com		install_dir "$insrc"
97012199Sgerald.jelinek@sun.com		unpack_result=$?
97112199Sgerald.jelinek@sun.com
97212199Sgerald.jelinek@sun.com	elif [[ "$filetype" == "zfs" ]]; then
97312199Sgerald.jelinek@sun.com		#
97412199Sgerald.jelinek@sun.com		# Given a 'zfs send' stream file, receive the snapshot into
97512199Sgerald.jelinek@sun.com		# the zone's dataset.  We're getting the original system's
97612199Sgerald.jelinek@sun.com		# zonepath dataset.  Destroy the existing dataset created
97712199Sgerald.jelinek@sun.com		# above since this recreates it.
97812199Sgerald.jelinek@sun.com		#
97912199Sgerald.jelinek@sun.com		if [[ -z "$DATASET" ]]; then
98012199Sgerald.jelinek@sun.com			fatal "$f_nodataset"
98112199Sgerald.jelinek@sun.com		fi
98212199Sgerald.jelinek@sun.com		/usr/sbin/zfs destroy "$DATASET"
98312199Sgerald.jelinek@sun.com		if (( $? != 0 )); then
98412199Sgerald.jelinek@sun.com			log "$f_zfsdestroy" "$DATASET"
98512199Sgerald.jelinek@sun.com		fi
98612199Sgerald.jelinek@sun.com
98712199Sgerald.jelinek@sun.com		vlog "$stage1 $insrc | zfs receive -F $DATASET"
98812199Sgerald.jelinek@sun.com		( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET )
98912199Sgerald.jelinek@sun.com		unpack_result=$?
99012199Sgerald.jelinek@sun.com	fi
99112199Sgerald.jelinek@sun.com
99212199Sgerald.jelinek@sun.com	# Clean up any fs mounts used during unpacking.
99312199Sgerald.jelinek@sun.com	umnt_fs
99412734Sgary.pennington@oracle.com	rm -f $fstmpfile $fscpiofile $fspaxfile
99512199Sgerald.jelinek@sun.com
99612199Sgerald.jelinek@sun.com	chmod 700 $zonepath
99712199Sgerald.jelinek@sun.com
99812199Sgerald.jelinek@sun.com	(( $unpack_result != 0 )) && fatal "$f_unpack_failed"
99912199Sgerald.jelinek@sun.com
100012199Sgerald.jelinek@sun.com	# Verify this is a valid image.
100112199Sgerald.jelinek@sun.com	sanity_check $ZONEROOT
100212199Sgerald.jelinek@sun.com
100312199Sgerald.jelinek@sun.com	return 0
100412199Sgerald.jelinek@sun.com}
100512199Sgerald.jelinek@sun.com
100612199Sgerald.jelinek@sun.com# Setup i18n output
100712199Sgerald.jelinek@sun.comTEXTDOMAIN="SUNW_OST_OSCMD"
100812199Sgerald.jelinek@sun.comexport TEXTDOMAIN
100912199Sgerald.jelinek@sun.com
101012199Sgerald.jelinek@sun.come_cannot_wrap=$(gettext "%s: error: wrapper file already exists")
101112199Sgerald.jelinek@sun.come_baddir=$(gettext "Invalid '%s' directory within the zone")
101212199Sgerald.jelinek@sun.come_badfile=$(gettext "Invalid '%s' file within the zone")
101312199Sgerald.jelinek@sun.come_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
101412199Sgerald.jelinek@sun.come_not_found=$(gettext "%s: error: file or directory not found.")
101512199Sgerald.jelinek@sun.come_install_abort=$(gettext "Installation aborted.")
101612199Sgerald.jelinek@sun.come_not_readable=$(gettext "Cannot read directory '%s'")
101712199Sgerald.jelinek@sun.come_not_dir=$(gettext "Error: must be a directory")
101812199Sgerald.jelinek@sun.come_unknown_archive=$(gettext "Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.")
101912199Sgerald.jelinek@sun.come_absolute_archive=$(gettext "Error: archive contains absolute paths instead of relative paths.")
102012199Sgerald.jelinek@sun.come_mismatch_archive=$(gettext "Error: the archive top-level directory (%s) does not match the zonepath (%s).")
102112199Sgerald.jelinek@sun.come_tmpfile=$(gettext "Unable to create temporary file")
102212199Sgerald.jelinek@sun.come_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
102312199Sgerald.jelinek@sun.comf_mkdir=$(gettext "Unable to create directory %s.")
102412199Sgerald.jelinek@sun.comf_chmod=$(gettext "Unable to chmod directory %s.")
102512199Sgerald.jelinek@sun.comf_chown=$(gettext "Unable to chown directory %s.")
1026*12773Sgerald.jelinek@sun.comf_hwcap_info=$(gettext "HWCAP: %s\n")
1027*12773Sgerald.jelinek@sun.comf_sanity_hwcap=$(gettext \
1028*12773Sgerald.jelinek@sun.com"The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\
1029*12773Sgerald.jelinek@sun.com"       The zone will not boot on this platform.  See the zone's\n"\
1030*12773Sgerald.jelinek@sun.com"       documentation for the recommended way to create the archive.")
103112199Sgerald.jelinek@sun.com
103212199Sgerald.jelinek@sun.comm_analyse_archive=$(gettext "Analysing the archive")
103312199Sgerald.jelinek@sun.com
103412199Sgerald.jelinek@sun.comnot_readable=$(gettext "Cannot read file '%s'")
103512199Sgerald.jelinek@sun.comnot_flar=$(gettext "Input is not a flash archive")
103612199Sgerald.jelinek@sun.combad_flar=$(gettext "Flash archive is a corrupt")
103712199Sgerald.jelinek@sun.combad_zfs_flar=$(gettext "Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax.")
103812199Sgerald.jelinek@sun.comf_unpack_failed=$(gettext "Unpacking the archive failed")
103912199Sgerald.jelinek@sun.comunknown_archiver=$(gettext "Archiver %s is not supported")
104012199Sgerald.jelinek@sun.comcmd_not_exec=$(gettext "Required command '%s' not executable!")
104112199Sgerald.jelinek@sun.com
104212199Sgerald.jelinek@sun.com#
104312199Sgerald.jelinek@sun.com# Exit values used by the script, as #defined in <sys/zone.h>
104412199Sgerald.jelinek@sun.com#
104512199Sgerald.jelinek@sun.com#	ZONE_SUBPROC_OK
104612199Sgerald.jelinek@sun.com#	===============
104712199Sgerald.jelinek@sun.com#	Installation was successful
104812199Sgerald.jelinek@sun.com#
104912199Sgerald.jelinek@sun.com#	ZONE_SUBPROC_USAGE
105012199Sgerald.jelinek@sun.com#	==================
105112199Sgerald.jelinek@sun.com#	Improper arguments were passed, so print a usage message before exiting
105212199Sgerald.jelinek@sun.com#
105312199Sgerald.jelinek@sun.com#	ZONE_SUBPROC_NOTCOMPLETE
105412199Sgerald.jelinek@sun.com#	========================
105512199Sgerald.jelinek@sun.com#	Installation did not complete, but another installation attempt can be
105612199Sgerald.jelinek@sun.com#	made without an uninstall
105712199Sgerald.jelinek@sun.com#
105812199Sgerald.jelinek@sun.com#	ZONE_SUBPROC_FATAL
105912199Sgerald.jelinek@sun.com#	==================
106012199Sgerald.jelinek@sun.com#	Installation failed and an uninstall will be required before another
106112199Sgerald.jelinek@sun.com#	install can be attempted
106212199Sgerald.jelinek@sun.com#
106312199Sgerald.jelinek@sun.comZONE_SUBPROC_OK=0
106412199Sgerald.jelinek@sun.comZONE_SUBPROC_USAGE=253
106512199Sgerald.jelinek@sun.comZONE_SUBPROC_NOTCOMPLETE=254
106612199Sgerald.jelinek@sun.comZONE_SUBPROC_FATAL=255
106712199Sgerald.jelinek@sun.com
1068