1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
22# Use is subject to license terms.
23#
24
25#
26# Send the error message to the screen and to the logfile.
27#
28error()
29{
30        typeset fmt="$1"
31        shift
32
33        printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
34        [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
35}
36
37fatal()
38{
39        typeset fmt="$1"
40        shift
41
42	error "$fmt" "$@"
43	exit $EXIT_CODE
44}
45
46#
47# Send the provided printf()-style arguments to the screen and to the logfile.
48#
49log()
50{
51        typeset fmt="$1"
52        shift
53
54        printf "${MSG_PREFIX}${fmt}\n" "$@"
55        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
56}
57
58#
59# Print provided text to the screen if the shell variable "OPT_V" is set.
60# The text is always sent to the logfile.
61#
62vlog()
63{
64        typeset fmt="$1"
65        shift
66
67        [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
68        [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
69}
70
71# Validate that the directory is safe.
72safe_dir()
73{
74	typeset dir="$1"
75
76	if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
77		fatal "$e_baddir" "$dir"
78	fi
79}
80
81# Only make a copy if we haven't already done so.
82safe_backup()
83{
84	typeset src="$1"
85	typeset dst="$2"
86
87	if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
88		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
89	fi
90}
91
92# Make a copy even if the destination already exists.
93safe_copy()
94{
95	typeset src="$1"
96	typeset dst="$2"
97
98	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
99		/usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
100	fi
101}
102
103# Move a file
104safe_move()
105{
106	typeset src="$1"
107	typeset dst="$2"
108
109	if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
110		/usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
111	fi
112}
113
114#
115# Read zonecfg ipd and fs entries and save the relevant data, one entry per
116# line.
117# This assumes the properties from the zonecfg output, e.g.:
118#	inherit-pkg-dir:
119#		dir: /usr
120#	fs:
121#		dir: /opt
122#		special: /opt
123#		raw not specified
124#		type: lofs
125#		options: [noexec,ro,noatime]
126#
127# and it assumes the order of the fs properties as above.  This also saves the
128# inherit-pkg-dir patterns into the ipd.{cpio|pax} temporary files for
129# filtering while extracting the image into the zonepath.  We have to save the
130# IPD patterns in the appropriate format for filtering with the different
131# archivers and we don't know what format we'll get until after the flash
132# archive is unpacked.
133#
134get_fs_info()
135{
136	zonecfg -z $zonename info inherit-pkg-dir | \
137	    nawk -v ipdcpiof=$ipdcpiofile -v ipdpaxf=$ipdpaxfile '{
138		if ($1 == "dir:") {
139			dir=$2;
140			printf("%s lofs %s ro\n", dir, dir);
141
142			if (substr(dir, 1, 1) == "/") {
143				printf("%s\n", substr(dir, 2)) >> ipdcpiof
144				printf("%s/*\n", substr(dir, 2)) >> ipdcpiof
145			} else {
146				printf("%s\n", dir) >> ipdcpiof
147				printf("%s/*\n", dir) >> ipdcpiof
148			}
149
150			if (substr(dir, 1, 1) == "/") {
151				printf("%s ", substr(dir, 2)) >> ipdpaxf
152			} else {
153				printf("%s ", dir) >> ipdpaxf
154			}
155		}
156	}' >> $fstmpfile
157
158	zonecfg -z $zonename info fs | nawk '{
159		if ($1 == "options:") {
160			# Remove brackets.
161			options=substr($2, 2, length($2) - 2);
162			printf("%s %s %s %s\n", dir, type, special, options);
163		} else if ($1 == "dir:") {
164			dir=$2;
165		} else if ($1 == "special:") {
166			special=$2;
167		} else if ($1 == "type:") {
168			type=$2
169		}
170	}' >> $fstmpfile
171}
172
173#
174# Mount zonecfg fs entries into the zonepath.
175#
176mnt_fs()
177{
178	if [ ! -s $fstmpfile ]; then
179		return;
180	fi
181
182	# Sort the fs entries so we can handle nested mounts.
183	sort $fstmpfile | nawk -v zonepath=$zonepath '{
184		if (NF == 4)
185			options="-o " $4;
186		else
187			options=""
188
189		# Create the mount point.  Ignore errors since we might have
190		# a nested mount with a pre-existing mount point.
191		cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
192		system(cmd);
193
194		cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
195		    zonepath "/root" $1;
196		if (system(cmd) != 0) {
197			printf("command failed: %s\n", cmd);
198			exit 1;
199		}
200	}' >>$LOGFILE
201}
202
203#
204# Unmount zonecfg fs entries from the zonepath.
205#
206umnt_fs()
207{
208	if [ ! -s $fstmpfile ]; then
209		return;
210	fi
211
212	# Reverse sort the fs entries so we can handle nested unmounts.
213	sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
214		cmd="/usr/sbin/umount " zonepath "/root" $1
215		if (system(cmd) != 0) {
216			printf("command failed: %s\n", cmd);
217		}
218	}' >>$LOGFILE
219}
220
221#
222# Perform any cleanup in the zoneroot after unpacking the archive.
223#
224post_unpack()
225{
226	( cd "$ZONEROOT" && \
227	    find . \( -type b -o -type c \) -exec rm -f "{}" \; )
228}
229
230#
231# Determine flar compression style from identification file.
232#
233get_compression()
234{
235	typeset ident=$1
236	typeset line=$(grep "^files_compressed_method=" $ident)
237
238	print ${line##*=}
239}
240
241#
242# Determine flar archive style from identification file.
243#
244get_archiver()
245{
246        typeset ident=$1
247        typeset line=$(grep "^files_archived_method=" $ident)
248
249        print ${line##*=}
250}
251
252#
253# Unpack flar into current directory (which should be zoneroot).  The flash
254# archive is standard input.  See flash_archive(4) man page.
255#
256# We can't use "flar split" since it will only unpack into a directory called
257# "archive".  We need to unpack in place in order to properly handle nested
258# fs mounts within the zone root.  This function does the unpacking into the
259# current directory.
260#
261# This code is derived from the gen_split() function in /usr/sbin/flar so
262# we keep the same style as the original.
263#
264install_flar()
265{
266	typeset result
267        typeset archiver_command
268        typeset archiver_arguments
269
270	vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar"
271
272	# Read cookie
273	read -r input_line
274	if (( $? != 0 )); then
275		log "$not_readable" "$install_media"
276		return 1
277	fi
278	# The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
279	if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
280		log "$not_flar"
281		return 1
282	fi
283
284	while [ true ]
285	do
286		# We should always be at the start of a section here
287		read -r input_line
288		if [[ ${input_line%%=*} != "section_begin" ]]; then
289			log "$bad_flar"
290			return 1
291		fi
292		section_name=${input_line##*=}
293
294		# If we're at the archive, we're done skipping sections.
295		if [[ "$section_name" == "archive" ]]; then
296			break
297		fi
298
299		#
300		# Save identification section to a file so we can determine
301		# how to unpack the archive.
302		#
303		if [[ "$section_name" == "identification" ]]; then
304			/usr/bin/rm -f identification
305			while read -r input_line
306			do
307				if [[ ${input_line%%=*} == \
308				    "section_begin" ]]; then
309					/usr/bin/rm -f identification
310					log "$bad_flar"
311					return 1
312				fi
313
314				if [[ $input_line == \
315				    "section_end=$section_name" ]]; then
316					break;
317				fi
318				echo $input_line >> identification
319			done
320
321			continue
322		fi
323
324		#
325		# Otherwise skip past this section; read lines until detecting
326		# section_end.  According to flash_archive(4) we can have
327		# an arbitrary number of sections but the archive section
328		# must be last.
329		#
330		success=0
331		while read -r input_line
332		do
333			if [[ $input_line == "section_end=$section_name" ]];
334			then
335				success=1
336				break
337			fi
338			# Fail if we miss the end of the section
339			if [[ ${input_line%%=*} == "section_begin" ]]; then
340				/usr/bin/rm -f identification
341				log "$bad_flar"
342				return 1
343			fi
344		done
345		if (( $success == 0 )); then
346			#
347			# If we get here we read to the end of the file before
348			# seeing the end of the section we were reading.
349			#
350			/usr/bin/rm -f identification
351			log "$bad_flar"
352			return 1
353		fi
354	done
355
356	# Get the information needed to unpack the archive.
357	archiver=$(get_archiver identification)
358	if [[ $archiver == "pax" ]]; then
359		# pax archiver specified
360		archiver_command="/usr/bin/pax"
361		if [[ -s $ipdpaxfile ]]; then
362			archiver_arguments="-r -p e -c \
363			    $(/usr/bin/cat $ipdpaxfile)"
364		else
365			archiver_arguments="-r -p e"
366		fi
367	elif [[ $archiver == "cpio" || -z $archiver ]]; then
368		# cpio archived specified OR no archiver specified - use default
369		archiver_command="/usr/bin/cpio"
370		archiver_arguments="-icdumfE $ipdcpiofile"
371	else
372		# unknown archiver specified
373		log "$unknown_archiver" $archiver
374		return 1
375	fi
376
377	if [[ ! -x $archiver_command ]]; then
378		/usr/bin/rm -f identification
379		log "$cmd_not_exec" $archiver_command
380		return 1
381	fi
382
383	compression=$(get_compression identification)
384
385	# We're done with the identification file
386	/usr/bin/rm -f identification
387
388	# Extract archive
389	if [[ $compression == "compress" ]]; then
390		/usr/bin/zcat | \
391		    $archiver_command $archiver_arguments 2>/dev/null
392	else
393		$archiver_command $archiver_arguments 2>/dev/null
394	fi
395	result=$?
396
397	post_unpack
398
399	(( $result != 0 )) && return 1
400
401	return 0
402}
403
404#
405# Unpack cpio archive into zoneroot.
406#
407install_cpio()
408{
409	stage1=$1
410	archive=$2
411
412	cpioopts="-idmfE $ipdcpiofile"
413
414	vlog "cd \"$ZONEROOT\" && $stage1 \"$archive\" | cpio $cpioopts"
415
416	( cd "$ZONEROOT" && $stage1 "$archive" | cpio $cpioopts )
417	result=$?
418
419	post_unpack
420
421	return $result
422}
423
424#
425# Unpack pax archive into zoneroot.
426#
427install_pax()
428{
429	archive=$1
430
431	if [[ -s $ipdpaxfile ]]; then
432		filtopt="-c $(/usr/bin/cat $ipdpaxfile)"
433	fi
434
435	vlog "cd \"$ZONEROOT\" && pax -r -f \"$archive\" $filtopt"
436
437	( cd "$ZONEROOT" && pax -r -f "$archive" $filtopt )
438	result=$?
439
440	post_unpack
441
442	return $result
443}
444
445#
446# Unpack UFS dump into zoneroot.
447#
448install_ufsdump()
449{
450	archive=$1
451
452	vlog "cd \"$ZONEROOT\" && ufsrestore rf \"$archive\""
453
454	#
455	# ufsrestore goes interactive if you ^C it.  To prevent that,
456	# we make sure its stdin is not a terminal.
457	# Note that there is no way to filter inherit-pkg-dirs for a full
458	# restore so there will be warnings in the log file.
459	#
460	( cd "$ZONEROOT" && ufsrestore rf "$archive" < /dev/null )
461	result=$?
462
463	post_unpack
464
465	return $result
466}
467
468#
469# Copy directory hierarchy into zoneroot.
470#
471install_dir()
472{
473	source_dir=$1
474
475	cpioopts="-pdm"
476
477	first=1
478	filt=$(for i in $(cat $ipdpaxfile)
479		do
480			echo $i | egrep -s "/" && continue
481			if [[ $first == 1 ]]; then
482				printf "^%s" $i
483				first=0
484			else
485				printf "|^%s" $i
486			fi
487		done)
488
489	list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
490	flist=$(for i in $list
491	do
492		printf "%s " "$i"
493	done)
494	findopts="-xdev ( -type d -o -type f -o -type l ) -print"
495
496	vlog "cd \"$source_dir\" && find $flist $findopts | "
497	vlog "cpio $cpioopts \"$ZONEROOT\""
498
499	( cd "$source_dir" && find $flist $findopts | \
500	    cpio $cpioopts "$ZONEROOT" )
501	result=$?
502
503	post_unpack
504
505	return $result
506}
507
508#
509# This is a common function for laying down a zone image from a variety of
510# different sources.  This can be used to either install a fresh zone or as
511# part of zone migration during attach.
512#
513# The first argument specifies the type of image: archive, directory or stdin.
514# The second argument specifies the image itself.  In the case of stdin, the
515# second argument specifies the format of the stream (cpio, flar, etc.).
516# Any validation or post-processing on the image is done elsewhere.
517#
518# This function calls a 'sanity_check' function which must be provided by
519# the script which includes this code.
520#
521install_image()
522{
523	intype=$1
524	insrc=$2
525
526	if [[ -z "$intype" || -z "$insrc" ]]; then
527		return 1
528	fi
529
530	filetype="unknown"
531	filetypename="unknown"
532	stage1="cat"
533
534	if [[ "$intype" == "directory" ]]; then
535		if [[ "$insrc" == "-" ]]; then
536			# Indicates that the existing zonepath is prepopulated.
537			filetype="existing"
538			filetypename="existing"
539		else
540			if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then
541				fatal "$e_path_abs" "$insrc"
542			fi
543
544			if [[ ! -e "$insrc" ]]; then
545				log "$e_not_found" "$insrc"
546				fatal "$e_install_abort"
547			fi
548
549			if [[ ! -r "$insrc" ]]; then
550				log "$e_not_readable" "$insrc"
551				fatal "$e_install_abort"
552			fi
553
554			if [[ ! -d "$insrc" ]]; then
555				log "$e_not_dir"
556				fatal "$e_install_abort"
557			fi
558
559			sanity_check $insrc
560
561			filetype="directory"
562			filetypename="directory"
563		fi
564
565	else
566		# Common code for both archive and stdin stream.
567
568		if [[ "$intype" == "archive" ]]; then
569			if [[ ! -f "$insrc" ]]; then
570				log "$e_unknown_archive"
571				fatal "$e_install_abort"
572			fi
573			ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)"
574		else
575			# For intype == stdin, the insrc parameter specifies
576			# the stream format coming on stdin.
577			ftype="$insrc"
578			insrc="-"
579		fi
580
581		# Setup vars for the archive type we have.
582		case "$ftype" in
583		*cpio*)		filetype="cpio"
584				filetypename="cpio archive"
585			;;
586		*bzip2*)	filetype="bzip2"
587				filetypename="bzipped cpio archive"
588			;;
589		*gzip*)		filetype="gzip"
590				filetypename="gzipped cpio archive"
591			;;
592		*ufsdump*)	filetype="ufsdump"
593				filetypename="ufsdump archive"
594			;;
595		"flar")
596				filetype="flar"
597				filetypename="flash archive"
598			;;
599		"flash")
600				filetype="flar"
601				filetypename="flash archive"
602			;;
603		*Flash\ Archive*)
604				filetype="flar"
605				filetypename="flash archive"
606			;;
607		"tar")
608				filetype="tar"
609				filetypename="tar archive"
610			;;
611		*USTAR\ tar\ archive)
612				filetype="tar"
613				filetypename="tar archive"
614			;;
615		"pax")
616				filetype="xustar"
617				filetypename="pax (xustar) archive"
618			;;
619		*USTAR\ tar\ archive\ extended\ format*)
620				filetype="xustar"
621				filetypename="pax (xustar) archive"
622			;;
623		"zfs")
624				filetype="zfs"
625				filetypename="ZFS send stream"
626			;;
627		*ZFS\ snapshot\ stream*)
628				filetype="zfs"
629				filetypename="ZFS send stream"
630			;;
631		*)		log "$e_unknown_archive"
632				fatal "$e_install_abort"
633			;;
634		esac
635	fi
636
637	vlog "$filetypename"
638
639	# Check for a non-empty root if no '-d -' option.
640	if [[ "$filetype" != "existing" ]]; then
641		cnt=$(ls $ZONEROOT | wc -l)
642		if (( $cnt != 0 )); then
643			fatal "$e_root_full" "$ZONEROOT"
644		fi
645	fi
646
647	fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
648	if [[ -z "$fstmpfile" ]]; then
649		fatal "$e_tmpfile"
650	fi
651
652	# Make sure we always have the files holding the directories to filter
653	# out when extracting from a CPIO or PAX archive.  We'll add the fs
654	# entries to these files in get_fs_info() (there may be no IPDs for
655	# some brands but thats ok).
656	ipdcpiofile=$(/usr/bin/mktemp -t -p /var/tmp ipd.cpio.XXXXXX)
657	if [[ -z "$ipdcpiofile" ]]; then
658		rm -f $fstmpfile
659		fatal "$e_tmpfile"
660	fi
661
662	# In addition to the IPDs, also filter out these directories.
663	echo 'dev/*' >>$ipdcpiofile
664	echo 'devices/*' >>$ipdcpiofile
665	echo 'devices' >>$ipdcpiofile
666	echo 'proc/*' >>$ipdcpiofile
667	echo 'tmp/*' >>$ipdcpiofile
668	echo 'var/run/*' >>$ipdcpiofile
669	echo 'system/contract/*' >>$ipdcpiofile
670	echo 'system/object/*' >>$ipdcpiofile
671
672	ipdpaxfile=$(/usr/bin/mktemp -t -p /var/tmp ipd.pax.XXXXXX)
673	if [[ -z "$ipdpaxfile" ]]; then
674		rm -f $fstmpfile $ipdcpiofile
675		fatal "$e_tmpfile"
676	fi
677
678	printf "%s " \
679	    "dev devices proc tmp var/run system/contract system/object" \
680	    >>$ipdpaxfile
681
682	# Set up any fs mounts so the archive will install into the correct
683	# locations.
684	get_fs_info
685	mnt_fs
686	if (( $? != 0 )); then
687		umnt_fs >/dev/null 2>&1
688		rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
689		fatal "$mount_failed"
690	fi
691
692	if [[ "$filetype" == "existing" ]]; then
693		log "$no_installing"
694	else
695		log "$installing"
696	fi
697
698	#
699	# Install the image into the zonepath.
700	#
701	unpack_result=0
702	stage1="cat"
703	if [[ "$filetype" == "gzip" ]]; then
704		stage1="gzcat"
705		filetype="cpio"
706	elif [[ "$filetype" == "bzip2" ]]; then
707		stage1="bzcat"
708		filetype="cpio"
709	fi
710
711	if [[ "$filetype" == "cpio" ]]; then
712		install_cpio "$stage1" "$insrc"
713		unpack_result=$?
714
715	elif [[ "$filetype" == "flar" ]]; then
716		( cd "$ZONEROOT" && $stage1 $insrc | install_flar )
717		unpack_result=$?
718
719	elif [[ "$filetype" == "xustar" ]]; then
720		install_pax "$insrc"
721		unpack_result=$?
722
723	elif [[ "$filetype" = "tar" ]]; then
724		vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\""
725		( cd "$ZONEROOT" && tar -xf "$insrc" )
726		unpack_result=$?
727		post_unpack
728
729	elif [[ "$filetype" == "ufsdump" ]]; then
730		install_ufsdump "$insrc"
731		unpack_result=$?
732
733	elif [[ "$filetype" == "directory" ]]; then
734		install_dir "$insrc"
735		unpack_result=$?
736
737	elif [[ "$filetype" == "zfs" ]]; then
738		#
739		# Given a 'zfs send' stream file, receive the snapshot into
740		# the zone's dataset.  We're getting the original system's
741		# zonepath dataset.  Destroy the existing dataset created
742		# above since this recreates it.
743		#
744		if [[ -z "$DATASET" ]]; then
745			fatal "$f_nodataset"
746		fi
747		/usr/sbin/zfs destroy "$DATASET"
748		if (( $? != 0 )); then
749			log "$f_zfsdestroy" "$DATASET"
750		fi
751
752		vlog "$stage1 $insrc | zfs receive -F $DATASET"
753		( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET )
754		unpack_result=$?
755	fi
756
757	vlog "$unpack_done" $unpack_result
758
759	# Clean up any fs mounts used during unpacking.
760	umnt_fs
761	rm -f $fstmpfile $ipdcpiofile $ipdpaxfile
762
763	#
764	# If the archive was of a zone then the archive might have been made
765	# of the zonepath (single dir), inside the zonepath (dev, root, etc.,
766	# or just even just root) or inside the zonepath root (all the top
767	# level dirs).  Try to normalize these possibilities.
768	#
769	dirsize=$(ls $ZONEROOT | wc -l)
770	if [[ -d $ZONEROOT/root && -d $ZONEROOT/root/etc && \
771	    -d $ZONEROOT/root/var ]]; then
772		# The archive was made of the zoneroot.
773		mkdir -m 0755 $ZONEPATH/.attach_root
774		mv $ZONEROOT/root/* $ZONEPATH/.attach_root
775		mv $ZONEROOT/root/.[a-zA-Z]* $ZONEPATH/.attach_root \
776		    >/dev/null 2>&1
777		rm -rf $ZONEROOT
778		mv $ZONEPATH/.attach_root $ZONEROOT
779
780	elif (( $dirsize == 1 )); then
781		# The archive was made of the the zonepath.
782
783		dir=$(ls $ZONEROOT)
784
785		if [[ -d $ZONEROOT/$dir/root ]]; then
786			mkdir -m 0755 $ZONEPATH/.attach_root
787			mv $ZONEROOT/$dir/root/* $ZONEPATH/.attach_root
788			mv $ZONEROOT/$dir/root/.[a-zA-Z]* \
789			    $ZONEPATH/.attach_root >/dev/null 2>&1
790			rm -rf $ZONEROOT
791			mv $ZONEPATH/.attach_root $ZONEROOT
792		else
793			# We don't know where this archive was made.
794			fatal "$e_bad_zone_layout"
795		fi
796
797	elif [[ ! -d $ZONEROOT/etc ]]; then
798		# We were expecting that the archive was made inside the
799		# zoneroot but there's no etc dir, so we don't know where
800		# this archive was made.
801		fatal "$e_bad_zone_layout"
802	fi
803
804	chmod 700 $zonepath
805
806	# Verify this is a valid image.
807	sanity_check $ZONEROOT
808
809	return 0
810}
811
812# Setup i18n output
813TEXTDOMAIN="SUNW_OST_OSCMD"
814export TEXTDOMAIN
815
816e_baddir=$(gettext "Invalid '%s' directory within the zone")
817e_badfile=$(gettext "Invalid '%s' file within the zone")
818e_bad_zone_layout=$(gettext "Unexpected zone layout.")
819e_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
820e_not_found=$(gettext "%s: error: file or directory not found.")
821e_install_abort=$(gettext "Installation aborted.")
822e_not_readable=$(gettext "Cannot read directory '%s'")
823e_not_dir=$(gettext "Error: must be a directory")
824e_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.")
825e_tmpfile=$(gettext "Unable to create temporary file")
826e_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
827
828
829not_readable=$(gettext "Cannot read file '%s'")
830not_flar=$(gettext "Input is not a flash archive")
831bad_flar=$(gettext "Flash archive is a corrupt")
832unknown_archiver=$(gettext "Archiver %s is not supported")
833cmd_not_exec=$(gettext "Required command '%s' not executable!")
834
835#
836# Exit values used by the script, as #defined in <sys/zone.h>
837#
838#	ZONE_SUBPROC_OK
839#	===============
840#	Installation was successful
841#
842#	ZONE_SUBPROC_USAGE
843#	==================
844#	Improper arguments were passed, so print a usage message before exiting
845#
846#	ZONE_SUBPROC_NOTCOMPLETE
847#	========================
848#	Installation did not complete, but another installation attempt can be
849#	made without an uninstall
850#
851#	ZONE_SUBPROC_FATAL
852#	==================
853#	Installation failed and an uninstall will be required before another
854#	install can be attempted
855#
856ZONE_SUBPROC_OK=0
857ZONE_SUBPROC_USAGE=253
858ZONE_SUBPROC_NOTCOMPLETE=254
859ZONE_SUBPROC_FATAL=255
860
861