xref: /illumos-gate/usr/src/lib/brand/shared/zone/common.ksh (revision 19b779014a4ce36fb75ab60afd585f5c586af44d)
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() {
46*19b77901S        typeset fmt="$1"
47*19b77901S        shift
48*19b77901S
49*19b77901S	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#
329*19b77901S# Perform validation and cleanup in the zoneroot after unpacking the archive.
330eba00995S#
331eba00995Spost_unpack()
332eba00995S{
333*19b77901S	#
334*19b77901S	# Check if the image was created with a valid libc.so.1.
335*19b77901S	#
336*19b77901S	hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1`
337*19b77901S	if (( $? != 0 )); then
338*19b77901S		vlog "$f_hwcap_info" "$hwcap"
339*19b77901S		fail_fatal "$f_sanity_hwcap"
340*19b77901S	fi
341*19b77901S
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
5548c20418dSGerald Jelinek#      of a physical sytem.  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.")
1026*19b77901Sf_hwcap_info=$(gettext "HWCAP: %s\n")
1027*19b77901Sf_sanity_hwcap=$(gettext \
1028*19b77901S"The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\
1029*19b77901S"       The zone will not boot on this platform.  See the zone's\n"\
1030*19b77901S"       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