xref: /illumos-gate/usr/src/lib/brand/shared/zone/common.ksh (revision d0b12b660e0741581d18f1f3a7d5268e0a5f1806)
1edfa49ffS#
2edfa49ffS# CDDL HEADER START
3edfa49ffS#
4edfa49ffS# The contents of this file are subject to the terms of the
5edfa49ffS# Common Development and Distribution License (the "License").
6edfa49ffS# You may not use this file except in compliance with the License.
7edfa49ffS#
8edfa49ffS# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9edfa49ffS# or http://www.opensolaris.org/os/licensing.
10edfa49ffS# See the License for the specific language governing permissions
11edfa49ffS# and limitations under the License.
12edfa49ffS#
13edfa49ffS# When distributing Covered Code, include this CDDL HEADER in each
14edfa49ffS# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15edfa49ffS# If applicable, add the following below this CDDL HEADER, with the
16edfa49ffS# fields enclosed by brackets "[]" replaced with your own identifying
17edfa49ffS# information: Portions Copyright [yyyy] [name of copyright owner]
18edfa49ffS#
19edfa49ffS# CDDL HEADER END
20edfa49ffS#
216e1ae2a3SGary Pennington# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
22edfa49ffS#
23edfa49ffS
24edfa49ffS#
25edfa49ffS# Send the error message to the screen and to the logfile.
26edfa49ffS#
27edfa49ffSerror()
28edfa49ffS{
29edfa49ffS        typeset fmt="$1"
30edfa49ffS        shift
31edfa49ffS
32edfa49ffS        printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
33edfa49ffS        [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
34edfa49ffS}
35edfa49ffS
36edfa49ffSfatal()
37edfa49ffS{
38edfa49ffS        typeset fmt="$1"
39edfa49ffS        shift
40edfa49ffS
41edfa49ffS	error "$fmt" "$@"
42edfa49ffS	exit $EXIT_CODE
43edfa49ffS}
44edfa49ffS
45e71ca95cSGerald Jelinekfail_fatal() {
4619b77901S        typeset fmt="$1"
4719b77901S        shift
4819b77901S
4919b77901S	error "$fmt" "$@"
50e71ca95cSGerald Jelinek	exit $ZONE_SUBPROC_FATAL
51e71ca95cSGerald Jelinek}
52e71ca95cSGerald Jelinek
53edfa49ffS#
54edfa49ffS# Send the provided printf()-style arguments to the screen and to the logfile.
55edfa49ffS#
56edfa49ffSlog()
57edfa49ffS{
58edfa49ffS        typeset fmt="$1"
59edfa49ffS        shift
60edfa49ffS
61edfa49ffS        printf "${MSG_PREFIX}${fmt}\n" "$@"
62edfa49ffS        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
63edfa49ffS}
64edfa49ffS
65edfa49ffS#
66edfa49ffS# Print provided text to the screen if the shell variable "OPT_V" is set.
67edfa49ffS# The text is always sent to the logfile.
68edfa49ffS#
69edfa49ffSvlog()
70edfa49ffS{
71edfa49ffS        typeset fmt="$1"
72edfa49ffS        shift
73edfa49ffS
74edfa49ffS        [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
75edfa49ffS        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
76edfa49ffS}
77edfa49ffS
78e71ca95cSGerald Jelinek#
79edfa49ffS# Validate that the directory is safe.
80e71ca95cSGerald Jelinek#
81e71ca95cSGerald Jelinek# It is possible for a malicious zone root user to modify a zone's filesystem
82e71ca95cSGerald Jelinek# so that modifications made to the zone's filesystem by administrators in the
83e71ca95cSGerald Jelinek# global zone modify the global zone's filesystem.  We can prevent this by
84e71ca95cSGerald Jelinek# ensuring that all components of paths accessed by scripts are real (i.e.,
85e71ca95cSGerald Jelinek# non-symlink) directories.
86e71ca95cSGerald Jelinek#
87e71ca95cSGerald Jelinek# NOTE: The specified path should be an absolute path as would be seen from
88e71ca95cSGerald Jelinek# within the zone.  Also, this function does not check parent directories.
89e71ca95cSGerald Jelinek# If, for example, you need to ensure that every component of the path
90e71ca95cSGerald Jelinek# '/foo/bar/baz' is a directory and not a symlink, then do the following:
91e71ca95cSGerald Jelinek#
92e71ca95cSGerald Jelinek#	safe_dir /foo
93e71ca95cSGerald Jelinek#	safe_dir /foo/bar
94e71ca95cSGerald Jelinek#	safe_dir /foo/bar/baz
95e71ca95cSGerald Jelinek#
96edfa49ffSsafe_dir()
97edfa49ffS{
98edfa49ffS	typeset dir="$1"
99edfa49ffS
100edfa49ffS	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
101edfa49ffS		fatal "$e_baddir" "$dir"
102edfa49ffS	fi
103edfa49ffS}
104edfa49ffS
105e71ca95cSGerald Jelinek# Like safe_dir except the dir doesn't have to exist.
106e71ca95cSGerald Jelineksafe_opt_dir()
107e71ca95cSGerald Jelinek{
108e71ca95cSGerald Jelinek	typeset dir="$1"
109e71ca95cSGerald Jelinek
110e71ca95cSGerald Jelinek	[[ ! -e $ZONEROOT/$dir ]] && return
111e71ca95cSGerald Jelinek
112e71ca95cSGerald Jelinek	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
113e71ca95cSGerald Jelinek		fatal "$e_baddir" "$dir"
114e71ca95cSGerald Jelinek	fi
115e71ca95cSGerald Jelinek}
116e71ca95cSGerald Jelinek
117edfa49ffS# Only make a copy if we haven't already done so.
118edfa49ffSsafe_backup()
119edfa49ffS{
120edfa49ffS	typeset src="$1"
121edfa49ffS	typeset dst="$2"
122edfa49ffS
123edfa49ffS	if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
124edfa49ffS		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
125edfa49ffS	fi
126edfa49ffS}
127edfa49ffS
128edfa49ffS# Make a copy even if the destination already exists.
129edfa49ffSsafe_copy()
130edfa49ffS{
131edfa49ffS	typeset src="$1"
132edfa49ffS	typeset dst="$2"
133edfa49ffS
134edfa49ffS	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
135edfa49ffS		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
136edfa49ffS	fi
137edfa49ffS}
138edfa49ffS
139edfa49ffS# Move a file
140edfa49ffSsafe_move()
141edfa49ffS{
142edfa49ffS	typeset src="$1"
143edfa49ffS	typeset dst="$2"
144edfa49ffS
145edfa49ffS	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
146edfa49ffS		/usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
147edfa49ffS	fi
148edfa49ffS}
149edfa49ffS
150e71ca95cSGerald Jelineksafe_rm()
151e71ca95cSGerald Jelinek{
152e71ca95cSGerald Jelinek	if [[ ! -h $ZONEROOT/$1 && -f $ZONEROOT/$1 ]]; then
153e71ca95cSGerald Jelinek		rm -f "$ZONEROOT/$1"
154e71ca95cSGerald Jelinek	fi
155e71ca95cSGerald Jelinek}
156e71ca95cSGerald Jelinek
157e71ca95cSGerald Jelinek#
158e71ca95cSGerald Jelinek# Replace the file with a wrapper pointing to the native brand code.
159e71ca95cSGerald Jelinek# However, we only do the replacement if the file hasn't already been
160e71ca95cSGerald Jelinek# replaced with our wrapper.  This function expects the cwd to be the
161e71ca95cSGerald Jelinek# location of the file we're replacing.
162e71ca95cSGerald Jelinek#
163e71ca95cSGerald Jelinek# Some of the files we're replacing are hardlinks to isaexec so we need to 'rm'
164e71ca95cSGerald Jelinek# the file before we setup the wrapper while others are hardlinks to rc scripts
165e71ca95cSGerald Jelinek# that we need to maintain.
166e71ca95cSGerald Jelinek#
167e71ca95cSGerald Jelineksafe_replace()
168e71ca95cSGerald Jelinek{
169e71ca95cSGerald Jelinek	typeset filename="$1"
170e71ca95cSGerald Jelinek	typeset runname="$2"
171e71ca95cSGerald Jelinek	typeset mode="$3"
172e71ca95cSGerald Jelinek	typeset own="$4"
173e71ca95cSGerald Jelinek	typeset rem="$5"
174e71ca95cSGerald Jelinek
175e71ca95cSGerald Jelinek	if [ -h $filename -o ! -f $filename ]; then
176e71ca95cSGerald Jelinek		return
177e71ca95cSGerald Jelinek	fi
178e71ca95cSGerald Jelinek
179e71ca95cSGerald Jelinek	egrep -s "Solaris Brand Replacement" $filename
180e71ca95cSGerald Jelinek	if [ $? -eq 0 ]; then
181e71ca95cSGerald Jelinek		return
182e71ca95cSGerald Jelinek	fi
183e71ca95cSGerald Jelinek
184e71ca95cSGerald Jelinek	safe_backup $filename $filename.pre_p2v
185e71ca95cSGerald Jelinek	if [ $rem = "remove" ]; then
186e71ca95cSGerald Jelinek		rm -f $filename
187e71ca95cSGerald Jelinek	fi
188e71ca95cSGerald Jelinek
189e71ca95cSGerald Jelinek	cat <<-END >$filename || exit 1
1901022fd2aS	#!/bin/sh -p
191e71ca95cSGerald Jelinek	#
192e71ca95cSGerald Jelinek	# Solaris Brand Replacement
193e71ca95cSGerald Jelinek	#
194e71ca95cSGerald Jelinek	# Attention.  This file has been replaced with a new version for
195e71ca95cSGerald Jelinek	# use in a virtualized environment.  Modification of this script is not
196e71ca95cSGerald Jelinek	# supported and all changes will be lost upon reboot.  The
197e71ca95cSGerald Jelinek	# {name}.pre_p2v version of this file is a backup copy of the
198e71ca95cSGerald Jelinek	# original and should not be deleted.
199e71ca95cSGerald Jelinek	#
200e71ca95cSGerald Jelinek	END
201e71ca95cSGerald Jelinek
202e71ca95cSGerald Jelinek	echo ". $runname \"\$@\"" >>$filename || exit 1
203e71ca95cSGerald Jelinek
204e71ca95cSGerald Jelinek	chmod $mode $filename
205e71ca95cSGerald Jelinek	chown $own $filename
206e71ca95cSGerald Jelinek}
207e71ca95cSGerald Jelinek
208ae104932SJonathan Adamssafe_wrap()
209ae104932SJonathan Adams{
210ae104932SJonathan Adams	typeset filename="$1"
211ae104932SJonathan Adams	typeset runname="$2"
212ae104932SJonathan Adams	typeset mode="$3"
213ae104932SJonathan Adams	typeset own="$4"
214ae104932SJonathan Adams
215ae104932SJonathan Adams	if [ -f $filename ]; then
216ae104932SJonathan Adams		log "$e_cannot_wrap" "$filename"
217ae104932SJonathan Adams		exit 1
218ae104932SJonathan Adams	fi
219ae104932SJonathan Adams
220ae104932SJonathan Adams	cat <<-END >$filename || exit 1
221ae104932SJonathan Adams	#!/bin/sh
222ae104932SJonathan Adams	#
223ae104932SJonathan Adams	# Solaris Brand Wrapper
224ae104932SJonathan Adams	#
225ae104932SJonathan Adams	# Attention.  This file has been created for use in a
226ae104932SJonathan Adams	# virtualized environment.  Modification of this script
227ae104932SJonathan Adams	# is not supported and all changes will be lost upon reboot.
228ae104932SJonathan Adams	#
229ae104932SJonathan Adams	END
230ae104932SJonathan Adams
231ae104932SJonathan Adams	echo ". $runname \"\$@\"" >>$filename || exit 1
232ae104932SJonathan Adams
233ae104932SJonathan Adams	chmod $mode $filename
234ae104932SJonathan Adams	chown $own $filename
235ae104932SJonathan Adams}
236ae104932SJonathan Adams
237edfa49ffS#
2386e1ae2a3SGary Pennington# Read zonecfg fs entries and save the relevant data, one entry per
239edfa49ffS# line.
240edfa49ffS# This assumes the properties from the zonecfg output, e.g.:
241edfa49ffS#	fs:
242edfa49ffS#		dir: /opt
243edfa49ffS#		special: /opt
244edfa49ffS#		raw not specified
245edfa49ffS#		type: lofs
246edfa49ffS#		options: [noexec,ro,noatime]
247edfa49ffS#
2486e1ae2a3SGary Pennington# and it assumes the order of the fs properties as above.
249edfa49ffS#
250edfa49ffSget_fs_info()
251edfa49ffS{
252edfa49ffS	zonecfg -z $zonename info fs | nawk '{
253edfa49ffS		if ($1 == "options:") {
254edfa49ffS			# Remove brackets.
255edfa49ffS			options=substr($2, 2, length($2) - 2);
256edfa49ffS			printf("%s %s %s %s\n", dir, type, special, options);
257edfa49ffS		} else if ($1 == "dir:") {
258edfa49ffS			dir=$2;
259edfa49ffS		} else if ($1 == "special:") {
260edfa49ffS			special=$2;
261edfa49ffS		} else if ($1 == "type:") {
262edfa49ffS			type=$2
263edfa49ffS		}
264edfa49ffS	}' >> $fstmpfile
265edfa49ffS}
266edfa49ffS
267edfa49ffS#
268edfa49ffS# Mount zonecfg fs entries into the zonepath.
269edfa49ffS#
270edfa49ffSmnt_fs()
271edfa49ffS{
272edfa49ffS	if [ ! -s $fstmpfile ]; then
273edfa49ffS		return;
274edfa49ffS	fi
275edfa49ffS
276edfa49ffS	# Sort the fs entries so we can handle nested mounts.
277edfa49ffS	sort $fstmpfile | nawk -v zonepath=$zonepath '{
278edfa49ffS		if (NF == 4)
279edfa49ffS			options="-o " $4;
280edfa49ffS		else
281edfa49ffS			options=""
282edfa49ffS
283edfa49ffS		# Create the mount point.  Ignore errors since we might have
284edfa49ffS		# a nested mount with a pre-existing mount point.
285edfa49ffS		cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
286edfa49ffS		system(cmd);
287edfa49ffS
288edfa49ffS		cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
289edfa49ffS		    zonepath "/root" $1;
290edfa49ffS		if (system(cmd) != 0) {
291edfa49ffS			printf("command failed: %s\n", cmd);
292edfa49ffS			exit 1;
293edfa49ffS		}
294edfa49ffS	}' >>$LOGFILE
295edfa49ffS}
296edfa49ffS
297edfa49ffS#
298edfa49ffS# Unmount zonecfg fs entries from the zonepath.
299edfa49ffS#
300edfa49ffSumnt_fs()
301edfa49ffS{
302edfa49ffS	if [ ! -s $fstmpfile ]; then
303edfa49ffS		return;
304edfa49ffS	fi
305edfa49ffS
306edfa49ffS	# Reverse sort the fs entries so we can handle nested unmounts.
307edfa49ffS	sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
308edfa49ffS		cmd="/usr/sbin/umount " zonepath "/root" $1
309edfa49ffS		if (system(cmd) != 0) {
310edfa49ffS			printf("command failed: %s\n", cmd);
311edfa49ffS		}
312edfa49ffS	}' >>$LOGFILE
313edfa49ffS}
314edfa49ffS
315e71ca95cSGerald Jelinek# Find the dataset mounted on the zonepath.
316e71ca95cSGerald Jelinekget_zonepath_ds() {
317e71ca95cSGerald Jelinek	ZONEPATH_DS=`/usr/sbin/zfs list -H -t filesystem -o name,mountpoint | \
318e71ca95cSGerald Jelinek	    /usr/bin/nawk -v zonepath=$1 '{
319e71ca95cSGerald Jelinek		if ($2 == zonepath)
320e71ca95cSGerald Jelinek			print $1
321e71ca95cSGerald Jelinek	}'`
322e71ca95cSGerald Jelinek
323e71ca95cSGerald Jelinek	if [ -z "$ZONEPATH_DS" ]; then
324e71ca95cSGerald Jelinek		fail_fatal "$f_no_ds"
325e71ca95cSGerald Jelinek	fi
326e71ca95cSGerald Jelinek}
327e71ca95cSGerald Jelinek
328eba00995S#
32919b77901S# Perform validation and cleanup in the zoneroot after unpacking the archive.
330eba00995S#
331eba00995Spost_unpack()
332eba00995S{
33319b77901S	#
33419b77901S	# Check if the image was created with a valid libc.so.1.
33519b77901S	#
33619b77901S	hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1`
33719b77901S	if (( $? != 0 )); then
33819b77901S		vlog "$f_hwcap_info" "$hwcap"
33919b77901S		fail_fatal "$f_sanity_hwcap"
34019b77901S	fi
34119b77901S
342eba00995S	( cd "$ZONEROOT" && \
343eba00995S	    find . \( -type b -o -type c \) -exec rm -f "{}" \; )
344eba00995S}
345eba00995S
346edfa49ffS#
347edfa49ffS# Determine flar compression style from identification file.
348edfa49ffS#
349edfa49ffSget_compression()
350edfa49ffS{
351edfa49ffS	typeset ident=$1
352edfa49ffS	typeset line=$(grep "^files_compressed_method=" $ident)
353edfa49ffS
354edfa49ffS	print ${line##*=}
355edfa49ffS}
356edfa49ffS
357edfa49ffS#
358edfa49ffS# Determine flar archive style from identification file.
359edfa49ffS#
360edfa49ffSget_archiver()
361edfa49ffS{
362edfa49ffS        typeset ident=$1
363edfa49ffS        typeset line=$(grep "^files_archived_method=" $ident)
364edfa49ffS
365edfa49ffS        print ${line##*=}
366edfa49ffS}
367edfa49ffS
368edfa49ffS#
369edfa49ffS# Unpack flar into current directory (which should be zoneroot).  The flash
370edfa49ffS# archive is standard input.  See flash_archive(4) man page.
371edfa49ffS#
372edfa49ffS# We can't use "flar split" since it will only unpack into a directory called
373edfa49ffS# "archive".  We need to unpack in place in order to properly handle nested
374edfa49ffS# fs mounts within the zone root.  This function does the unpacking into the
375edfa49ffS# current directory.
376edfa49ffS#
377edfa49ffS# This code is derived from the gen_split() function in /usr/sbin/flar so
378edfa49ffS# we keep the same style as the original.
379edfa49ffS#
380edfa49ffSinstall_flar()
381edfa49ffS{
382edfa49ffS	typeset result
383edfa49ffS        typeset archiver_command
384edfa49ffS        typeset archiver_arguments
385edfa49ffS
38674bbcaa8S	vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar"
387edfa49ffS
388edfa49ffS	# Read cookie
389edfa49ffS	read -r input_line
390edfa49ffS	if (( $? != 0 )); then
391edfa49ffS		log "$not_readable" "$install_media"
392edfa49ffS		return 1
393edfa49ffS	fi
394edfa49ffS	# The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
395edfa49ffS	if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
396edfa49ffS		log "$not_flar"
397edfa49ffS		return 1
398edfa49ffS	fi
399edfa49ffS
400edfa49ffS	while [ true ]
401edfa49ffS	do
402edfa49ffS		# We should always be at the start of a section here
403edfa49ffS		read -r input_line
404edfa49ffS		if [[ ${input_line%%=*} != "section_begin" ]]; then
405edfa49ffS			log "$bad_flar"
406edfa49ffS			return 1
407edfa49ffS		fi
408edfa49ffS		section_name=${input_line##*=}
409edfa49ffS
410edfa49ffS		# If we're at the archive, we're done skipping sections.
411edfa49ffS		if [[ "$section_name" == "archive" ]]; then
412edfa49ffS			break
413edfa49ffS		fi
414edfa49ffS
415edfa49ffS		#
416edfa49ffS		# Save identification section to a file so we can determine
417edfa49ffS		# how to unpack the archive.
418edfa49ffS		#
419edfa49ffS		if [[ "$section_name" == "identification" ]]; then
420edfa49ffS			/usr/bin/rm -f identification
421edfa49ffS			while read -r input_line
422edfa49ffS			do
423edfa49ffS				if [[ ${input_line%%=*} == \
424edfa49ffS				    "section_begin" ]]; then
425edfa49ffS					/usr/bin/rm -f identification
426edfa49ffS					log "$bad_flar"
427edfa49ffS					return 1
428edfa49ffS				fi
429edfa49ffS
430edfa49ffS				if [[ $input_line == \
431edfa49ffS				    "section_end=$section_name" ]]; then
432edfa49ffS					break;
433edfa49ffS				fi
434edfa49ffS				echo $input_line >> identification
435edfa49ffS			done
436edfa49ffS
437edfa49ffS			continue
438edfa49ffS		fi
439edfa49ffS
440edfa49ffS		#
441edfa49ffS		# Otherwise skip past this section; read lines until detecting
442edfa49ffS		# section_end.  According to flash_archive(4) we can have
443edfa49ffS		# an arbitrary number of sections but the archive section
444edfa49ffS		# must be last.
445edfa49ffS		#
446edfa49ffS		success=0
447edfa49ffS		while read -r input_line
448edfa49ffS		do
449edfa49ffS			if [[ $input_line == "section_end=$section_name" ]];
450edfa49ffS			then
451edfa49ffS				success=1
452edfa49ffS				break
453edfa49ffS			fi
454edfa49ffS			# Fail if we miss the end of the section
455edfa49ffS			if [[ ${input_line%%=*} == "section_begin" ]]; then
456edfa49ffS				/usr/bin/rm -f identification
457edfa49ffS				log "$bad_flar"
458edfa49ffS				return 1
459edfa49ffS			fi
460edfa49ffS		done
461edfa49ffS		if (( $success == 0 )); then
462edfa49ffS			#
463edfa49ffS			# If we get here we read to the end of the file before
464edfa49ffS			# seeing the end of the section we were reading.
465edfa49ffS			#
466edfa49ffS			/usr/bin/rm -f identification
467edfa49ffS			log "$bad_flar"
468edfa49ffS			return 1
469edfa49ffS		fi
470edfa49ffS	done
471edfa49ffS
472cec6066bS	# Check for an archive made from a ZFS root pool.
473cec6066bS	egrep -s "^rootpool=" identification
474cec6066bS        if (( $? == 0 )); then
475cec6066bS		/usr/bin/rm -f identification
476cec6066bS                log "$bad_zfs_flar"
477cec6066bS                return 1
478cec6066bS        fi
479cec6066bS
480edfa49ffS	# Get the information needed to unpack the archive.
481edfa49ffS	archiver=$(get_archiver identification)
482edfa49ffS	if [[ $archiver == "pax" ]]; then
483edfa49ffS		# pax archiver specified
484edfa49ffS		archiver_command="/usr/bin/pax"
4856e1ae2a3SGary Pennington		if [[ -s $fspaxfile ]]; then
486edfa49ffS			archiver_arguments="-r -p e -c \
4876e1ae2a3SGary Pennington			    $(/usr/bin/cat $fspaxfile)"
488edfa49ffS		else
489edfa49ffS			archiver_arguments="-r -p e"
490edfa49ffS		fi
491edfa49ffS	elif [[ $archiver == "cpio" || -z $archiver ]]; then
492edfa49ffS		# cpio archived specified OR no archiver specified - use default
493edfa49ffS		archiver_command="/usr/bin/cpio"
4946e1ae2a3SGary Pennington		archiver_arguments="-icdumfE $fscpiofile"
495edfa49ffS	else
496edfa49ffS		# unknown archiver specified
497edfa49ffS		log "$unknown_archiver" $archiver
498edfa49ffS		return 1
499edfa49ffS	fi
500edfa49ffS
501edfa49ffS	if [[ ! -x $archiver_command ]]; then
502edfa49ffS		/usr/bin/rm -f identification
503edfa49ffS		log "$cmd_not_exec" $archiver_command
504edfa49ffS		return 1
505edfa49ffS	fi
506edfa49ffS
507edfa49ffS	compression=$(get_compression identification)
508edfa49ffS
509edfa49ffS	# We're done with the identification file
510edfa49ffS	/usr/bin/rm -f identification
511edfa49ffS
512edfa49ffS	# Extract archive
513edfa49ffS	if [[ $compression == "compress" ]]; then
514eba00995S		/usr/bin/zcat | \
515edfa49ffS		    $archiver_command $archiver_arguments 2>/dev/null
516edfa49ffS	else
517eba00995S		$archiver_command $archiver_arguments 2>/dev/null
518edfa49ffS	fi
519edfa49ffS	result=$?
520edfa49ffS
521eba00995S	post_unpack
522eba00995S
523edfa49ffS	(( $result != 0 )) && return 1
524edfa49ffS
525edfa49ffS	return 0
526edfa49ffS}
527edfa49ffS
5288c20418dSGerald Jelinek#
5298c20418dSGerald Jelinek# Get the archive base.
5308c20418dSGerald Jelinek#
5318c20418dSGerald Jelinek# We must unpack the archive in the right place within the zonepath so
5328c20418dSGerald Jelinek# that files are installed into the various mounted filesystems that are set
5338c20418dSGerald Jelinek# up in the zone's configuration.  These are already mounted for us by the
5348c20418dSGerald Jelinek# mntfs function.
5358c20418dSGerald Jelinek#
5368c20418dSGerald Jelinek# Archives can be made of either a physical host's root file system or a
5378c20418dSGerald Jelinek# zone's zonepath.  For a physical system, if the archive is made using an
5388c20418dSGerald Jelinek# absolute path (/...) we can't use it.  For a zone the admin can make the
5398c20418dSGerald Jelinek# archive from a variety of locations;
5408c20418dSGerald Jelinek#
5418c20418dSGerald Jelinek#   a) zonepath itself: This will be a single dir, probably named with the
5428c20418dSGerald Jelinek#      zone name, it will contain a root dir and under the root we'll see all
5438c20418dSGerald Jelinek#      the top level dirs; etc, var, usr...  We must be above the ZONEPATH
5448c20418dSGerald Jelinek#      when we unpack the archive but this will only work if the the archive's
5458c20418dSGerald Jelinek#      top-level dir name matches the ZONEPATH base-level dir name.  If not,
5468c20418dSGerald Jelinek#      this is an error.
5478c20418dSGerald Jelinek#
5488c20418dSGerald Jelinek#   b) inside the zonepath: We'll see root and it will contain all the top
5498c20418dSGerald Jelinek#      level dirs; etc, var, usr....  We must be in the ZONEPATH when we unpack
5508c20418dSGerald Jelinek#      the archive.
5518c20418dSGerald Jelinek#
5528c20418dSGerald Jelinek#   c) inside the zonepath root: We'll see all the top level dirs, ./etc,
5538c20418dSGerald Jelinek#      ./var, ./usr....  This is also the case we see when we get an archive
554*d0b12b66SToomas Soome#      of a physical system.  We must be in ZONEROOT when we unpack the archive.
5558c20418dSGerald Jelinek#
5568c20418dSGerald Jelinek# Note that there can be a directory named "root" under the ZONEPATH/root
5578c20418dSGerald Jelinek# directory.
5588c20418dSGerald Jelinek#
5598c20418dSGerald Jelinek# This function handles the above possibilities so that we reject absolute
5608c20418dSGerald Jelinek# path archives and figure out where in the file system we need to be to
5618c20418dSGerald Jelinek# properly unpack the archive into the zone.  It sets the ARCHIVE_BASE
5628c20418dSGerald Jelinek# variable to the location where the achive should be unpacked.
5638c20418dSGerald Jelinek#
5648c20418dSGerald Jelinekget_archive_base()
5658c20418dSGerald Jelinek{
5668c20418dSGerald Jelinek	stage1=$1
5678c20418dSGerald Jelinek	archive=$2
5688c20418dSGerald Jelinek	stage2=$3
5698c20418dSGerald Jelinek
5708c20418dSGerald Jelinek	vlog "$m_analyse_archive"
5718c20418dSGerald Jelinek
5728c20418dSGerald Jelinek	base=`$stage1 $archive | $stage2 2>/dev/null | nawk -F/ '{
5738c20418dSGerald Jelinek		# Check for an absolute path archive
5748c20418dSGerald Jelinek		if (substr($0, 1, 1) == "/")
5758c20418dSGerald Jelinek			exit 1
5768c20418dSGerald Jelinek
5778c20418dSGerald Jelinek		if ($1 != ".")
5788c20418dSGerald Jelinek			dirs[$1] = 1
5798c20418dSGerald Jelinek		else
5808c20418dSGerald Jelinek			dirs[$2] = 1
5818c20418dSGerald Jelinek	}
5828c20418dSGerald Jelinek	END {
5838c20418dSGerald Jelinek		for (d in dirs) {
5848c20418dSGerald Jelinek			cnt++
5858c20418dSGerald Jelinek			if (d == "bin")  sawbin = 1
5868c20418dSGerald Jelinek			if (d == "etc")  sawetc = 1
5878c20418dSGerald Jelinek			if (d == "root") sawroot = 1
5888c20418dSGerald Jelinek			if (d == "var")  sawvar = 1
5898c20418dSGerald Jelinek                }
5908c20418dSGerald Jelinek
5918c20418dSGerald Jelinek		if (cnt == 1) {
5928c20418dSGerald Jelinek			# If only one top-level dir named root, we are in the
5938c20418dSGerald Jelinek			# zonepath, otherwise this must be an archive *of*
5948c20418dSGerald Jelinek			# the zonepath so print the top-level dir name.
5958c20418dSGerald Jelinek			if (sawroot)
5968c20418dSGerald Jelinek				print "*zonepath*"
5978c20418dSGerald Jelinek			else
5988c20418dSGerald Jelinek				for (d in dirs) print d
5998c20418dSGerald Jelinek		} else {
6008c20418dSGerald Jelinek			# We are either in the zonepath or in the zonepath/root
6018c20418dSGerald Jelinek			# (or at the top level of a full system archive which
6028c20418dSGerald Jelinek			# looks like the zonepath/root case).  Figure out which
6038c20418dSGerald Jelinek			# one.
6048c20418dSGerald Jelinek			if (sawroot && !sawbin && !sawetc && !sawvar)
6058c20418dSGerald Jelinek				print "*zonepath*"
6068c20418dSGerald Jelinek			else
6078c20418dSGerald Jelinek				print "*zoneroot*"
6088c20418dSGerald Jelinek		}
6098c20418dSGerald Jelinek	}'`
6108c20418dSGerald Jelinek
6118c20418dSGerald Jelinek	if (( $? != 0 )); then
6128c20418dSGerald Jelinek		umnt_fs
6138c20418dSGerald Jelinek		fatal "$e_absolute_archive"
6148c20418dSGerald Jelinek	fi
6158c20418dSGerald Jelinek
6168c20418dSGerald Jelinek	if [[ "$base" == "*zoneroot*" ]]; then
6178c20418dSGerald Jelinek		ARCHIVE_BASE=$ZONEROOT
6188c20418dSGerald Jelinek	elif [[ "$base" == "*zonepath*" ]]; then
6198c20418dSGerald Jelinek		ARCHIVE_BASE=$ZONEPATH
6208c20418dSGerald Jelinek	else
6218c20418dSGerald Jelinek		# We need to be in the dir above the ZONEPATH but we need to
6228c20418dSGerald Jelinek		# validate that $base matches the final component of ZONEPATH.
6238c20418dSGerald Jelinek		bname=`basename $ZONEPATH`
6248c20418dSGerald Jelinek
6258c20418dSGerald Jelinek		if [[ "$bname" != "$base" ]]; then
6268c20418dSGerald Jelinek			umnt_fs
6278c20418dSGerald Jelinek			fatal "$e_mismatch_archive" "$base" "$bname"
6288c20418dSGerald Jelinek		fi
6298c20418dSGerald Jelinek		ARCHIVE_BASE=`dirname $ZONEPATH`
6308c20418dSGerald Jelinek	fi
6318c20418dSGerald Jelinek}
6328c20418dSGerald Jelinek
633edfa49ffS#
634edfa49ffS# Unpack cpio archive into zoneroot.
635edfa49ffS#
636edfa49ffSinstall_cpio()
637edfa49ffS{
638edfa49ffS	stage1=$1
639edfa49ffS	archive=$2
640edfa49ffS
6418c20418dSGerald Jelinek	get_archive_base "$stage1" "$archive" "cpio -it"
64262ac5336S
6436e1ae2a3SGary Pennington	cpioopts="-idmfE $fscpiofile"
644edfa49ffS
6458c20418dSGerald Jelinek	vlog "cd \"$ARCHIVE_BASE\" && $stage1 \"$archive\" | cpio $cpioopts"
646eba00995S
647cec6066bS	# Ignore errors from cpio since we expect some errors depending on
648cec6066bS	# how the archive was made.
6498c20418dSGerald Jelinek	( cd "$ARCHIVE_BASE" && $stage1 "$archive" | cpio $cpioopts )
650eba00995S
651eba00995S	post_unpack
652edfa49ffS
653cec6066bS	return 0
654edfa49ffS}
655edfa49ffS
656edfa49ffS#
657edfa49ffS# Unpack pax archive into zoneroot.
658edfa49ffS#
659edfa49ffSinstall_pax()
660edfa49ffS{
661edfa49ffS	archive=$1
662edfa49ffS
6638c20418dSGerald Jelinek	get_archive_base "cat" "$archive" "pax"
66462ac5336S
6656e1ae2a3SGary Pennington	if [[ -s $fspaxfile ]]; then
6666e1ae2a3SGary Pennington		filtopt="-c $(/usr/bin/cat $fspaxfile)"
667edfa49ffS	fi
668edfa49ffS
6698c20418dSGerald Jelinek	vlog "cd \"$ARCHIVE_BASE\" && pax -r -f \"$archive\" $filtopt"
670edfa49ffS
671cec6066bS	# Ignore errors from pax since we expect some errors depending on
672cec6066bS	# how the archive was made.
6738c20418dSGerald Jelinek	( cd "$ARCHIVE_BASE" && pax -r -f "$archive" $filtopt )
674eba00995S
675eba00995S	post_unpack
676eba00995S
677cec6066bS	return 0
678edfa49ffS}
679edfa49ffS
680edfa49ffS#
681edfa49ffS# Unpack UFS dump into zoneroot.
682edfa49ffS#
683edfa49ffSinstall_ufsdump()
684edfa49ffS{
685edfa49ffS	archive=$1
686edfa49ffS
687eba00995S	vlog "cd \"$ZONEROOT\" && ufsrestore rf \"$archive\""
688edfa49ffS
689edfa49ffS	#
690edfa49ffS	# ufsrestore goes interactive if you ^C it.  To prevent that,
691edfa49ffS	# we make sure its stdin is not a terminal.
692edfa49ffS	#
693eba00995S	( cd "$ZONEROOT" && ufsrestore rf "$archive" < /dev/null )
694eba00995S	result=$?
695eba00995S
696eba00995S	post_unpack
697eba00995S
698eba00995S	return $result
699edfa49ffS}
700edfa49ffS
701edfa49ffS#
702edfa49ffS# Copy directory hierarchy into zoneroot.
703edfa49ffS#
704edfa49ffSinstall_dir()
705edfa49ffS{
706edfa49ffS	source_dir=$1
707edfa49ffS
708edfa49ffS	cpioopts="-pdm"
709edfa49ffS
710edfa49ffS	first=1
7116e1ae2a3SGary Pennington	filt=$(for i in $(cat $fspaxfile)
712edfa49ffS		do
713edfa49ffS			echo $i | egrep -s "/" && continue
714edfa49ffS			if [[ $first == 1 ]]; then
715edfa49ffS				printf "^%s" $i
716edfa49ffS				first=0
717edfa49ffS			else
718edfa49ffS				printf "|^%s" $i
719edfa49ffS			fi
720edfa49ffS		done)
721edfa49ffS
722edfa49ffS	list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
723edfa49ffS	flist=$(for i in $list
724edfa49ffS	do
725edfa49ffS		printf "%s " "$i"
726edfa49ffS	done)
727edfa49ffS	findopts="-xdev ( -type d -o -type f -o -type l ) -print"
728edfa49ffS
729edfa49ffS	vlog "cd \"$source_dir\" && find $flist $findopts | "
730eba00995S	vlog "cpio $cpioopts \"$ZONEROOT\""
731edfa49ffS
732cec6066bS	# Ignore errors from cpio since we expect some errors depending on
733cec6066bS	# how the archive was made.
734edfa49ffS	( cd "$source_dir" && find $flist $findopts | \
735eba00995S	    cpio $cpioopts "$ZONEROOT" )
736eba00995S
737eba00995S	post_unpack
738eba00995S
739cec6066bS	return 0
740edfa49ffS}
741edfa49ffS
74274bbcaa8S#
74374bbcaa8S# This is a common function for laying down a zone image from a variety of
74474bbcaa8S# different sources.  This can be used to either install a fresh zone or as
74574bbcaa8S# part of zone migration during attach.
74674bbcaa8S#
74774bbcaa8S# The first argument specifies the type of image: archive, directory or stdin.
74874bbcaa8S# The second argument specifies the image itself.  In the case of stdin, the
74974bbcaa8S# second argument specifies the format of the stream (cpio, flar, etc.).
75074bbcaa8S# Any validation or post-processing on the image is done elsewhere.
75174bbcaa8S#
75274bbcaa8S# This function calls a 'sanity_check' function which must be provided by
75374bbcaa8S# the script which includes this code.
75474bbcaa8S#
75574bbcaa8Sinstall_image()
75674bbcaa8S{
75774bbcaa8S	intype=$1
75874bbcaa8S	insrc=$2
75974bbcaa8S
76074bbcaa8S	if [[ -z "$intype" || -z "$insrc" ]]; then
76174bbcaa8S		return 1
76274bbcaa8S	fi
76374bbcaa8S
76474bbcaa8S	filetype="unknown"
76574bbcaa8S	filetypename="unknown"
76674bbcaa8S	stage1="cat"
76774bbcaa8S
76874bbcaa8S	if [[ "$intype" == "directory" ]]; then
76974bbcaa8S		if [[ "$insrc" == "-" ]]; then
77074bbcaa8S			# Indicates that the existing zonepath is prepopulated.
77174bbcaa8S			filetype="existing"
77274bbcaa8S			filetypename="existing"
77374bbcaa8S		else
77474bbcaa8S			if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then
77574bbcaa8S				fatal "$e_path_abs" "$insrc"
77674bbcaa8S			fi
77774bbcaa8S
77874bbcaa8S			if [[ ! -e "$insrc" ]]; then
77974bbcaa8S				log "$e_not_found" "$insrc"
78074bbcaa8S				fatal "$e_install_abort"
78174bbcaa8S			fi
78274bbcaa8S
78374bbcaa8S			if [[ ! -r "$insrc" ]]; then
78474bbcaa8S				log "$e_not_readable" "$insrc"
78574bbcaa8S				fatal "$e_install_abort"
78674bbcaa8S			fi
78774bbcaa8S
78874bbcaa8S			if [[ ! -d "$insrc" ]]; then
78974bbcaa8S				log "$e_not_dir"
79074bbcaa8S				fatal "$e_install_abort"
79174bbcaa8S			fi
79274bbcaa8S
79374bbcaa8S			sanity_check $insrc
79474bbcaa8S
79574bbcaa8S			filetype="directory"
79674bbcaa8S			filetypename="directory"
79774bbcaa8S		fi
79874bbcaa8S
79974bbcaa8S	else
80074bbcaa8S		# Common code for both archive and stdin stream.
80174bbcaa8S
80274bbcaa8S		if [[ "$intype" == "archive" ]]; then
80374bbcaa8S			if [[ ! -f "$insrc" ]]; then
80474bbcaa8S				log "$e_unknown_archive"
80574bbcaa8S				fatal "$e_install_abort"
80674bbcaa8S			fi
80774bbcaa8S			ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)"
80874bbcaa8S		else
80974bbcaa8S			# For intype == stdin, the insrc parameter specifies
81074bbcaa8S			# the stream format coming on stdin.
81174bbcaa8S			ftype="$insrc"
81274bbcaa8S			insrc="-"
81374bbcaa8S		fi
81474bbcaa8S
81574bbcaa8S		# Setup vars for the archive type we have.
81674bbcaa8S		case "$ftype" in
81774bbcaa8S		*cpio*)		filetype="cpio"
81874bbcaa8S				filetypename="cpio archive"
81974bbcaa8S			;;
82074bbcaa8S		*bzip2*)	filetype="bzip2"
82174bbcaa8S				filetypename="bzipped cpio archive"
82274bbcaa8S			;;
82374bbcaa8S		*gzip*)		filetype="gzip"
82474bbcaa8S				filetypename="gzipped cpio archive"
82574bbcaa8S			;;
82674bbcaa8S		*ufsdump*)	filetype="ufsdump"
82774bbcaa8S				filetypename="ufsdump archive"
82874bbcaa8S			;;
82974bbcaa8S		"flar")
83074bbcaa8S				filetype="flar"
83174bbcaa8S				filetypename="flash archive"
83274bbcaa8S			;;
83374bbcaa8S		"flash")
83474bbcaa8S				filetype="flar"
83574bbcaa8S				filetypename="flash archive"
83674bbcaa8S			;;
83774bbcaa8S		*Flash\ Archive*)
83874bbcaa8S				filetype="flar"
83974bbcaa8S				filetypename="flash archive"
84074bbcaa8S			;;
84174bbcaa8S		"tar")
84274bbcaa8S				filetype="tar"
84374bbcaa8S				filetypename="tar archive"
84474bbcaa8S			;;
84574bbcaa8S		*USTAR\ tar\ archive)
84674bbcaa8S				filetype="tar"
84774bbcaa8S				filetypename="tar archive"
84874bbcaa8S			;;
84974bbcaa8S		"pax")
85074bbcaa8S				filetype="xustar"
85174bbcaa8S				filetypename="pax (xustar) archive"
85274bbcaa8S			;;
85374bbcaa8S		*USTAR\ tar\ archive\ extended\ format*)
85474bbcaa8S				filetype="xustar"
85574bbcaa8S				filetypename="pax (xustar) archive"
85674bbcaa8S			;;
85774bbcaa8S		"zfs")
85874bbcaa8S				filetype="zfs"
85974bbcaa8S				filetypename="ZFS send stream"
86074bbcaa8S			;;
86174bbcaa8S		*ZFS\ snapshot\ stream*)
86274bbcaa8S				filetype="zfs"
86374bbcaa8S				filetypename="ZFS send stream"
86474bbcaa8S			;;
86574bbcaa8S		*)		log "$e_unknown_archive"
86674bbcaa8S				fatal "$e_install_abort"
86774bbcaa8S			;;
86874bbcaa8S		esac
86974bbcaa8S	fi
87074bbcaa8S
87174bbcaa8S	vlog "$filetypename"
87274bbcaa8S
87374bbcaa8S	# Check for a non-empty root if no '-d -' option.
87474bbcaa8S	if [[ "$filetype" != "existing" ]]; then
87574bbcaa8S		cnt=$(ls $ZONEROOT | wc -l)
87674bbcaa8S		if (( $cnt != 0 )); then
87774bbcaa8S			fatal "$e_root_full" "$ZONEROOT"
87874bbcaa8S		fi
87974bbcaa8S	fi
88074bbcaa8S
88174bbcaa8S	fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
88274bbcaa8S	if [[ -z "$fstmpfile" ]]; then
88374bbcaa8S		fatal "$e_tmpfile"
88474bbcaa8S	fi
88574bbcaa8S
88674bbcaa8S	# Make sure we always have the files holding the directories to filter
88774bbcaa8S	# out when extracting from a CPIO or PAX archive.  We'll add the fs
8886e1ae2a3SGary Pennington	# entries to these files in get_fs_info()
8896e1ae2a3SGary Pennington	fscpiofile=$(/usr/bin/mktemp -t -p /var/tmp fs.cpio.XXXXXX)
8906e1ae2a3SGary Pennington	if [[ -z "$fscpiofile" ]]; then
89174bbcaa8S		rm -f $fstmpfile
89274bbcaa8S		fatal "$e_tmpfile"
89374bbcaa8S	fi
89474bbcaa8S
8956e1ae2a3SGary Pennington	# Filter out these directories.
8966e1ae2a3SGary Pennington	echo 'dev/*' >>$fscpiofile
8976e1ae2a3SGary Pennington	echo 'devices/*' >>$fscpiofile
8986e1ae2a3SGary Pennington	echo 'devices' >>$fscpiofile
8996e1ae2a3SGary Pennington	echo 'proc/*' >>$fscpiofile
9006e1ae2a3SGary Pennington	echo 'tmp/*' >>$fscpiofile
9016e1ae2a3SGary Pennington	echo 'var/run/*' >>$fscpiofile
9026e1ae2a3SGary Pennington	echo 'system/contract/*' >>$fscpiofile
9036e1ae2a3SGary Pennington	echo 'system/object/*' >>$fscpiofile
9046e1ae2a3SGary Pennington
9056e1ae2a3SGary Pennington	fspaxfile=$(/usr/bin/mktemp -t -p /var/tmp fs.pax.XXXXXX)
9066e1ae2a3SGary Pennington	if [[ -z "$fspaxfile" ]]; then
9076e1ae2a3SGary Pennington		rm -f $fstmpfile $fscpiofile
90874bbcaa8S		fatal "$e_tmpfile"
90974bbcaa8S	fi
91074bbcaa8S
91174bbcaa8S	printf "%s " \
91274bbcaa8S	    "dev devices proc tmp var/run system/contract system/object" \
9136e1ae2a3SGary Pennington	    >>$fspaxfile
91474bbcaa8S
91574bbcaa8S	# Set up any fs mounts so the archive will install into the correct
91674bbcaa8S	# locations.
91774bbcaa8S	get_fs_info
91874bbcaa8S	mnt_fs
91974bbcaa8S	if (( $? != 0 )); then
92074bbcaa8S		umnt_fs >/dev/null 2>&1
9216e1ae2a3SGary Pennington		rm -f $fstmpfile $fscpiofile $fspaxfile
92274bbcaa8S		fatal "$mount_failed"
92374bbcaa8S	fi
92474bbcaa8S
92574bbcaa8S	if [[ "$filetype" == "existing" ]]; then
92674bbcaa8S		log "$no_installing"
92774bbcaa8S	else
92874bbcaa8S		log "$installing"
92974bbcaa8S	fi
93074bbcaa8S
93174bbcaa8S	#
93274bbcaa8S	# Install the image into the zonepath.
93374bbcaa8S	#
93474bbcaa8S	unpack_result=0
93574bbcaa8S	stage1="cat"
93674bbcaa8S	if [[ "$filetype" == "gzip" ]]; then
93774bbcaa8S		stage1="gzcat"
93874bbcaa8S		filetype="cpio"
93974bbcaa8S	elif [[ "$filetype" == "bzip2" ]]; then
94074bbcaa8S		stage1="bzcat"
94174bbcaa8S		filetype="cpio"
94274bbcaa8S	fi
94374bbcaa8S
94474bbcaa8S	if [[ "$filetype" == "cpio" ]]; then
94574bbcaa8S		install_cpio "$stage1" "$insrc"
94674bbcaa8S		unpack_result=$?
94774bbcaa8S
94874bbcaa8S	elif [[ "$filetype" == "flar" ]]; then
94974bbcaa8S		( cd "$ZONEROOT" && $stage1 $insrc | install_flar )
95074bbcaa8S		unpack_result=$?
95174bbcaa8S
95274bbcaa8S	elif [[ "$filetype" == "xustar" ]]; then
95374bbcaa8S		install_pax "$insrc"
95474bbcaa8S		unpack_result=$?
95574bbcaa8S
95674bbcaa8S	elif [[ "$filetype" = "tar" ]]; then
95774bbcaa8S		vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\""
958cec6066bS		# Ignore errors from tar since we expect some errors depending
959cec6066bS		# on how the archive was made.
96074bbcaa8S		( cd "$ZONEROOT" && tar -xf "$insrc" )
961cec6066bS		unpack_result=0
96274bbcaa8S		post_unpack
96374bbcaa8S
96474bbcaa8S	elif [[ "$filetype" == "ufsdump" ]]; then
96574bbcaa8S		install_ufsdump "$insrc"
96674bbcaa8S		unpack_result=$?
96774bbcaa8S
96874bbcaa8S	elif [[ "$filetype" == "directory" ]]; then
96974bbcaa8S		install_dir "$insrc"
97074bbcaa8S		unpack_result=$?
97174bbcaa8S
97274bbcaa8S	elif [[ "$filetype" == "zfs" ]]; then
97374bbcaa8S		#
97474bbcaa8S		# Given a 'zfs send' stream file, receive the snapshot into
97574bbcaa8S		# the zone's dataset.  We're getting the original system's
97674bbcaa8S		# zonepath dataset.  Destroy the existing dataset created
97774bbcaa8S		# above since this recreates it.
97874bbcaa8S		#
97974bbcaa8S		if [[ -z "$DATASET" ]]; then
98074bbcaa8S			fatal "$f_nodataset"
98174bbcaa8S		fi
98274bbcaa8S		/usr/sbin/zfs destroy "$DATASET"
98374bbcaa8S		if (( $? != 0 )); then
98474bbcaa8S			log "$f_zfsdestroy" "$DATASET"
98574bbcaa8S		fi
98674bbcaa8S
98774bbcaa8S		vlog "$stage1 $insrc | zfs receive -F $DATASET"
98874bbcaa8S		( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET )
98974bbcaa8S		unpack_result=$?
99074bbcaa8S	fi
99174bbcaa8S
99274bbcaa8S	# Clean up any fs mounts used during unpacking.
99374bbcaa8S	umnt_fs
9946e1ae2a3SGary Pennington	rm -f $fstmpfile $fscpiofile $fspaxfile
99574bbcaa8S
99674bbcaa8S	chmod 700 $zonepath
99774bbcaa8S
998cec6066bS	(( $unpack_result != 0 )) && fatal "$f_unpack_failed"
999cec6066bS
100074bbcaa8S	# Verify this is a valid image.
100174bbcaa8S	sanity_check $ZONEROOT
100274bbcaa8S
100374bbcaa8S	return 0
100474bbcaa8S}
100574bbcaa8S
1006edfa49ffS# Setup i18n output
1007edfa49ffSTEXTDOMAIN="SUNW_OST_OSCMD"
1008edfa49ffSexport TEXTDOMAIN
1009edfa49ffS
1010ae104932SJonathan Adamse_cannot_wrap=$(gettext "%s: error: wrapper file already exists")
1011edfa49ffSe_baddir=$(gettext "Invalid '%s' directory within the zone")
1012edfa49ffSe_badfile=$(gettext "Invalid '%s' file within the zone")
101374bbcaa8Se_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
101474bbcaa8Se_not_found=$(gettext "%s: error: file or directory not found.")
101574bbcaa8Se_install_abort=$(gettext "Installation aborted.")
101674bbcaa8Se_not_readable=$(gettext "Cannot read directory '%s'")
101774bbcaa8Se_not_dir=$(gettext "Error: must be a directory")
101874bbcaa8Se_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.")
101962ac5336Se_absolute_archive=$(gettext "Error: archive contains absolute paths instead of relative paths.")
10208c20418dSGerald Jelineke_mismatch_archive=$(gettext "Error: the archive top-level directory (%s) does not match the zonepath (%s).")
102174bbcaa8Se_tmpfile=$(gettext "Unable to create temporary file")
102274bbcaa8Se_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
1023e71ca95cSGerald Jelinekf_mkdir=$(gettext "Unable to create directory %s.")
1024e71ca95cSGerald Jelinekf_chmod=$(gettext "Unable to chmod directory %s.")
1025e71ca95cSGerald Jelinekf_chown=$(gettext "Unable to chown directory %s.")
102619b77901Sf_hwcap_info=$(gettext "HWCAP: %s\n")
102719b77901Sf_sanity_hwcap=$(gettext \
102819b77901S"The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\
102919b77901S"       The zone will not boot on this platform.  See the zone's\n"\
103019b77901S"       documentation for the recommended way to create the archive.")
103174bbcaa8S
10328c20418dSGerald Jelinekm_analyse_archive=$(gettext "Analysing the archive")
10338c20418dSGerald Jelinek
103474bbcaa8Snot_readable=$(gettext "Cannot read file '%s'")
103574bbcaa8Snot_flar=$(gettext "Input is not a flash archive")
103674bbcaa8Sbad_flar=$(gettext "Flash archive is a corrupt")
1037cec6066bSbad_zfs_flar=$(gettext "Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax.")
1038cec6066bSf_unpack_failed=$(gettext "Unpacking the archive failed")
103974bbcaa8Sunknown_archiver=$(gettext "Archiver %s is not supported")
104074bbcaa8Scmd_not_exec=$(gettext "Required command '%s' not executable!")
1041edfa49ffS
1042edfa49ffS#
1043edfa49ffS# Exit values used by the script, as #defined in <sys/zone.h>
1044edfa49ffS#
1045edfa49ffS#	ZONE_SUBPROC_OK
1046edfa49ffS#	===============
1047edfa49ffS#	Installation was successful
1048edfa49ffS#
1049edfa49ffS#	ZONE_SUBPROC_USAGE
1050edfa49ffS#	==================
1051edfa49ffS#	Improper arguments were passed, so print a usage message before exiting
1052edfa49ffS#
1053edfa49ffS#	ZONE_SUBPROC_NOTCOMPLETE
1054edfa49ffS#	========================
1055edfa49ffS#	Installation did not complete, but another installation attempt can be
1056edfa49ffS#	made without an uninstall
1057edfa49ffS#
1058edfa49ffS#	ZONE_SUBPROC_FATAL
1059edfa49ffS#	==================
1060edfa49ffS#	Installation failed and an uninstall will be required before another
1061edfa49ffS#	install can be attempted
1062edfa49ffS#
1063edfa49ffSZONE_SUBPROC_OK=0
1064edfa49ffSZONE_SUBPROC_USAGE=253
1065edfa49ffSZONE_SUBPROC_NOTCOMPLETE=254
1066edfa49ffSZONE_SUBPROC_FATAL=255
1067edfa49ffS
1068