1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland 
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland  * Module:	zones.c
30*5c51f124SMoriah Waterland  * Group:	libinstzones
31*5c51f124SMoriah Waterland  * Description:	Provide "zones" interface for install consolidation code
32*5c51f124SMoriah Waterland  *
33*5c51f124SMoriah Waterland  * Public Methods:
34*5c51f124SMoriah Waterland  *  z_create_zone_admin_file - Given a location to create the file, and
35*5c51f124SMoriah Waterland  *	optionally an existing administration file, generate an
36*5c51f124SMoriah Waterland  *	administration file that can be used to perform "non-interactive"
37*5c51f124SMoriah Waterland  *	operations in a non-global zone.
38*5c51f124SMoriah Waterland  *  z_free_zone_list - free contents of zoneList_t object
39*5c51f124SMoriah Waterland  *  z_get_nonglobal_zone_list - return zoneList_t object describing all
40*5c51f124SMoriah Waterland  *	non-global native zones
41*5c51f124SMoriah Waterland  *  z_get_nonglobal_zone_list_by_brand - return zoneList_t object describing
42*5c51f124SMoriah Waterland  *      all non-global zones matching the list of zone brands passed in.
43*5c51f124SMoriah Waterland  *  z_free_brand_list - free contents of a zoneBrandList_t object
44*5c51f124SMoriah Waterland  *  z_make_brand_list - return a zoneBrandList_t object describing the list
45*5c51f124SMoriah Waterland  *	of all zone brands passed in.
46*5c51f124SMoriah Waterland  *  z_get_zonename - return the name of the current zone
47*5c51f124SMoriah Waterland  *  z_global_only - Determine if the global zone is only zone on the spec list
48*5c51f124SMoriah Waterland  *  z_lock_this_zone - lock this zone
49*5c51f124SMoriah Waterland  *  z_lock_zones - lock specified zones
50*5c51f124SMoriah Waterland  *  z_mount_in_lz - Mount global zone directory in specified zone's root file
51*5c51f124SMoriah Waterland  *	system
52*5c51f124SMoriah Waterland  *  z_non_global_zones_exist - Determine if any non-global native zones exist
53*5c51f124SMoriah Waterland  *  z_on_zone_spec - Determine if named zone is on the zone_spec list
54*5c51f124SMoriah Waterland  *  z_running_in_global_zone - Determine if running in the "global" zone
55*5c51f124SMoriah Waterland  *  z_set_output_functions - Link program specific output functions
56*5c51f124SMoriah Waterland  *  z_set_zone_root - Set root for zones library operations
57*5c51f124SMoriah Waterland  *  z_set_zone_spec - Set list of zones on which actions will be performed
58*5c51f124SMoriah Waterland  *  z_umount_lz_mount - Unmount directory mounted with z_mount_in_lz
59*5c51f124SMoriah Waterland  *  z_unlock_this_zone - unlock this zone
60*5c51f124SMoriah Waterland  *  z_unlock_zones - unlock specified zones
61*5c51f124SMoriah Waterland  *  z_verify_zone_spec - Verify list of zones on which actions will be performed
62*5c51f124SMoriah Waterland  *  z_zlist_change_zone_state - Change the current state of the specified zone
63*5c51f124SMoriah Waterland  *  z_zlist_get_current_state - Determine the current kernel state of the
64*5c51f124SMoriah Waterland  *	specified zone
65*5c51f124SMoriah Waterland  *  z_zlist_get_inherited_pkg_dirs - Determine directories inherited by
66*5c51f124SMoriah Waterland  *	specified zone
67*5c51f124SMoriah Waterland  *  z_zlist_get_original_state - Return the original kernal state of the
68*5c51f124SMoriah Waterland  *	specified zone
69*5c51f124SMoriah Waterland  *  z_zlist_get_scratch - Determine name of scratch zone
70*5c51f124SMoriah Waterland  *  z_zlist_get_zonename - Determine name of specified zone
71*5c51f124SMoriah Waterland  *  z_zlist_get_zonepath - Determine zonepath of specified zone
72*5c51f124SMoriah Waterland  *  z_zlist_restore_zone_state - Return the zone to the state it was originally
73*5c51f124SMoriah Waterland  *	in
74*5c51f124SMoriah Waterland  *  z_zone_exec - Execute a Unix command in a specified zone and return results
75*5c51f124SMoriah Waterland  *  z_zones_are_implemented - Determine if any zone operations can be performed
76*5c51f124SMoriah Waterland  *  z_is_zone_branded - determine if zone has a non-native brand
77*5c51f124SMoriah Waterland  *  z_is_zone_brand_in_list - determine if the zone's brand matches the
78*5c51f124SMoriah Waterland  *      brand list passed in.
79*5c51f124SMoriah Waterland  *  z_brands_are_implemented - determine if branded zones are implemented on
80*5c51f124SMoriah Waterland  *			this system
81*5c51f124SMoriah Waterland  */
82*5c51f124SMoriah Waterland 
83*5c51f124SMoriah Waterland /*
84*5c51f124SMoriah Waterland  * System includes
85*5c51f124SMoriah Waterland  */
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland #include <stdio.h>
88*5c51f124SMoriah Waterland #include <stdlib.h>
89*5c51f124SMoriah Waterland #include <unistd.h>
90*5c51f124SMoriah Waterland #include <fcntl.h>
91*5c51f124SMoriah Waterland #include <ctype.h>
92*5c51f124SMoriah Waterland #include <sys/types.h>
93*5c51f124SMoriah Waterland #include <sys/param.h>
94*5c51f124SMoriah Waterland #include <sys/sysmacros.h>
95*5c51f124SMoriah Waterland #include <string.h>
96*5c51f124SMoriah Waterland #include <strings.h>
97*5c51f124SMoriah Waterland #include <sys/stat.h>
98*5c51f124SMoriah Waterland #include <stdarg.h>
99*5c51f124SMoriah Waterland #include <limits.h>
100*5c51f124SMoriah Waterland #include <errno.h>
101*5c51f124SMoriah Waterland #include <time.h>
102*5c51f124SMoriah Waterland #include <signal.h>
103*5c51f124SMoriah Waterland #include <stropts.h>
104*5c51f124SMoriah Waterland #include <wait.h>
105*5c51f124SMoriah Waterland #include <zone.h>
106*5c51f124SMoriah Waterland #include <sys/brand.h>
107*5c51f124SMoriah Waterland #include <libintl.h>
108*5c51f124SMoriah Waterland #include <locale.h>
109*5c51f124SMoriah Waterland #include <libzonecfg.h>
110*5c51f124SMoriah Waterland #include <libcontract.h>
111*5c51f124SMoriah Waterland #include <sys/contract/process.h>
112*5c51f124SMoriah Waterland #include <sys/ctfs.h>
113*5c51f124SMoriah Waterland #include <assert.h>
114*5c51f124SMoriah Waterland #include <dlfcn.h>
115*5c51f124SMoriah Waterland #include <link.h>
116*5c51f124SMoriah Waterland #include <time.h>
117*5c51f124SMoriah Waterland 
118*5c51f124SMoriah Waterland /*
119*5c51f124SMoriah Waterland  * local includes
120*5c51f124SMoriah Waterland  */
121*5c51f124SMoriah Waterland 
122*5c51f124SMoriah Waterland /*
123*5c51f124SMoriah Waterland  * When _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA is defined,
124*5c51f124SMoriah Waterland  * instzones_lib.h will define the z_global_data structure.
125*5c51f124SMoriah Waterland  * Otherwise an extern to the structure is inserted.
126*5c51f124SMoriah Waterland  */
127*5c51f124SMoriah Waterland 
128*5c51f124SMoriah Waterland #define	_INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA
129*5c51f124SMoriah Waterland #include "instzones_lib.h"
130*5c51f124SMoriah Waterland #include "zones_strings.h"
131*5c51f124SMoriah Waterland 
132*5c51f124SMoriah Waterland /*
133*5c51f124SMoriah Waterland  * Private structures
134*5c51f124SMoriah Waterland  */
135*5c51f124SMoriah Waterland 
136*5c51f124SMoriah Waterland #define	CLUSTER_BRAND_NAME	"cluster"
137*5c51f124SMoriah Waterland 
138*5c51f124SMoriah Waterland /* maximum number of arguments to exec() call */
139*5c51f124SMoriah Waterland 
140*5c51f124SMoriah Waterland #define	UUID_FORMAT	"%02d%02d%02d%03d-%02d%02d%02d%d-%016llx"
141*5c51f124SMoriah Waterland 
142*5c51f124SMoriah Waterland /*
143*5c51f124SMoriah Waterland  * Library Function Prototypes
144*5c51f124SMoriah Waterland  */
145*5c51f124SMoriah Waterland 
146*5c51f124SMoriah Waterland #define	streq(a, b) (strcmp((a), (b)) == 0)
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland /*
149*5c51f124SMoriah Waterland  * Local Function Prototypes
150*5c51f124SMoriah Waterland  */
151*5c51f124SMoriah Waterland 
152*5c51f124SMoriah Waterland /*
153*5c51f124SMoriah Waterland  * global internal (private) declarations
154*5c51f124SMoriah Waterland  */
155*5c51f124SMoriah Waterland 
156*5c51f124SMoriah Waterland /*
157*5c51f124SMoriah Waterland  * *****************************************************************************
158*5c51f124SMoriah Waterland  * global external (public) functions
159*5c51f124SMoriah Waterland  * *****************************************************************************
160*5c51f124SMoriah Waterland  */
161*5c51f124SMoriah Waterland 
162*5c51f124SMoriah Waterland /*
163*5c51f124SMoriah Waterland  * Name:	z_create_zone_admin_file
164*5c51f124SMoriah Waterland  * Description:	Given a location to create the file, and optionally an existing
165*5c51f124SMoriah Waterland  *		administration file, generate an administration file that
166*5c51f124SMoriah Waterland  *		can be used to perform "non-interactive" operations in a
167*5c51f124SMoriah Waterland  *		non-global zone.
168*5c51f124SMoriah Waterland  * Arguments:	a_zoneAdminFilename - pointer to string representing the
169*5c51f124SMoriah Waterland  *			full path of zone admin file to create
170*5c51f124SMoriah Waterland  *		a_userAdminFilename - pointer to string representing the path
171*5c51f124SMoriah Waterland  *			to an existing "user" administration file - the
172*5c51f124SMoriah Waterland  *			administration file created will contain the
173*5c51f124SMoriah Waterland  *			settings contained in this file, modified as
174*5c51f124SMoriah Waterland  *			appropriate to supress any interaction;
175*5c51f124SMoriah Waterland  *			If this is == NULL then the administration file
176*5c51f124SMoriah Waterland  *			created will not contain any extra settings
177*5c51f124SMoriah Waterland  * Returns:	boolean_t
178*5c51f124SMoriah Waterland  *			== B_TRUE - admin file created
179*5c51f124SMoriah Waterland  *			== B_FALSE - failed to create admin file
180*5c51f124SMoriah Waterland  */
181*5c51f124SMoriah Waterland 
182*5c51f124SMoriah Waterland boolean_t
183*5c51f124SMoriah Waterland z_create_zone_admin_file(char *a_zoneAdminFilename, char *a_userAdminFilename)
184*5c51f124SMoriah Waterland {
185*5c51f124SMoriah Waterland 	FILE	*zFp;
186*5c51f124SMoriah Waterland 	FILE	*uFp = (FILE *)NULL;
187*5c51f124SMoriah Waterland 
188*5c51f124SMoriah Waterland 	/* entry assertions */
189*5c51f124SMoriah Waterland 
190*5c51f124SMoriah Waterland 	assert(a_zoneAdminFilename != NULL);
191*5c51f124SMoriah Waterland 	assert(*a_zoneAdminFilename != '\0');
192*5c51f124SMoriah Waterland 
193*5c51f124SMoriah Waterland 	/* create temporary zone admin file */
194*5c51f124SMoriah Waterland 
195*5c51f124SMoriah Waterland 	zFp = fopen(a_zoneAdminFilename, "w");
196*5c51f124SMoriah Waterland 	if (zFp == (FILE *)NULL) {
197*5c51f124SMoriah Waterland 		return (B_FALSE);
198*5c51f124SMoriah Waterland 	}
199*5c51f124SMoriah Waterland 
200*5c51f124SMoriah Waterland 	/* open user admin file if specified */
201*5c51f124SMoriah Waterland 
202*5c51f124SMoriah Waterland 	if (a_userAdminFilename != (char *)NULL) {
203*5c51f124SMoriah Waterland 		uFp = fopen(a_userAdminFilename, "r");
204*5c51f124SMoriah Waterland 	}
205*5c51f124SMoriah Waterland 
206*5c51f124SMoriah Waterland 	/* create default admin file for zone pkg ops if no user admin file */
207*5c51f124SMoriah Waterland 
208*5c51f124SMoriah Waterland 	if (uFp == (FILE *)NULL) {
209*5c51f124SMoriah Waterland 		/* create default admin file */
210*5c51f124SMoriah Waterland 		(void) fprintf(zFp, "action=nocheck\nauthentication=nocheck\n"
211*5c51f124SMoriah Waterland 		    "basedir=default\nconflict=nocheck\nidepend=nocheck\n"
212*5c51f124SMoriah Waterland 		    "instance=unique\npartial=nocheck\nrdepend=nocheck\n"
213*5c51f124SMoriah Waterland 		    "runlevel=nocheck\nsetuid=nocheck\nspace=nocheck\n"
214*5c51f124SMoriah Waterland 		    "mail=\n");
215*5c51f124SMoriah Waterland 	} else for (;;) {
216*5c51f124SMoriah Waterland 		/* copy user admin file substitute/change appropriate entries */
217*5c51f124SMoriah Waterland 		char	buf[LINE_MAX+1];
218*5c51f124SMoriah Waterland 		char	*p;
219*5c51f124SMoriah Waterland 
220*5c51f124SMoriah Waterland 		/* read next line of user admin file */
221*5c51f124SMoriah Waterland 
222*5c51f124SMoriah Waterland 		p = fgets(buf, sizeof (buf), uFp);
223*5c51f124SMoriah Waterland 		if (p == (char *)NULL) {
224*5c51f124SMoriah Waterland 			(void) fclose(uFp);
225*5c51f124SMoriah Waterland 			break;
226*5c51f124SMoriah Waterland 		}
227*5c51f124SMoriah Waterland 
228*5c51f124SMoriah Waterland 		/* modify / replace / accept as appropriate */
229*5c51f124SMoriah Waterland 
230*5c51f124SMoriah Waterland 		if (strncmp(buf, "instance=quit", 13) == 0) {
231*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "%s", "instance=unique\n");
232*5c51f124SMoriah Waterland 			/*LINTED*/
233*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "keystore=", 9) == 0) {
234*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "action=", 7) == 0) {
235*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "action=nocheck\n");
236*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "authentication=", 15) == 0) {
237*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "authentication=nocheck\n");
238*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "conflict=", 9) == 0) {
239*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "conflict=nocheck\n");
240*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "idepend=", 8) == 0) {
241*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "idepend=nocheck\n");
242*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "mail=", 5) == 0) {
243*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "mail=\n");
244*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "partial=", 8) == 0) {
245*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "partial=nocheck\n");
246*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "rdepend=", 8) == 0) {
247*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "rdepend=nocheck\n");
248*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "runlevel=", 9) == 0) {
249*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "runlevel=nocheck\n");
250*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "setuid=", 7) == 0) {
251*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "setuid=nocheck\n");
252*5c51f124SMoriah Waterland 		} else if (strncmp(buf, "space=", 6) == 0) {
253*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "space=nocheck\n");
254*5c51f124SMoriah Waterland 		} else {
255*5c51f124SMoriah Waterland 			(void) fprintf(zFp, "%s", buf);
256*5c51f124SMoriah Waterland 		}
257*5c51f124SMoriah Waterland 	}
258*5c51f124SMoriah Waterland 
259*5c51f124SMoriah Waterland 	/* close admin file and return success */
260*5c51f124SMoriah Waterland 
261*5c51f124SMoriah Waterland 	(void) fclose(zFp);
262*5c51f124SMoriah Waterland 	return (B_TRUE);
263*5c51f124SMoriah Waterland }
264*5c51f124SMoriah Waterland 
265*5c51f124SMoriah Waterland /*
266*5c51f124SMoriah Waterland  * Name:	z_brands_are_implemented
267*5c51f124SMoriah Waterland  * Description:	Determine if any branded zones may be present
268*5c51f124SMoriah Waterland  * Arguments:	void
269*5c51f124SMoriah Waterland  * Returns:	boolean_t
270*5c51f124SMoriah Waterland  *			== B_TRUE - branded zones are supported
271*5c51f124SMoriah Waterland  *			== B_FALSE - branded zones are not supported
272*5c51f124SMoriah Waterland  */
273*5c51f124SMoriah Waterland 
274*5c51f124SMoriah Waterland boolean_t
275*5c51f124SMoriah Waterland z_brands_are_implemented(void)
276*5c51f124SMoriah Waterland {
277*5c51f124SMoriah Waterland static	boolean_t	_brandsImplementedDetermined = B_FALSE;
278*5c51f124SMoriah Waterland static	boolean_t	_brandsAreImplemented = B_FALSE;
279*5c51f124SMoriah Waterland 
280*5c51f124SMoriah Waterland 	/* if availability has not been determined, cache it now */
281*5c51f124SMoriah Waterland 
282*5c51f124SMoriah Waterland 	if (!_brandsImplementedDetermined) {
283*5c51f124SMoriah Waterland 		_brandsImplementedDetermined = B_TRUE;
284*5c51f124SMoriah Waterland 		_brandsAreImplemented = _z_brands_are_implemented();
285*5c51f124SMoriah Waterland 		if (_brandsAreImplemented) {
286*5c51f124SMoriah Waterland 			_z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED);
287*5c51f124SMoriah Waterland 		} else {
288*5c51f124SMoriah Waterland 			_z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED);
289*5c51f124SMoriah Waterland 		}
290*5c51f124SMoriah Waterland 	}
291*5c51f124SMoriah Waterland 
292*5c51f124SMoriah Waterland 	/* return cached answer */
293*5c51f124SMoriah Waterland 
294*5c51f124SMoriah Waterland 	return (_brandsAreImplemented);
295*5c51f124SMoriah Waterland }
296*5c51f124SMoriah Waterland 
297*5c51f124SMoriah Waterland /*
298*5c51f124SMoriah Waterland  * Name:	z_free_zone_list
299*5c51f124SMoriah Waterland  * Description:	free contents of zoneList_t object
300*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object to free
301*5c51f124SMoriah Waterland  * Returns:	void
302*5c51f124SMoriah Waterland  */
303*5c51f124SMoriah Waterland 
304*5c51f124SMoriah Waterland void
305*5c51f124SMoriah Waterland z_free_zone_list(zoneList_t a_zlst)
306*5c51f124SMoriah Waterland {
307*5c51f124SMoriah Waterland 	int	numzones;
308*5c51f124SMoriah Waterland 
309*5c51f124SMoriah Waterland 	/* ignore empty list */
310*5c51f124SMoriah Waterland 
311*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
312*5c51f124SMoriah Waterland 		return;
313*5c51f124SMoriah Waterland 	}
314*5c51f124SMoriah Waterland 
315*5c51f124SMoriah Waterland 	/* free each entry in the zone list */
316*5c51f124SMoriah Waterland 
317*5c51f124SMoriah Waterland 	for (numzones = 0; a_zlst[numzones]._zlName != (char *)NULL;
318*5c51f124SMoriah Waterland 	    numzones++) {
319*5c51f124SMoriah Waterland 		zoneListElement_t *zelm = &a_zlst[numzones];
320*5c51f124SMoriah Waterland 
321*5c51f124SMoriah Waterland 		/* free zone name string */
322*5c51f124SMoriah Waterland 
323*5c51f124SMoriah Waterland 		free(zelm->_zlName);
324*5c51f124SMoriah Waterland 
325*5c51f124SMoriah Waterland 		/* free zonepath string */
326*5c51f124SMoriah Waterland 
327*5c51f124SMoriah Waterland 		if (zelm->_zlPath != (char *)NULL) {
328*5c51f124SMoriah Waterland 			free(zelm->_zlPath);
329*5c51f124SMoriah Waterland 		}
330*5c51f124SMoriah Waterland 
331*5c51f124SMoriah Waterland 		/* free list of inherited package directories */
332*5c51f124SMoriah Waterland 
333*5c51f124SMoriah Waterland 		if (zelm->_zlInheritedDirs != (char **)NULL) {
334*5c51f124SMoriah Waterland 			int	n;
335*5c51f124SMoriah Waterland 
336*5c51f124SMoriah Waterland 			for (n = 0;
337*5c51f124SMoriah Waterland 			    (zelm->_zlInheritedDirs)[n] != (char *)NULL;
338*5c51f124SMoriah Waterland 			    n++) {
339*5c51f124SMoriah Waterland 				(void) free((zelm->_zlInheritedDirs)[n]);
340*5c51f124SMoriah Waterland 			}
341*5c51f124SMoriah Waterland 			(void) free(zelm->_zlInheritedDirs);
342*5c51f124SMoriah Waterland 		}
343*5c51f124SMoriah Waterland 	}
344*5c51f124SMoriah Waterland 
345*5c51f124SMoriah Waterland 	/* free handle to the list */
346*5c51f124SMoriah Waterland 
347*5c51f124SMoriah Waterland 	free(a_zlst);
348*5c51f124SMoriah Waterland }
349*5c51f124SMoriah Waterland 
350*5c51f124SMoriah Waterland /*
351*5c51f124SMoriah Waterland  * Name:	z_get_nonglobal_zone_list
352*5c51f124SMoriah Waterland  * Description: return zoneList_t object describing all non-global
353*5c51f124SMoriah Waterland  *              native zones - branded zones are not included in list
354*5c51f124SMoriah Waterland  * Arguments:	None.
355*5c51f124SMoriah Waterland  * Returns:	zoneList_t
356*5c51f124SMoriah Waterland  *			== NULL - error, list could not be generated
357*5c51f124SMoriah Waterland  *			!= NULL - success, list returned
358*5c51f124SMoriah Waterland  * NOTE:    	Any zoneList_t returned is placed in new storage for the
359*5c51f124SMoriah Waterland  *		calling function. The caller must use 'z_free_zone_list' to
360*5c51f124SMoriah Waterland  *		dispose of the storage once the list is no longer needed.
361*5c51f124SMoriah Waterland  */
362*5c51f124SMoriah Waterland 
363*5c51f124SMoriah Waterland zoneList_t
364*5c51f124SMoriah Waterland z_get_nonglobal_zone_list(void)
365*5c51f124SMoriah Waterland {
366*5c51f124SMoriah Waterland 	zoneList_t zones;
367*5c51f124SMoriah Waterland 	zoneBrandList_t *brands = NULL;
368*5c51f124SMoriah Waterland 
369*5c51f124SMoriah Waterland 	if ((brands = z_make_brand_list("native cluster", " ")) == NULL)
370*5c51f124SMoriah Waterland 		return (NULL);
371*5c51f124SMoriah Waterland 
372*5c51f124SMoriah Waterland 	zones = z_get_nonglobal_zone_list_by_brand(brands);
373*5c51f124SMoriah Waterland 
374*5c51f124SMoriah Waterland 	z_free_brand_list(brands);
375*5c51f124SMoriah Waterland 
376*5c51f124SMoriah Waterland 	return (zones);
377*5c51f124SMoriah Waterland }
378*5c51f124SMoriah Waterland 
379*5c51f124SMoriah Waterland /*
380*5c51f124SMoriah Waterland  * Name:	z_free_brand_list
381*5c51f124SMoriah Waterland  * Description: Free contents of zoneBrandList_t object
382*5c51f124SMoriah Waterland  * Arguments:	brands - pointer to zoneBrandList_t object to free
383*5c51f124SMoriah Waterland  * Returns: 	void
384*5c51f124SMoriah Waterland  */
385*5c51f124SMoriah Waterland void
386*5c51f124SMoriah Waterland z_free_brand_list(zoneBrandList_t *brands)
387*5c51f124SMoriah Waterland {
388*5c51f124SMoriah Waterland 	while (brands != NULL) {
389*5c51f124SMoriah Waterland 		zoneBrandList_t *temp = brands;
390*5c51f124SMoriah Waterland 		free(brands->string_ptr);
391*5c51f124SMoriah Waterland 		brands = brands->next;
392*5c51f124SMoriah Waterland 		free(temp);
393*5c51f124SMoriah Waterland 	}
394*5c51f124SMoriah Waterland }
395*5c51f124SMoriah Waterland 
396*5c51f124SMoriah Waterland /*
397*5c51f124SMoriah Waterland  * Name:	z_make_brand_list
398*5c51f124SMoriah Waterland  * Description:	Given a string with a list of brand name delimited by
399*5c51f124SMoriah Waterland  *		the delimeter passed in, build a zoneBrandList_t structure
400*5c51f124SMoriah Waterland  *		with the list of brand names and return it to the caller.
401*5c51f124SMoriah Waterland  * Arguments:
402*5c51f124SMoriah Waterland  *		brands - const char pointer to string list of brand names
403*5c51f124SMoriah Waterland  *		delim - const char pointer to string representing the
404*5c51f124SMoriah Waterland  *			delimeter for brands string.
405*5c51f124SMoriah Waterland  * Returns:	zoneBrandList_t *
406*5c51f124SMoriah Waterland  *			== NULL - error, list could not be generated
407*5c51f124SMoriah Waterland  *			!= NULL - success, list returned
408*5c51f124SMoriah Waterland  * NOTE:	Any zoneBrandList_t returned is placed in new storage for the
409*5c51f124SMoriah Waterland  *		calling function.  The caller must use 'z_free_brand_list' to
410*5c51f124SMoriah Waterland  *		dispose of the storage once the list is no longer needed.
411*5c51f124SMoriah Waterland  */
412*5c51f124SMoriah Waterland zoneBrandList_t *
413*5c51f124SMoriah Waterland z_make_brand_list(const char *brands, const char *delim)
414*5c51f124SMoriah Waterland {
415*5c51f124SMoriah Waterland 	zoneBrandList_t *brand = NULL, *head = NULL;
416*5c51f124SMoriah Waterland 	char		*blist = NULL;
417*5c51f124SMoriah Waterland 	char		*str = NULL;
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 	if ((blist = strdup(brands)) == NULL)
420*5c51f124SMoriah Waterland 		return (NULL);
421*5c51f124SMoriah Waterland 
422*5c51f124SMoriah Waterland 	if ((str = strtok(blist, delim)) != NULL) {
423*5c51f124SMoriah Waterland 		if ((brand = (zoneBrandList_t *)
424*5c51f124SMoriah Waterland 		    malloc(sizeof (struct _zoneBrandList))) == NULL) {
425*5c51f124SMoriah Waterland 			return (NULL);
426*5c51f124SMoriah Waterland 		}
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 		head = brand;
429*5c51f124SMoriah Waterland 		brand->string_ptr = strdup(str);
430*5c51f124SMoriah Waterland 		brand->next = NULL;
431*5c51f124SMoriah Waterland 
432*5c51f124SMoriah Waterland 		while ((str = strtok(NULL, delim)) != NULL) {
433*5c51f124SMoriah Waterland 			if ((brand->next = (zoneBrandList_t *)
434*5c51f124SMoriah Waterland 			    malloc(sizeof (struct _zoneBrandList))) == NULL) {
435*5c51f124SMoriah Waterland 				return (NULL);
436*5c51f124SMoriah Waterland 			}
437*5c51f124SMoriah Waterland 
438*5c51f124SMoriah Waterland 			brand = brand->next;
439*5c51f124SMoriah Waterland 			brand->string_ptr = strdup(str);
440*5c51f124SMoriah Waterland 			brand->next = NULL;
441*5c51f124SMoriah Waterland 		}
442*5c51f124SMoriah Waterland 	}
443*5c51f124SMoriah Waterland 
444*5c51f124SMoriah Waterland 	free(blist);
445*5c51f124SMoriah Waterland 	return (head);
446*5c51f124SMoriah Waterland }
447*5c51f124SMoriah Waterland 
448*5c51f124SMoriah Waterland /*
449*5c51f124SMoriah Waterland  * Name:	z_get_nonglobal_zone_list_by_brand
450*5c51f124SMoriah Waterland  * Description: return zoneList_t object describing all non-global
451*5c51f124SMoriah Waterland  *              zones matching the list of brands passed in.
452*5c51f124SMoriah Waterland  * Arguments:	brands - The list of zone brands to look for.
453*5c51f124SMoriah Waterland  * Returns:	zoneList_t
454*5c51f124SMoriah Waterland  *			== NULL - error, list could not be generated
455*5c51f124SMoriah Waterland  *			!= NULL - success, list returned
456*5c51f124SMoriah Waterland  * NOTE:    	Any zoneList_t returned is placed in new storage for the
457*5c51f124SMoriah Waterland  *		calling function. The caller must use 'z_free_zone_list' to
458*5c51f124SMoriah Waterland  *		dispose of the storage once the list is no longer needed.
459*5c51f124SMoriah Waterland  */
460*5c51f124SMoriah Waterland zoneList_t
461*5c51f124SMoriah Waterland z_get_nonglobal_zone_list_by_brand(zoneBrandList_t *brands)
462*5c51f124SMoriah Waterland {
463*5c51f124SMoriah Waterland 	FILE		*zoneIndexFP;
464*5c51f124SMoriah Waterland 	int		numzones = 0;
465*5c51f124SMoriah Waterland 	struct zoneent	*ze;
466*5c51f124SMoriah Waterland 	zoneList_t	zlst = NULL;
467*5c51f124SMoriah Waterland 	FILE		*mapFP;
468*5c51f124SMoriah Waterland 	char		zonename[ZONENAME_MAX];
469*5c51f124SMoriah Waterland 	zone_spec_t	*zent;
470*5c51f124SMoriah Waterland 
471*5c51f124SMoriah Waterland 	/* if zones are not implemented, return empty list */
472*5c51f124SMoriah Waterland 
473*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
474*5c51f124SMoriah Waterland 		return ((zoneList_t)NULL);
475*5c51f124SMoriah Waterland 	}
476*5c51f124SMoriah Waterland 
477*5c51f124SMoriah Waterland 	/*
478*5c51f124SMoriah Waterland 	 * Open the zone index file.  Note that getzoneent_private() handles
479*5c51f124SMoriah Waterland 	 * NULL.
480*5c51f124SMoriah Waterland 	 */
481*5c51f124SMoriah Waterland 	zoneIndexFP = setzoneent();
482*5c51f124SMoriah Waterland 
483*5c51f124SMoriah Waterland 	mapFP = zonecfg_open_scratch("", B_FALSE);
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 	/* index file open; scan all zones; see if any are at least installed */
486*5c51f124SMoriah Waterland 
487*5c51f124SMoriah Waterland 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
488*5c51f124SMoriah Waterland 		zone_state_t	st;
489*5c51f124SMoriah Waterland 
490*5c51f124SMoriah Waterland 		/* skip the global zone */
491*5c51f124SMoriah Waterland 
492*5c51f124SMoriah Waterland 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
493*5c51f124SMoriah Waterland 			free(ze);
494*5c51f124SMoriah Waterland 			continue;
495*5c51f124SMoriah Waterland 		}
496*5c51f124SMoriah Waterland 
497*5c51f124SMoriah Waterland 		/*
498*5c51f124SMoriah Waterland 		 * skip any zones with brands not on the brand list
499*5c51f124SMoriah Waterland 		 */
500*5c51f124SMoriah Waterland 		if (!z_is_zone_brand_in_list(ze->zone_name, brands)) {
501*5c51f124SMoriah Waterland 			free(ze);
502*5c51f124SMoriah Waterland 			continue;
503*5c51f124SMoriah Waterland 		}
504*5c51f124SMoriah Waterland 
505*5c51f124SMoriah Waterland 		/*
506*5c51f124SMoriah Waterland 		 * If the user specified an explicit zone list, then ignore any
507*5c51f124SMoriah Waterland 		 * zones that aren't on that list.
508*5c51f124SMoriah Waterland 		 */
509*5c51f124SMoriah Waterland 		if ((zent = _z_global_data._zone_spec) != NULL) {
510*5c51f124SMoriah Waterland 			while (zent != NULL) {
511*5c51f124SMoriah Waterland 				if (strcmp(zent->zl_name, ze->zone_name) == 0)
512*5c51f124SMoriah Waterland 					break;
513*5c51f124SMoriah Waterland 				zent = zent->zl_next;
514*5c51f124SMoriah Waterland 			}
515*5c51f124SMoriah Waterland 			if (zent == NULL) {
516*5c51f124SMoriah Waterland 				free(ze);
517*5c51f124SMoriah Waterland 				continue;
518*5c51f124SMoriah Waterland 			}
519*5c51f124SMoriah Waterland 		}
520*5c51f124SMoriah Waterland 
521*5c51f124SMoriah Waterland 		/* non-global zone: create entry for this zone */
522*5c51f124SMoriah Waterland 
523*5c51f124SMoriah Waterland 		if (numzones == 0) {
524*5c51f124SMoriah Waterland 			zlst = (zoneList_t)_z_calloc(
525*5c51f124SMoriah Waterland 			    sizeof (zoneListElement_t)*2);
526*5c51f124SMoriah Waterland 		} else {
527*5c51f124SMoriah Waterland 			zlst = (zoneList_t)_z_realloc(zlst,
528*5c51f124SMoriah Waterland 			    sizeof (zoneListElement_t)*(numzones+2));
529*5c51f124SMoriah Waterland 			(void) memset(&zlst[numzones], 0L,
530*5c51f124SMoriah Waterland 			    sizeof (zoneListElement_t)*2);
531*5c51f124SMoriah Waterland 		}
532*5c51f124SMoriah Waterland 
533*5c51f124SMoriah Waterland 		/*
534*5c51f124SMoriah Waterland 		 * remember the zone name, zonepath and the current
535*5c51f124SMoriah Waterland 		 * zone state of the zone.
536*5c51f124SMoriah Waterland 		 */
537*5c51f124SMoriah Waterland 		zlst[numzones]._zlName = _z_strdup(ze->zone_name);
538*5c51f124SMoriah Waterland 		zlst[numzones]._zlPath = _z_strdup(ze->zone_path);
539*5c51f124SMoriah Waterland 		zlst[numzones]._zlOrigInstallState = ze->zone_state;
540*5c51f124SMoriah Waterland 		zlst[numzones]._zlCurrInstallState = ze->zone_state;
541*5c51f124SMoriah Waterland 
542*5c51f124SMoriah Waterland 		/* get the zone kernel status */
543*5c51f124SMoriah Waterland 
544*5c51f124SMoriah Waterland 		if (zone_get_state(ze->zone_name, &st) != Z_OK) {
545*5c51f124SMoriah Waterland 			st = ZONE_STATE_INCOMPLETE;
546*5c51f124SMoriah Waterland 		}
547*5c51f124SMoriah Waterland 
548*5c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_NGZ_LIST_STATES,
549*5c51f124SMoriah Waterland 		    ze->zone_name, ze->zone_state, st);
550*5c51f124SMoriah Waterland 
551*5c51f124SMoriah Waterland 		/*
552*5c51f124SMoriah Waterland 		 * For a scratch zone, we need to know the kernel zone name.
553*5c51f124SMoriah Waterland 		 */
554*5c51f124SMoriah Waterland 		if (zonecfg_in_alt_root() && mapFP != NULL &&
555*5c51f124SMoriah Waterland 		    zonecfg_find_scratch(mapFP, ze->zone_name,
556*5c51f124SMoriah Waterland 		    zonecfg_get_root(), zonename, sizeof (zonename)) != -1) {
557*5c51f124SMoriah Waterland 			free(zlst[numzones]._zlScratchName);
558*5c51f124SMoriah Waterland 			zlst[numzones]._zlScratchName = _z_strdup(zonename);
559*5c51f124SMoriah Waterland 		}
560*5c51f124SMoriah Waterland 
561*5c51f124SMoriah Waterland 		/*
562*5c51f124SMoriah Waterland 		 * remember the current kernel status of the zone.
563*5c51f124SMoriah Waterland 		 */
564*5c51f124SMoriah Waterland 
565*5c51f124SMoriah Waterland 		zlst[numzones]._zlOrigKernelStatus = st;
566*5c51f124SMoriah Waterland 		zlst[numzones]._zlCurrKernelStatus = st;
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 		zlst[numzones]._zlInheritedDirs =
569*5c51f124SMoriah Waterland 		    _z_get_inherited_dirs(ze->zone_name);
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 		numzones++;
572*5c51f124SMoriah Waterland 		free(ze);
573*5c51f124SMoriah Waterland 	}
574*5c51f124SMoriah Waterland 
575*5c51f124SMoriah Waterland 	/* close the index file */
576*5c51f124SMoriah Waterland 	endzoneent(zoneIndexFP);
577*5c51f124SMoriah Waterland 
578*5c51f124SMoriah Waterland 	if (mapFP != NULL)
579*5c51f124SMoriah Waterland 		zonecfg_close_scratch(mapFP);
580*5c51f124SMoriah Waterland 
581*5c51f124SMoriah Waterland 	/* return generated list */
582*5c51f124SMoriah Waterland 
583*5c51f124SMoriah Waterland 	return (zlst);
584*5c51f124SMoriah Waterland }
585*5c51f124SMoriah Waterland 
586*5c51f124SMoriah Waterland /*
587*5c51f124SMoriah Waterland  * Name:	z_get_zonename
588*5c51f124SMoriah Waterland  * Description:	return the name of the current zone
589*5c51f124SMoriah Waterland  * Arguments:	void
590*5c51f124SMoriah Waterland  * Returns:	char *
591*5c51f124SMoriah Waterland  *			- pointer to string representing the name of the current
592*5c51f124SMoriah Waterland  *			zone
593*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
594*5c51f124SMoriah Waterland  *		calling function. The caller must use 'Free' to dispose
595*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
596*5c51f124SMoriah Waterland  */
597*5c51f124SMoriah Waterland 
598*5c51f124SMoriah Waterland char *
599*5c51f124SMoriah Waterland z_get_zonename(void)
600*5c51f124SMoriah Waterland {
601*5c51f124SMoriah Waterland 	ssize_t		zonenameLen;
602*5c51f124SMoriah Waterland 	char		zonename[ZONENAME_MAX];
603*5c51f124SMoriah Waterland 	zoneid_t	zoneid = (zoneid_t)-1;
604*5c51f124SMoriah Waterland 
605*5c51f124SMoriah Waterland 	/* if zones are not implemented, return "" */
606*5c51f124SMoriah Waterland 
607*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
608*5c51f124SMoriah Waterland 		return (_z_strdup(""));
609*5c51f124SMoriah Waterland 	}
610*5c51f124SMoriah Waterland 
611*5c51f124SMoriah Waterland 	/* get the zone i.d. of the current zone */
612*5c51f124SMoriah Waterland 
613*5c51f124SMoriah Waterland 	zoneid = getzoneid();
614*5c51f124SMoriah Waterland 
615*5c51f124SMoriah Waterland 	/* get the name of the current zone */
616*5c51f124SMoriah Waterland 
617*5c51f124SMoriah Waterland 	zonenameLen = getzonenamebyid(zoneid, zonename, sizeof (zonename));
618*5c51f124SMoriah Waterland 
619*5c51f124SMoriah Waterland 	/* return "" if could not get zonename */
620*5c51f124SMoriah Waterland 
621*5c51f124SMoriah Waterland 	if (zonenameLen < 1) {
622*5c51f124SMoriah Waterland 		return (_z_strdup(""));
623*5c51f124SMoriah Waterland 	}
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland 	return (_z_strdup(zonename));
626*5c51f124SMoriah Waterland }
627*5c51f124SMoriah Waterland 
628*5c51f124SMoriah Waterland /*
629*5c51f124SMoriah Waterland  * Name:	z_global_only
630*5c51f124SMoriah Waterland  * Description:	Determine if the global zone is only zone on the spec list.
631*5c51f124SMoriah Waterland  * Arguments:	None
632*5c51f124SMoriah Waterland  * Returns:	B_TRUE if global zone is the only zone on the list,
633*5c51f124SMoriah Waterland  *		B_FALSE otherwise.
634*5c51f124SMoriah Waterland  */
635*5c51f124SMoriah Waterland 
636*5c51f124SMoriah Waterland boolean_t
637*5c51f124SMoriah Waterland z_global_only(void)
638*5c51f124SMoriah Waterland {
639*5c51f124SMoriah Waterland 	/* return true if zones are not implemented - treate as global zone */
640*5c51f124SMoriah Waterland 
641*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
642*5c51f124SMoriah Waterland 		return (B_TRUE);
643*5c51f124SMoriah Waterland 	}
644*5c51f124SMoriah Waterland 
645*5c51f124SMoriah Waterland 	/* return true if this is the global zone */
646*5c51f124SMoriah Waterland 
647*5c51f124SMoriah Waterland 	if (_z_global_data._zone_spec != NULL &&
648*5c51f124SMoriah Waterland 	    _z_global_data._zone_spec->zl_next == NULL &&
649*5c51f124SMoriah Waterland 	    strcmp(_z_global_data._zone_spec->zl_name, GLOBAL_ZONENAME) == 0) {
650*5c51f124SMoriah Waterland 		return (B_TRUE);
651*5c51f124SMoriah Waterland 	}
652*5c51f124SMoriah Waterland 
653*5c51f124SMoriah Waterland 	/* return false - not the global zone */
654*5c51f124SMoriah Waterland 
655*5c51f124SMoriah Waterland 	return (B_FALSE);
656*5c51f124SMoriah Waterland }
657*5c51f124SMoriah Waterland 
658*5c51f124SMoriah Waterland /*
659*5c51f124SMoriah Waterland  * Name:	z_lock_this_zone
660*5c51f124SMoriah Waterland  * Description:	lock this zone
661*5c51f124SMoriah Waterland  * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
662*5c51f124SMoriah Waterland  *			Flags indicating which locks to acquire
663*5c51f124SMoriah Waterland  * Returns:	boolean_t
664*5c51f124SMoriah Waterland  *			== B_TRUE - success specified locks acquired
665*5c51f124SMoriah Waterland  *			== B_FALSE - failure specified locks not acquired
666*5c51f124SMoriah Waterland  * NOTE: the lock objects for "this zone" are maintained internally.
667*5c51f124SMoriah Waterland  */
668*5c51f124SMoriah Waterland 
669*5c51f124SMoriah Waterland boolean_t
670*5c51f124SMoriah Waterland z_lock_this_zone(ZLOCKS_T a_lflags)
671*5c51f124SMoriah Waterland {
672*5c51f124SMoriah Waterland 	boolean_t	b;
673*5c51f124SMoriah Waterland 	char		*zoneName;
674*5c51f124SMoriah Waterland 	pid_t		pid = (pid_t)0;
675*5c51f124SMoriah Waterland 
676*5c51f124SMoriah Waterland 	/* entry assertions */
677*5c51f124SMoriah Waterland 
678*5c51f124SMoriah Waterland 	assert(a_lflags != ZLOCKS_NONE);
679*5c51f124SMoriah Waterland 
680*5c51f124SMoriah Waterland 	/* entry debugging info */
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_LCK_THIS, a_lflags);
683*5c51f124SMoriah Waterland 
684*5c51f124SMoriah Waterland 	zoneName = z_get_zonename();
685*5c51f124SMoriah Waterland 	pid = getpid();
686*5c51f124SMoriah Waterland 
687*5c51f124SMoriah Waterland 	/* lock zone administration */
688*5c51f124SMoriah Waterland 
689*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
690*5c51f124SMoriah Waterland 		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
691*5c51f124SMoriah Waterland 		    zoneName, LOBJ_ZONEADMIN, pid,
692*5c51f124SMoriah Waterland 		    MSG_ZONES_LCK_THIS_ZONEADM,
693*5c51f124SMoriah Waterland 		    ERR_ZONES_LCK_THIS_ZONEADM);
694*5c51f124SMoriah Waterland 		if (!b) {
695*5c51f124SMoriah Waterland 			(void) free(zoneName);
696*5c51f124SMoriah Waterland 			return (B_FALSE);
697*5c51f124SMoriah Waterland 		}
698*5c51f124SMoriah Waterland 	}
699*5c51f124SMoriah Waterland 
700*5c51f124SMoriah Waterland 	/* lock package administration always */
701*5c51f124SMoriah Waterland 
702*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
703*5c51f124SMoriah Waterland 		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
704*5c51f124SMoriah Waterland 		    zoneName, LOBJ_PKGADMIN, pid,
705*5c51f124SMoriah Waterland 		    MSG_ZONES_LCK_THIS_PKGADM,
706*5c51f124SMoriah Waterland 		    ERR_ZONES_LCK_THIS_PKGADM);
707*5c51f124SMoriah Waterland 		if (!b) {
708*5c51f124SMoriah Waterland 			(void) z_unlock_this_zone(a_lflags);
709*5c51f124SMoriah Waterland 			(void) free(zoneName);
710*5c51f124SMoriah Waterland 			return (B_FALSE);
711*5c51f124SMoriah Waterland 		}
712*5c51f124SMoriah Waterland 	}
713*5c51f124SMoriah Waterland 
714*5c51f124SMoriah Waterland 	/* lock patch administration always */
715*5c51f124SMoriah Waterland 
716*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PATCH_ADMIN) {
717*5c51f124SMoriah Waterland 		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
718*5c51f124SMoriah Waterland 		    zoneName, LOBJ_PATCHADMIN, pid,
719*5c51f124SMoriah Waterland 		    MSG_ZONES_LCK_THIS_PATCHADM,
720*5c51f124SMoriah Waterland 		    ERR_ZONES_LCK_THIS_PATCHADM);
721*5c51f124SMoriah Waterland 		if (!b) {
722*5c51f124SMoriah Waterland 			(void) z_unlock_this_zone(a_lflags);
723*5c51f124SMoriah Waterland 			(void) free(zoneName);
724*5c51f124SMoriah Waterland 			return (B_FALSE);
725*5c51f124SMoriah Waterland 		}
726*5c51f124SMoriah Waterland 	}
727*5c51f124SMoriah Waterland 
728*5c51f124SMoriah Waterland 	(void) free(zoneName);
729*5c51f124SMoriah Waterland 
730*5c51f124SMoriah Waterland 	return (B_TRUE);
731*5c51f124SMoriah Waterland }
732*5c51f124SMoriah Waterland 
733*5c51f124SMoriah Waterland /*
734*5c51f124SMoriah Waterland  * Name:	z_lock_zones
735*5c51f124SMoriah Waterland  * Description:	lock specified zones
736*5c51f124SMoriah Waterland  * Arguments:	a_zlst - zoneList_t object describing zones to lock
737*5c51f124SMoriah Waterland  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
738*5c51f124SMoriah Waterland  *			Flags indicating which locks to acquire
739*5c51f124SMoriah Waterland  * Returns:	boolean_t
740*5c51f124SMoriah Waterland  *			== B_TRUE - success, zones locked
741*5c51f124SMoriah Waterland  *			== B_FALSE - failure, zones not locked
742*5c51f124SMoriah Waterland  */
743*5c51f124SMoriah Waterland 
744*5c51f124SMoriah Waterland boolean_t
745*5c51f124SMoriah Waterland z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
746*5c51f124SMoriah Waterland {
747*5c51f124SMoriah Waterland 	boolean_t	b;
748*5c51f124SMoriah Waterland 	int		i;
749*5c51f124SMoriah Waterland 
750*5c51f124SMoriah Waterland 	/* entry assertions */
751*5c51f124SMoriah Waterland 
752*5c51f124SMoriah Waterland 	assert(a_lflags != ZLOCKS_NONE);
753*5c51f124SMoriah Waterland 
754*5c51f124SMoriah Waterland 	/* entry debugging info */
755*5c51f124SMoriah Waterland 
756*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags);
757*5c51f124SMoriah Waterland 
758*5c51f124SMoriah Waterland 	/* if zones are not implemented, return TRUE */
759*5c51f124SMoriah Waterland 
760*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
761*5c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP);
762*5c51f124SMoriah Waterland 		return (B_TRUE);
763*5c51f124SMoriah Waterland 	}
764*5c51f124SMoriah Waterland 
765*5c51f124SMoriah Waterland 	/* lock this zone first before locking other zones */
766*5c51f124SMoriah Waterland 
767*5c51f124SMoriah Waterland 	b = z_lock_this_zone(a_lflags);
768*5c51f124SMoriah Waterland 	if (b == B_FALSE) {
769*5c51f124SMoriah Waterland 		return (b);
770*5c51f124SMoriah Waterland 	}
771*5c51f124SMoriah Waterland 
772*5c51f124SMoriah Waterland 	/* ignore empty list */
773*5c51f124SMoriah Waterland 
774*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
775*5c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES);
776*5c51f124SMoriah Waterland 		return (B_FALSE);
777*5c51f124SMoriah Waterland 	}
778*5c51f124SMoriah Waterland 
779*5c51f124SMoriah Waterland 	/* zones exist */
780*5c51f124SMoriah Waterland 
781*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST);
782*5c51f124SMoriah Waterland 
783*5c51f124SMoriah Waterland 	/*
784*5c51f124SMoriah Waterland 	 * lock each listed zone that is currently running
785*5c51f124SMoriah Waterland 	 */
786*5c51f124SMoriah Waterland 
787*5c51f124SMoriah Waterland 	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
788*5c51f124SMoriah Waterland 		/* ignore zone if already locked */
789*5c51f124SMoriah Waterland 		if (a_zlst[i]._zlStatus & ZST_LOCKED) {
790*5c51f124SMoriah Waterland 			continue;
791*5c51f124SMoriah Waterland 		}
792*5c51f124SMoriah Waterland 
793*5c51f124SMoriah Waterland 		/* ignore zone if not running */
794*5c51f124SMoriah Waterland 		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
795*5c51f124SMoriah Waterland 		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
796*5c51f124SMoriah Waterland 			continue;
797*5c51f124SMoriah Waterland 		}
798*5c51f124SMoriah Waterland 
799*5c51f124SMoriah Waterland 		/*
800*5c51f124SMoriah Waterland 		 * mark zone locked - if interrupted out during lock, an attempt
801*5c51f124SMoriah Waterland 		 * will be made to release the lock
802*5c51f124SMoriah Waterland 		 */
803*5c51f124SMoriah Waterland 		a_zlst[i]._zlStatus |= ZST_LOCKED;
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 		/* lock this zone */
806*5c51f124SMoriah Waterland 		b = _z_lock_zone(&a_zlst[i], a_lflags);
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland 		/* on failure unlock all zones and return error */
809*5c51f124SMoriah Waterland 		if (b != B_TRUE) {
810*5c51f124SMoriah Waterland 			_z_program_error(ERR_ZONES_LCK_ZONES_FAILED,
811*5c51f124SMoriah Waterland 			    a_zlst[i]._zlName);
812*5c51f124SMoriah Waterland 			(void) z_unlock_zones(a_zlst, a_lflags);
813*5c51f124SMoriah Waterland 			return (B_FALSE);
814*5c51f124SMoriah Waterland 		}
815*5c51f124SMoriah Waterland 	}
816*5c51f124SMoriah Waterland 
817*5c51f124SMoriah Waterland 	/* success */
818*5c51f124SMoriah Waterland 
819*5c51f124SMoriah Waterland 	return (B_TRUE);
820*5c51f124SMoriah Waterland }
821*5c51f124SMoriah Waterland 
822*5c51f124SMoriah Waterland /*
823*5c51f124SMoriah Waterland  * Name:	z_mount_in_lz
824*5c51f124SMoriah Waterland  * Description:	Mount global zone directory in specified zone's root file system
825*5c51f124SMoriah Waterland  * Arguments:	r_lzMountPoint - pointer to handle to string - on success, the
826*5c51f124SMoriah Waterland  *			full path to the mount point relative to the global zone
827*5c51f124SMoriah Waterland  *			root file system is returned here - this is needed to
828*5c51f124SMoriah Waterland  *			unmount the directory when it is no longer needed
829*5c51f124SMoriah Waterland  *		r_lzRootPath - pointer to handle to string - on success, the
830*5c51f124SMoriah Waterland  *			full path to the mount point relative to the specified
831*5c51f124SMoriah Waterland  *			zone's root file system is returned here - this is
832*5c51f124SMoriah Waterland  *			passed to any command executing in the specified zone to
833*5c51f124SMoriah Waterland  *			access the directory mounted
834*5c51f124SMoriah Waterland  *		a_zoneName - pointer to string representing the name of the zone
835*5c51f124SMoriah Waterland  *			to mount the specified global zone directory in
836*5c51f124SMoriah Waterland  *		a_gzPath - pointer to string representing the full absolute path
837*5c51f124SMoriah Waterland  *			of the global zone directory to LOFS mount inside of the
838*5c51f124SMoriah Waterland  *			specified non-global zone
839*5c51f124SMoriah Waterland  *		a_mountPointPrefix - pointer to string representing the prefix
840*5c51f124SMoriah Waterland  *			to be used when creating the mount point name in the
841*5c51f124SMoriah Waterland  *			specified zone's root directory
842*5c51f124SMoriah Waterland  * Returns:	boolean_t
843*5c51f124SMoriah Waterland  *			== B_TRUE - global zone directory mounted successfully
844*5c51f124SMoriah Waterland  *			== B_FALSE - failed to mount directory in specified zone
845*5c51f124SMoriah Waterland  * NOTE:    	Any strings returned is placed in new storage for the
846*5c51f124SMoriah Waterland  *		calling function. The caller must use 'Free' to dispose
847*5c51f124SMoriah Waterland  *		of the storage once the strings are no longer needed.
848*5c51f124SMoriah Waterland  */
849*5c51f124SMoriah Waterland 
850*5c51f124SMoriah Waterland boolean_t
851*5c51f124SMoriah Waterland z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName,
852*5c51f124SMoriah Waterland 	char *a_gzPath, char *a_mountPointPrefix)
853*5c51f124SMoriah Waterland {
854*5c51f124SMoriah Waterland 	char		lzRootPath[MAXPATHLEN] = {'\0'};
855*5c51f124SMoriah Waterland 	char		uuid[MAXPATHLEN] = {'\0'};
856*5c51f124SMoriah Waterland 	char		gzMountPoint[MAXPATHLEN] = {'\0'};
857*5c51f124SMoriah Waterland 	char		lzMountPoint[MAXPATHLEN] = {'\0'};
858*5c51f124SMoriah Waterland 	hrtime_t	hretime;
859*5c51f124SMoriah Waterland 	int		err;
860*5c51f124SMoriah Waterland 	int		slen;
861*5c51f124SMoriah Waterland 	struct tm	tstruct;
862*5c51f124SMoriah Waterland 	time_t		thetime;
863*5c51f124SMoriah Waterland 	zoneid_t	zid;
864*5c51f124SMoriah Waterland 
865*5c51f124SMoriah Waterland 	/* entry assertions */
866*5c51f124SMoriah Waterland 
867*5c51f124SMoriah Waterland 	assert(a_zoneName != (char *)NULL);
868*5c51f124SMoriah Waterland 	assert(*a_zoneName != '\0');
869*5c51f124SMoriah Waterland 	assert(a_gzPath != (char *)NULL);
870*5c51f124SMoriah Waterland 	assert(*a_gzPath != '\0');
871*5c51f124SMoriah Waterland 	assert(r_lzMountPoint != (char **)NULL);
872*5c51f124SMoriah Waterland 	assert(r_lzRootPath != (char **)NULL);
873*5c51f124SMoriah Waterland 
874*5c51f124SMoriah Waterland 	/* entry debugging info */
875*5c51f124SMoriah Waterland 
876*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath);
877*5c51f124SMoriah Waterland 
878*5c51f124SMoriah Waterland 	/* reset returned non-global zone mount point path handle */
879*5c51f124SMoriah Waterland 
880*5c51f124SMoriah Waterland 	*r_lzMountPoint = (char *)NULL;
881*5c51f124SMoriah Waterland 	*r_lzRootPath = (char *)NULL;
882*5c51f124SMoriah Waterland 
883*5c51f124SMoriah Waterland 	/* if zones are not implemented, return FALSE */
884*5c51f124SMoriah Waterland 
885*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
886*5c51f124SMoriah Waterland 		return (B_FALSE);
887*5c51f124SMoriah Waterland 	}
888*5c51f124SMoriah Waterland 
889*5c51f124SMoriah Waterland 	/* error if global zone path is not absolute */
890*5c51f124SMoriah Waterland 
891*5c51f124SMoriah Waterland 	if (*a_gzPath != '/') {
892*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath);
893*5c51f124SMoriah Waterland 		return (B_FALSE);
894*5c51f124SMoriah Waterland 	}
895*5c51f124SMoriah Waterland 
896*5c51f124SMoriah Waterland 	/* error if global zone path does not exist */
897*5c51f124SMoriah Waterland 
898*5c51f124SMoriah Waterland 	if (_z_is_directory(a_gzPath) != 0) {
899*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno));
900*5c51f124SMoriah Waterland 		return (B_FALSE);
901*5c51f124SMoriah Waterland 	}
902*5c51f124SMoriah Waterland 
903*5c51f124SMoriah Waterland 	/* verify that specified non-global zone exists */
904*5c51f124SMoriah Waterland 
905*5c51f124SMoriah Waterland 	err = zone_get_id(a_zoneName, &zid);
906*5c51f124SMoriah Waterland 	if (err != Z_OK) {
907*5c51f124SMoriah Waterland 		_z_program_error(ERR_GET_ZONEID, a_zoneName,
908*5c51f124SMoriah Waterland 		    zonecfg_strerror(err));
909*5c51f124SMoriah Waterland 		return (B_FALSE);
910*5c51f124SMoriah Waterland 	}
911*5c51f124SMoriah Waterland 
912*5c51f124SMoriah Waterland 	/* obtain global zone path to non-global zones root file system */
913*5c51f124SMoriah Waterland 
914*5c51f124SMoriah Waterland 	err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath));
915*5c51f124SMoriah Waterland 	if (err != Z_OK) {
916*5c51f124SMoriah Waterland 		_z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName,
917*5c51f124SMoriah Waterland 		    zonecfg_strerror(err));
918*5c51f124SMoriah Waterland 		return (B_FALSE);
919*5c51f124SMoriah Waterland 	}
920*5c51f124SMoriah Waterland 
921*5c51f124SMoriah Waterland 	if (lzRootPath[0] == '\0') {
922*5c51f124SMoriah Waterland 		_z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName);
923*5c51f124SMoriah Waterland 		return (B_FALSE);
924*5c51f124SMoriah Waterland 	}
925*5c51f124SMoriah Waterland 
926*5c51f124SMoriah Waterland 	/*
927*5c51f124SMoriah Waterland 	 * lofs resolve the non-global zone's root path first in case
928*5c51f124SMoriah Waterland 	 * its in a path that's been lofs mounted read-only.
929*5c51f124SMoriah Waterland 	 * (e.g. This happens when we're tyring to patch a zone in an ABE
930*5c51f124SMoriah Waterland 	 * that lives on a filesystem that the ABE shares with the currently
931*5c51f124SMoriah Waterland 	 * running BE.)
932*5c51f124SMoriah Waterland 	 */
933*5c51f124SMoriah Waterland 	z_resolve_lofs(lzRootPath, sizeof (lzRootPath));
934*5c51f124SMoriah Waterland 
935*5c51f124SMoriah Waterland 	/* verify that the root path exists */
936*5c51f124SMoriah Waterland 
937*5c51f124SMoriah Waterland 	if (_z_is_directory(lzRootPath) != 0) {
938*5c51f124SMoriah Waterland 		_z_program_error(ERR_LZROOT_NOTDIR, lzRootPath,
939*5c51f124SMoriah Waterland 		    strerror(errno));
940*5c51f124SMoriah Waterland 		return (B_FALSE);
941*5c51f124SMoriah Waterland 	}
942*5c51f124SMoriah Waterland 
943*5c51f124SMoriah Waterland 	/*
944*5c51f124SMoriah Waterland 	 * generate a unique key - the key is the same length as unique uid
945*5c51f124SMoriah Waterland 	 * but contains different information that is as unique as can be made;
946*5c51f124SMoriah Waterland 	 * include current hires time (nanosecond real timer). Such a unique
947*5c51f124SMoriah Waterland 	 * i.d. will look like:
948*5c51f124SMoriah Waterland 	 *		0203104092-1145345-0004e94d6af481a0
949*5c51f124SMoriah Waterland 	 */
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland 	hretime = gethrtime();
952*5c51f124SMoriah Waterland 
953*5c51f124SMoriah Waterland 	thetime = time((time_t *)NULL);
954*5c51f124SMoriah Waterland 	(void) localtime_r(&thetime, &tstruct);
955*5c51f124SMoriah Waterland 
956*5c51f124SMoriah Waterland 	slen = snprintf(uuid, sizeof (uuid),
957*5c51f124SMoriah Waterland 	    UUID_FORMAT,
958*5c51f124SMoriah Waterland 	    tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year,
959*5c51f124SMoriah Waterland 	    tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min,
960*5c51f124SMoriah Waterland 	    tstruct.tm_sec,	tstruct.tm_wday, hretime);
961*5c51f124SMoriah Waterland 	if (slen > sizeof (uuid)) {
962*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED,
963*5c51f124SMoriah Waterland 		    UUID_FORMAT, sizeof (uuid));
964*5c51f124SMoriah Waterland 		return (B_FALSE);
965*5c51f124SMoriah Waterland 	}
966*5c51f124SMoriah Waterland 
967*5c51f124SMoriah Waterland 	/* create the global zone mount point */
968*5c51f124SMoriah Waterland 
969*5c51f124SMoriah Waterland 	slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s",
970*5c51f124SMoriah Waterland 	    lzRootPath,
971*5c51f124SMoriah Waterland 	    a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid);
972*5c51f124SMoriah Waterland 	if (slen > sizeof (gzMountPoint)) {
973*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED,
974*5c51f124SMoriah Waterland 		    "%s/.SUNW_%s_%s", lzRootPath,
975*5c51f124SMoriah Waterland 		    a_mountPointPrefix ? a_mountPointPrefix : "zones",
976*5c51f124SMoriah Waterland 		    uuid, sizeof (gzMountPoint));
977*5c51f124SMoriah Waterland 		return (B_FALSE);
978*5c51f124SMoriah Waterland 	}
979*5c51f124SMoriah Waterland 
980*5c51f124SMoriah Waterland 	slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s",
981*5c51f124SMoriah Waterland 	    gzMountPoint+strlen(lzRootPath));
982*5c51f124SMoriah Waterland 	if (slen > sizeof (lzMountPoint)) {
983*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED,
984*5c51f124SMoriah Waterland 		    "%s", gzMountPoint+strlen(lzRootPath),
985*5c51f124SMoriah Waterland 		    sizeof (lzMountPoint));
986*5c51f124SMoriah Waterland 		return (B_FALSE);
987*5c51f124SMoriah Waterland 	}
988*5c51f124SMoriah Waterland 
989*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint,
990*5c51f124SMoriah Waterland 	    lzMountPoint);
991*5c51f124SMoriah Waterland 
992*5c51f124SMoriah Waterland 	/* error if the mount point already exists */
993*5c51f124SMoriah Waterland 
994*5c51f124SMoriah Waterland 	if (_z_is_directory(gzMountPoint) == 0) {
995*5c51f124SMoriah Waterland 		_z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint,
996*5c51f124SMoriah Waterland 		    a_zoneName, strerror(errno));
997*5c51f124SMoriah Waterland 		return (B_FALSE);
998*5c51f124SMoriah Waterland 	}
999*5c51f124SMoriah Waterland 
1000*5c51f124SMoriah Waterland 	/* create the temporary mount point */
1001*5c51f124SMoriah Waterland 
1002*5c51f124SMoriah Waterland 	if (mkdir(gzMountPoint, 0600) != 0) {
1003*5c51f124SMoriah Waterland 		_z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName,
1004*5c51f124SMoriah Waterland 		    strerror(errno));
1005*5c51f124SMoriah Waterland 		return (B_FALSE);
1006*5c51f124SMoriah Waterland 	}
1007*5c51f124SMoriah Waterland 
1008*5c51f124SMoriah Waterland 	/* mount the global zone path on the non-global zone root file system */
1009*5c51f124SMoriah Waterland 
1010*5c51f124SMoriah Waterland 	err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs",
1011*5c51f124SMoriah Waterland 	    (char *)NULL, 0, (char *)NULL, 0);
1012*5c51f124SMoriah Waterland 	if (err != 0) {
1013*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZMOUNT_FAILED, a_gzPath,
1014*5c51f124SMoriah Waterland 		    gzMountPoint, a_zoneName, strerror(errno));
1015*5c51f124SMoriah Waterland 		return (B_FALSE);
1016*5c51f124SMoriah Waterland 	}
1017*5c51f124SMoriah Waterland 
1018*5c51f124SMoriah Waterland 	/* success - return both mountpoints to caller */
1019*5c51f124SMoriah Waterland 
1020*5c51f124SMoriah Waterland 	*r_lzMountPoint = _z_strdup(gzMountPoint);
1021*5c51f124SMoriah Waterland 
1022*5c51f124SMoriah Waterland 	*r_lzRootPath = _z_strdup(lzMountPoint);
1023*5c51f124SMoriah Waterland 
1024*5c51f124SMoriah Waterland 	/* return success */
1025*5c51f124SMoriah Waterland 
1026*5c51f124SMoriah Waterland 	return (B_TRUE);
1027*5c51f124SMoriah Waterland }
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland /*
1030*5c51f124SMoriah Waterland  * Name:	z_non_global_zones_exist
1031*5c51f124SMoriah Waterland  * Description:	Determine if any non-global native zones exist
1032*5c51f124SMoriah Waterland  * Arguments:	None.
1033*5c51f124SMoriah Waterland  * Returns:	boolean_t
1034*5c51f124SMoriah Waterland  *	== B_TRUE - at least one non-global native zone exists
1035*5c51f124SMoriah Waterland  *	== B_FALSE - no non-global native zone exists
1036*5c51f124SMoriah Waterland  */
1037*5c51f124SMoriah Waterland 
1038*5c51f124SMoriah Waterland boolean_t
1039*5c51f124SMoriah Waterland z_non_global_zones_exist(void)
1040*5c51f124SMoriah Waterland {
1041*5c51f124SMoriah Waterland 	FILE		*zoneIndexFP;
1042*5c51f124SMoriah Waterland 	boolean_t	anyExist = B_FALSE;
1043*5c51f124SMoriah Waterland 	struct zoneent	*ze;
1044*5c51f124SMoriah Waterland 	zone_spec_t	*zent;
1045*5c51f124SMoriah Waterland 
1046*5c51f124SMoriah Waterland 	/* if zones are not implemented, return FALSE */
1047*5c51f124SMoriah Waterland 
1048*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
1049*5c51f124SMoriah Waterland 		return (B_FALSE);
1050*5c51f124SMoriah Waterland 	}
1051*5c51f124SMoriah Waterland 
1052*5c51f124SMoriah Waterland 	/* determine if any zones are configured */
1053*5c51f124SMoriah Waterland 	zoneIndexFP = setzoneent();
1054*5c51f124SMoriah Waterland 	if (zoneIndexFP == NULL) {
1055*5c51f124SMoriah Waterland 		return (B_FALSE);
1056*5c51f124SMoriah Waterland 	}
1057*5c51f124SMoriah Waterland 
1058*5c51f124SMoriah Waterland 	/* index file open; scan all zones; see if any are at least installed */
1059*5c51f124SMoriah Waterland 
1060*5c51f124SMoriah Waterland 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1061*5c51f124SMoriah Waterland 		/*
1062*5c51f124SMoriah Waterland 		 * If the user specified an explicit zone list, then ignore any
1063*5c51f124SMoriah Waterland 		 * zones that aren't on that list.
1064*5c51f124SMoriah Waterland 		 */
1065*5c51f124SMoriah Waterland 		if ((zent = _z_global_data._zone_spec) != NULL) {
1066*5c51f124SMoriah Waterland 			while (zent != NULL) {
1067*5c51f124SMoriah Waterland 				if (strcmp(zent->zl_name, ze->zone_name) == 0)
1068*5c51f124SMoriah Waterland 					break;
1069*5c51f124SMoriah Waterland 				zent = zent->zl_next;
1070*5c51f124SMoriah Waterland 			}
1071*5c51f124SMoriah Waterland 			if (zent == NULL) {
1072*5c51f124SMoriah Waterland 				free(ze);
1073*5c51f124SMoriah Waterland 				continue;
1074*5c51f124SMoriah Waterland 			}
1075*5c51f124SMoriah Waterland 		}
1076*5c51f124SMoriah Waterland 
1077*5c51f124SMoriah Waterland 		/* skip the global zone */
1078*5c51f124SMoriah Waterland 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
1079*5c51f124SMoriah Waterland 			free(ze);
1080*5c51f124SMoriah Waterland 			continue;
1081*5c51f124SMoriah Waterland 		}
1082*5c51f124SMoriah Waterland 
1083*5c51f124SMoriah Waterland 		/* skip any branded zones */
1084*5c51f124SMoriah Waterland 		if (z_is_zone_branded(ze->zone_name)) {
1085*5c51f124SMoriah Waterland 			free(ze);
1086*5c51f124SMoriah Waterland 			continue;
1087*5c51f124SMoriah Waterland 		}
1088*5c51f124SMoriah Waterland 
1089*5c51f124SMoriah Waterland 		/* is this zone installed? */
1090*5c51f124SMoriah Waterland 		if (ze->zone_state >= ZONE_STATE_INSTALLED) {
1091*5c51f124SMoriah Waterland 			free(ze);
1092*5c51f124SMoriah Waterland 			anyExist = B_TRUE;
1093*5c51f124SMoriah Waterland 			break;
1094*5c51f124SMoriah Waterland 		}
1095*5c51f124SMoriah Waterland 		free(ze);
1096*5c51f124SMoriah Waterland 	}
1097*5c51f124SMoriah Waterland 
1098*5c51f124SMoriah Waterland 	/* close the index file */
1099*5c51f124SMoriah Waterland 
1100*5c51f124SMoriah Waterland 	endzoneent(zoneIndexFP);
1101*5c51f124SMoriah Waterland 
1102*5c51f124SMoriah Waterland 	/* return results */
1103*5c51f124SMoriah Waterland 
1104*5c51f124SMoriah Waterland 	return (anyExist);
1105*5c51f124SMoriah Waterland }
1106*5c51f124SMoriah Waterland 
1107*5c51f124SMoriah Waterland /*
1108*5c51f124SMoriah Waterland  * Name:	z_on_zone_spec
1109*5c51f124SMoriah Waterland  * Description:	Determine if named zone is on the zone_spec list.
1110*5c51f124SMoriah Waterland  * Arguments:	Pointer to name to test.
1111*5c51f124SMoriah Waterland  * Returns:	B_TRUE if named zone is on the list or if the user specified
1112*5c51f124SMoriah Waterland  *		no list at all (all zones is the default), B_FALSE otherwise.
1113*5c51f124SMoriah Waterland  */
1114*5c51f124SMoriah Waterland 
1115*5c51f124SMoriah Waterland boolean_t
1116*5c51f124SMoriah Waterland z_on_zone_spec(const char *zonename)
1117*5c51f124SMoriah Waterland {
1118*5c51f124SMoriah Waterland 	zone_spec_t	*zent;
1119*5c51f124SMoriah Waterland 
1120*5c51f124SMoriah Waterland 	/* entry assertions */
1121*5c51f124SMoriah Waterland 
1122*5c51f124SMoriah Waterland 	assert(zonename != NULL);
1123*5c51f124SMoriah Waterland 	assert(*zonename != '\0');
1124*5c51f124SMoriah Waterland 
1125*5c51f124SMoriah Waterland 	/* return true if zones not implemented or no zone spec list defined */
1126*5c51f124SMoriah Waterland 
1127*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) {
1128*5c51f124SMoriah Waterland 		return (B_TRUE);
1129*5c51f124SMoriah Waterland 	}
1130*5c51f124SMoriah Waterland 
1131*5c51f124SMoriah Waterland 	/* return true if named zone is on the zone spec list */
1132*5c51f124SMoriah Waterland 
1133*5c51f124SMoriah Waterland 	for (zent = _z_global_data._zone_spec;
1134*5c51f124SMoriah Waterland 	    zent != NULL; zent = zent->zl_next) {
1135*5c51f124SMoriah Waterland 		if (strcmp(zent->zl_name, zonename) == 0)
1136*5c51f124SMoriah Waterland 			return (B_TRUE);
1137*5c51f124SMoriah Waterland 	}
1138*5c51f124SMoriah Waterland 
1139*5c51f124SMoriah Waterland 	/* named zone is not on the zone spec list */
1140*5c51f124SMoriah Waterland 
1141*5c51f124SMoriah Waterland 	return (B_FALSE);
1142*5c51f124SMoriah Waterland }
1143*5c51f124SMoriah Waterland 
1144*5c51f124SMoriah Waterland /*
1145*5c51f124SMoriah Waterland  * Name:	z_running_in_global_zone
1146*5c51f124SMoriah Waterland  * Description:	Determine if running in the "global" zone
1147*5c51f124SMoriah Waterland  * Arguments:	void
1148*5c51f124SMoriah Waterland  * Returns:	boolean_t
1149*5c51f124SMoriah Waterland  *			== B_TRUE - running in global zone
1150*5c51f124SMoriah Waterland  *			== B_FALSE - not running in global zone
1151*5c51f124SMoriah Waterland  */
1152*5c51f124SMoriah Waterland 
1153*5c51f124SMoriah Waterland boolean_t
1154*5c51f124SMoriah Waterland z_running_in_global_zone(void)
1155*5c51f124SMoriah Waterland {
1156*5c51f124SMoriah Waterland 	static	boolean_t	_zoneIdDetermined = B_FALSE;
1157*5c51f124SMoriah Waterland 	static	boolean_t	_zoneIsGlobal = B_FALSE;
1158*5c51f124SMoriah Waterland 
1159*5c51f124SMoriah Waterland 	/* if ID has not been determined, cache it now */
1160*5c51f124SMoriah Waterland 
1161*5c51f124SMoriah Waterland 	if (!_zoneIdDetermined) {
1162*5c51f124SMoriah Waterland 		_zoneIdDetermined = B_TRUE;
1163*5c51f124SMoriah Waterland 		_zoneIsGlobal = _z_running_in_global_zone();
1164*5c51f124SMoriah Waterland 	}
1165*5c51f124SMoriah Waterland 
1166*5c51f124SMoriah Waterland 	return (_zoneIsGlobal);
1167*5c51f124SMoriah Waterland }
1168*5c51f124SMoriah Waterland 
1169*5c51f124SMoriah Waterland /*
1170*5c51f124SMoriah Waterland  * Name:	z_set_output_functions
1171*5c51f124SMoriah Waterland  * Description:	Link program specific output functions to this library.
1172*5c51f124SMoriah Waterland  * Arguments:	a_echo_fcn - (_z_printf_fcn_t)
1173*5c51f124SMoriah Waterland  *			Function to call to cause "normal operation" messages
1174*5c51f124SMoriah Waterland  *			to be output/displayed
1175*5c51f124SMoriah Waterland  *		a_echo_debug_fcn - (_z_printf_fcn_t)
1176*5c51f124SMoriah Waterland  *			Function to call to cause "debugging" messages
1177*5c51f124SMoriah Waterland  *			to be output/displayed
1178*5c51f124SMoriah Waterland  *		a_progerr_fcn - (_z_printf_fcn_t)
1179*5c51f124SMoriah Waterland  *			Function to call to cause "program error" messages
1180*5c51f124SMoriah Waterland  *			to be output/displayed
1181*5c51f124SMoriah Waterland  * Returns:	void
1182*5c51f124SMoriah Waterland  * NOTE:	If NULL is specified for any function, then the functionality
1183*5c51f124SMoriah Waterland  *		associated with that function is disabled.
1184*5c51f124SMoriah Waterland  * NOTE:	The function pointers provided must call a function that
1185*5c51f124SMoriah Waterland  *		takes two arguments:
1186*5c51f124SMoriah Waterland  *			function(char *format, char *message)
1187*5c51f124SMoriah Waterland  *		Any registered function will be called like:
1188*5c51f124SMoriah Waterland  *			function("%s", "message")
1189*5c51f124SMoriah Waterland  */
1190*5c51f124SMoriah Waterland 
1191*5c51f124SMoriah Waterland void
1192*5c51f124SMoriah Waterland z_set_output_functions(_z_printf_fcn_t a_echo_fcn,
1193*5c51f124SMoriah Waterland     _z_printf_fcn_t a_echo_debug_fcn,
1194*5c51f124SMoriah Waterland     _z_printf_fcn_t a_progerr_fcn)
1195*5c51f124SMoriah Waterland {
1196*5c51f124SMoriah Waterland 	_z_global_data._z_echo = a_echo_fcn;
1197*5c51f124SMoriah Waterland 	_z_global_data._z_echo_debug = a_echo_debug_fcn;
1198*5c51f124SMoriah Waterland 	_z_global_data._z_progerr = a_progerr_fcn;
1199*5c51f124SMoriah Waterland }
1200*5c51f124SMoriah Waterland 
1201*5c51f124SMoriah Waterland /*
1202*5c51f124SMoriah Waterland  * Name:	z_set_zone_root
1203*5c51f124SMoriah Waterland  * Description:	Set root for zones library operations
1204*5c51f124SMoriah Waterland  * Arguments:	Path to root of boot environment containing zone; must be
1205*5c51f124SMoriah Waterland  *		absolute.
1206*5c51f124SMoriah Waterland  * Returns:	None.
1207*5c51f124SMoriah Waterland  * NOTE:	Must be called before performing any zone-related operations.
1208*5c51f124SMoriah Waterland  *		(Currently called directly by set_inst_root() during -R
1209*5c51f124SMoriah Waterland  *		argument handling.)
1210*5c51f124SMoriah Waterland  */
1211*5c51f124SMoriah Waterland 
1212*5c51f124SMoriah Waterland void
1213*5c51f124SMoriah Waterland z_set_zone_root(const char *zroot)
1214*5c51f124SMoriah Waterland {
1215*5c51f124SMoriah Waterland 	char *rootdir;
1216*5c51f124SMoriah Waterland 
1217*5c51f124SMoriah Waterland 	/* if zones are not implemented, just return */
1218*5c51f124SMoriah Waterland 
1219*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented())
1220*5c51f124SMoriah Waterland 		return;
1221*5c51f124SMoriah Waterland 
1222*5c51f124SMoriah Waterland 	/* entry assertions */
1223*5c51f124SMoriah Waterland 
1224*5c51f124SMoriah Waterland 	assert(zroot != NULL);
1225*5c51f124SMoriah Waterland 
1226*5c51f124SMoriah Waterland 	rootdir = _z_strdup((char *)zroot);
1227*5c51f124SMoriah Waterland 	z_canoninplace(rootdir);
1228*5c51f124SMoriah Waterland 
1229*5c51f124SMoriah Waterland 	if (strcmp(rootdir, "/") == 0) {
1230*5c51f124SMoriah Waterland 		rootdir[0] = '\0';
1231*5c51f124SMoriah Waterland 	}
1232*5c51f124SMoriah Waterland 
1233*5c51f124SMoriah Waterland 	/* free any existing cached root path */
1234*5c51f124SMoriah Waterland 
1235*5c51f124SMoriah Waterland 	if (*_z_global_data._z_root_dir != '\0') {
1236*5c51f124SMoriah Waterland 		free(_z_global_data._z_root_dir);
1237*5c51f124SMoriah Waterland 	}
1238*5c51f124SMoriah Waterland 
1239*5c51f124SMoriah Waterland 	/* store duplicate of new zone root path */
1240*5c51f124SMoriah Waterland 
1241*5c51f124SMoriah Waterland 	if (*rootdir != '\0') {
1242*5c51f124SMoriah Waterland 		_z_global_data._z_root_dir = _z_strdup(rootdir);
1243*5c51f124SMoriah Waterland 	} else {
1244*5c51f124SMoriah Waterland 		*_z_global_data._z_root_dir = '\0';
1245*5c51f124SMoriah Waterland 	}
1246*5c51f124SMoriah Waterland 
1247*5c51f124SMoriah Waterland 	/* set zone root path */
1248*5c51f124SMoriah Waterland 
1249*5c51f124SMoriah Waterland 	zonecfg_set_root(rootdir);
1250*5c51f124SMoriah Waterland 
1251*5c51f124SMoriah Waterland 	free(rootdir);
1252*5c51f124SMoriah Waterland }
1253*5c51f124SMoriah Waterland 
1254*5c51f124SMoriah Waterland /*
1255*5c51f124SMoriah Waterland  * Name:	z_set_zone_spec
1256*5c51f124SMoriah Waterland  * Description:	Set list of zones on which actions will be performed.
1257*5c51f124SMoriah Waterland  * Arguments:	Whitespace-separated list of zone names.
1258*5c51f124SMoriah Waterland  * Returns:	0 on success, -1 on error.
1259*5c51f124SMoriah Waterland  * NOTES:	Will call _z_program_error if argument can't be parsed or
1260*5c51f124SMoriah Waterland  *		memory not available.
1261*5c51f124SMoriah Waterland  */
1262*5c51f124SMoriah Waterland 
1263*5c51f124SMoriah Waterland int
1264*5c51f124SMoriah Waterland z_set_zone_spec(const char *zlist)
1265*5c51f124SMoriah Waterland {
1266*5c51f124SMoriah Waterland 	const char	*zend;
1267*5c51f124SMoriah Waterland 	ptrdiff_t	zlen;
1268*5c51f124SMoriah Waterland 	zone_spec_t	*zent;
1269*5c51f124SMoriah Waterland 	zone_spec_t	*zhead;
1270*5c51f124SMoriah Waterland 	zone_spec_t	**znextp = &zhead;
1271*5c51f124SMoriah Waterland 
1272*5c51f124SMoriah Waterland 	/* entry assertions */
1273*5c51f124SMoriah Waterland 
1274*5c51f124SMoriah Waterland 	assert(zlist != NULL);
1275*5c51f124SMoriah Waterland 
1276*5c51f124SMoriah Waterland 	/* parse list to zone_spec_t list, store in global data */
1277*5c51f124SMoriah Waterland 
1278*5c51f124SMoriah Waterland 	for (;;) {
1279*5c51f124SMoriah Waterland 		while (isspace(*zlist)) {
1280*5c51f124SMoriah Waterland 			zlist++;
1281*5c51f124SMoriah Waterland 		}
1282*5c51f124SMoriah Waterland 		if (*zlist == '\0') {
1283*5c51f124SMoriah Waterland 			break;
1284*5c51f124SMoriah Waterland 		}
1285*5c51f124SMoriah Waterland 		for (zend = zlist; *zend != '\0'; zend++) {
1286*5c51f124SMoriah Waterland 			if (isspace(*zend)) {
1287*5c51f124SMoriah Waterland 				break;
1288*5c51f124SMoriah Waterland 			}
1289*5c51f124SMoriah Waterland 		}
1290*5c51f124SMoriah Waterland 		zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist);
1291*5c51f124SMoriah Waterland 		if (zlen >= ZONENAME_MAX) {
1292*5c51f124SMoriah Waterland 			_z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist);
1293*5c51f124SMoriah Waterland 			return (-1);
1294*5c51f124SMoriah Waterland 		}
1295*5c51f124SMoriah Waterland 		zent = _z_malloc(sizeof (*zent));
1296*5c51f124SMoriah Waterland 		(void) memcpy(zent->zl_name, zlist, zlen);
1297*5c51f124SMoriah Waterland 		zent->zl_name[zlen] = '\0';
1298*5c51f124SMoriah Waterland 		zent->zl_used = B_FALSE;
1299*5c51f124SMoriah Waterland 		*znextp = zent;
1300*5c51f124SMoriah Waterland 		znextp = &zent->zl_next;
1301*5c51f124SMoriah Waterland 		zlist = zend;
1302*5c51f124SMoriah Waterland 	}
1303*5c51f124SMoriah Waterland 	*znextp = NULL;
1304*5c51f124SMoriah Waterland 
1305*5c51f124SMoriah Waterland 	if (zhead == NULL) {
1306*5c51f124SMoriah Waterland 		_z_program_error(ERR_ZONE_LIST_EMPTY);
1307*5c51f124SMoriah Waterland 		return (-1);
1308*5c51f124SMoriah Waterland 	}
1309*5c51f124SMoriah Waterland 
1310*5c51f124SMoriah Waterland 	_z_global_data._zone_spec = zhead;
1311*5c51f124SMoriah Waterland 	return (0);
1312*5c51f124SMoriah Waterland }
1313*5c51f124SMoriah Waterland 
1314*5c51f124SMoriah Waterland /*
1315*5c51f124SMoriah Waterland  * Name:	z_umount_lz_mount
1316*5c51f124SMoriah Waterland  * Description:	Unmount directory mounted with z_mount_in_lz
1317*5c51f124SMoriah Waterland  * Arguments:	a_lzMountPointer - pointer to string returned by z_mount_in_lz
1318*5c51f124SMoriah Waterland  * Returns:	boolean_t
1319*5c51f124SMoriah Waterland  *			== B_TRUE - successfully unmounted directory
1320*5c51f124SMoriah Waterland  *			== B_FALSE - failed to unmount directory
1321*5c51f124SMoriah Waterland  */
1322*5c51f124SMoriah Waterland 
1323*5c51f124SMoriah Waterland boolean_t
1324*5c51f124SMoriah Waterland z_umount_lz_mount(char *a_lzMountPoint)
1325*5c51f124SMoriah Waterland {
1326*5c51f124SMoriah Waterland 	int	err;
1327*5c51f124SMoriah Waterland 
1328*5c51f124SMoriah Waterland 	/* entry assertions */
1329*5c51f124SMoriah Waterland 
1330*5c51f124SMoriah Waterland 	assert(a_lzMountPoint != (char *)NULL);
1331*5c51f124SMoriah Waterland 	assert(*a_lzMountPoint != '\0');
1332*5c51f124SMoriah Waterland 
1333*5c51f124SMoriah Waterland 	/* entry debugging info */
1334*5c51f124SMoriah Waterland 
1335*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint);
1336*5c51f124SMoriah Waterland 
1337*5c51f124SMoriah Waterland 	/* if zones are not implemented, return TRUE */
1338*5c51f124SMoriah Waterland 
1339*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
1340*5c51f124SMoriah Waterland 		return (B_FALSE);
1341*5c51f124SMoriah Waterland 	}
1342*5c51f124SMoriah Waterland 
1343*5c51f124SMoriah Waterland 	/* error if global zone path is not absolute */
1344*5c51f124SMoriah Waterland 
1345*5c51f124SMoriah Waterland 	if (*a_lzMountPoint != '/') {
1346*5c51f124SMoriah Waterland 		_z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint);
1347*5c51f124SMoriah Waterland 		return (B_FALSE);
1348*5c51f124SMoriah Waterland 	}
1349*5c51f124SMoriah Waterland 
1350*5c51f124SMoriah Waterland 	/* verify mount point exists */
1351*5c51f124SMoriah Waterland 
1352*5c51f124SMoriah Waterland 	if (_z_is_directory(a_lzMountPoint) != 0) {
1353*5c51f124SMoriah Waterland 		_z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint,
1354*5c51f124SMoriah Waterland 		    strerror(errno));
1355*5c51f124SMoriah Waterland 		return (B_FALSE);
1356*5c51f124SMoriah Waterland 	}
1357*5c51f124SMoriah Waterland 
1358*5c51f124SMoriah Waterland 	/* unmount */
1359*5c51f124SMoriah Waterland 
1360*5c51f124SMoriah Waterland 	err = umount2(a_lzMountPoint, 0);
1361*5c51f124SMoriah Waterland 	if (err != 0) {
1362*5c51f124SMoriah Waterland 		_z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint,
1363*5c51f124SMoriah Waterland 		    strerror(errno));
1364*5c51f124SMoriah Waterland 		return (B_FALSE);
1365*5c51f124SMoriah Waterland 	}
1366*5c51f124SMoriah Waterland 
1367*5c51f124SMoriah Waterland 	/* remove the mount point */
1368*5c51f124SMoriah Waterland 
1369*5c51f124SMoriah Waterland 	(void) remove(a_lzMountPoint);
1370*5c51f124SMoriah Waterland 
1371*5c51f124SMoriah Waterland 	/* return success */
1372*5c51f124SMoriah Waterland 
1373*5c51f124SMoriah Waterland 	return (B_TRUE);
1374*5c51f124SMoriah Waterland }
1375*5c51f124SMoriah Waterland 
1376*5c51f124SMoriah Waterland /*
1377*5c51f124SMoriah Waterland  * Name:	z_unlock_this_zone
1378*5c51f124SMoriah Waterland  * Description:	unlock this zone
1379*5c51f124SMoriah Waterland  * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
1380*5c51f124SMoriah Waterland  *			Flags indicating which locks to release
1381*5c51f124SMoriah Waterland  * Returns:	boolean_t
1382*5c51f124SMoriah Waterland  *			== B_TRUE - success specified locks released
1383*5c51f124SMoriah Waterland  *			== B_FALSE - failure specified locks may not be released
1384*5c51f124SMoriah Waterland  * NOTE: the lock objects for "this zone" are maintained internally.
1385*5c51f124SMoriah Waterland  */
1386*5c51f124SMoriah Waterland 
1387*5c51f124SMoriah Waterland boolean_t
1388*5c51f124SMoriah Waterland z_unlock_this_zone(ZLOCKS_T a_lflags)
1389*5c51f124SMoriah Waterland {
1390*5c51f124SMoriah Waterland 	boolean_t	b;
1391*5c51f124SMoriah Waterland 	boolean_t	errors = B_FALSE;
1392*5c51f124SMoriah Waterland 	char		*zoneName;
1393*5c51f124SMoriah Waterland 
1394*5c51f124SMoriah Waterland 	/* entry assertions */
1395*5c51f124SMoriah Waterland 
1396*5c51f124SMoriah Waterland 	assert(a_lflags != ZLOCKS_NONE);
1397*5c51f124SMoriah Waterland 
1398*5c51f124SMoriah Waterland 	/* entry debugging info */
1399*5c51f124SMoriah Waterland 
1400*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags);
1401*5c51f124SMoriah Waterland 
1402*5c51f124SMoriah Waterland 	/* return if no objects locked */
1403*5c51f124SMoriah Waterland 
1404*5c51f124SMoriah Waterland 	if ((_z_global_data._z_ObjectLocks == (char *)NULL) ||
1405*5c51f124SMoriah Waterland 	    (*_z_global_data._z_ObjectLocks == '\0')) {
1406*5c51f124SMoriah Waterland 		return (B_TRUE);
1407*5c51f124SMoriah Waterland 	}
1408*5c51f124SMoriah Waterland 
1409*5c51f124SMoriah Waterland 	zoneName = z_get_zonename();
1410*5c51f124SMoriah Waterland 
1411*5c51f124SMoriah Waterland 	/* unlock patch administration */
1412*5c51f124SMoriah Waterland 
1413*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PATCH_ADMIN) {
1414*5c51f124SMoriah Waterland 		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1415*5c51f124SMoriah Waterland 		    zoneName, LOBJ_PATCHADMIN, ERR_ZONES_ULK_THIS_PATCH);
1416*5c51f124SMoriah Waterland 		if (!b) {
1417*5c51f124SMoriah Waterland 			errors = B_TRUE;
1418*5c51f124SMoriah Waterland 		}
1419*5c51f124SMoriah Waterland 	}
1420*5c51f124SMoriah Waterland 
1421*5c51f124SMoriah Waterland 	/* unlock package administration */
1422*5c51f124SMoriah Waterland 
1423*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
1424*5c51f124SMoriah Waterland 		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1425*5c51f124SMoriah Waterland 		    zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE);
1426*5c51f124SMoriah Waterland 		if (!b) {
1427*5c51f124SMoriah Waterland 			errors = B_TRUE;
1428*5c51f124SMoriah Waterland 		}
1429*5c51f124SMoriah Waterland 	}
1430*5c51f124SMoriah Waterland 
1431*5c51f124SMoriah Waterland 	/* unlock zone administration */
1432*5c51f124SMoriah Waterland 
1433*5c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
1434*5c51f124SMoriah Waterland 		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1435*5c51f124SMoriah Waterland 		    zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES);
1436*5c51f124SMoriah Waterland 		if (!b) {
1437*5c51f124SMoriah Waterland 			errors = B_TRUE;
1438*5c51f124SMoriah Waterland 		}
1439*5c51f124SMoriah Waterland 	}
1440*5c51f124SMoriah Waterland 
1441*5c51f124SMoriah Waterland 	(void) free(zoneName);
1442*5c51f124SMoriah Waterland 	return (!errors);
1443*5c51f124SMoriah Waterland }
1444*5c51f124SMoriah Waterland 
1445*5c51f124SMoriah Waterland /*
1446*5c51f124SMoriah Waterland  * Name:	z_unlock_zones
1447*5c51f124SMoriah Waterland  * Description:	unlock specified zones
1448*5c51f124SMoriah Waterland  * Arguments:	a_zlst - zoneList_t object describing zones to unlock
1449*5c51f124SMoriah Waterland  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
1450*5c51f124SMoriah Waterland  *			Flags indicating which locks to release
1451*5c51f124SMoriah Waterland  * Returns:	boolean_t
1452*5c51f124SMoriah Waterland  *			== B_TRUE - success, zones unlocked
1453*5c51f124SMoriah Waterland  *			== B_FALSE - failure, zones not unlocked
1454*5c51f124SMoriah Waterland  */
1455*5c51f124SMoriah Waterland 
1456*5c51f124SMoriah Waterland boolean_t
1457*5c51f124SMoriah Waterland z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
1458*5c51f124SMoriah Waterland {
1459*5c51f124SMoriah Waterland 	boolean_t	b;
1460*5c51f124SMoriah Waterland 	boolean_t	errors = B_FALSE;
1461*5c51f124SMoriah Waterland 	int		i;
1462*5c51f124SMoriah Waterland 
1463*5c51f124SMoriah Waterland 	/* entry assertions */
1464*5c51f124SMoriah Waterland 
1465*5c51f124SMoriah Waterland 	assert(a_lflags != ZLOCKS_NONE);
1466*5c51f124SMoriah Waterland 
1467*5c51f124SMoriah Waterland 	/* entry debugging info */
1468*5c51f124SMoriah Waterland 
1469*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags);
1470*5c51f124SMoriah Waterland 
1471*5c51f124SMoriah Waterland 	/* if zones are not implemented, return TRUE */
1472*5c51f124SMoriah Waterland 
1473*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
1474*5c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP);
1475*5c51f124SMoriah Waterland 		return (B_TRUE);
1476*5c51f124SMoriah Waterland 	}
1477*5c51f124SMoriah Waterland 
1478*5c51f124SMoriah Waterland 	/* ignore empty list */
1479*5c51f124SMoriah Waterland 
1480*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1481*5c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES);
1482*5c51f124SMoriah Waterland 		/* unlock this zone before returning */
1483*5c51f124SMoriah Waterland 		return (z_unlock_this_zone(a_lflags));
1484*5c51f124SMoriah Waterland 	}
1485*5c51f124SMoriah Waterland 
1486*5c51f124SMoriah Waterland 	/* zones exist */
1487*5c51f124SMoriah Waterland 
1488*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST);
1489*5c51f124SMoriah Waterland 
1490*5c51f124SMoriah Waterland 	/*
1491*5c51f124SMoriah Waterland 	 * unlock each listed zone that is currently running
1492*5c51f124SMoriah Waterland 	 */
1493*5c51f124SMoriah Waterland 
1494*5c51f124SMoriah Waterland 	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
1495*5c51f124SMoriah Waterland 		/* ignore zone if not locked */
1496*5c51f124SMoriah Waterland 		if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) {
1497*5c51f124SMoriah Waterland 			continue;
1498*5c51f124SMoriah Waterland 		}
1499*5c51f124SMoriah Waterland 
1500*5c51f124SMoriah Waterland 		/* ignore zone if not running */
1501*5c51f124SMoriah Waterland 		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
1502*5c51f124SMoriah Waterland 		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
1503*5c51f124SMoriah Waterland 			continue;
1504*5c51f124SMoriah Waterland 		}
1505*5c51f124SMoriah Waterland 
1506*5c51f124SMoriah Waterland 		/* unlock this zone */
1507*5c51f124SMoriah Waterland 		b = _z_unlock_zone(&a_zlst[i], a_lflags);
1508*5c51f124SMoriah Waterland 
1509*5c51f124SMoriah Waterland 		if (b != B_TRUE) {
1510*5c51f124SMoriah Waterland 			errors = B_TRUE;
1511*5c51f124SMoriah Waterland 		} else {
1512*5c51f124SMoriah Waterland 			/* mark zone as unlocked */
1513*5c51f124SMoriah Waterland 			a_zlst[i]._zlStatus &= ~ZST_LOCKED;
1514*5c51f124SMoriah Waterland 		}
1515*5c51f124SMoriah Waterland 	}
1516*5c51f124SMoriah Waterland 
1517*5c51f124SMoriah Waterland 	/* unlock this zone */
1518*5c51f124SMoriah Waterland 
1519*5c51f124SMoriah Waterland 	if (z_unlock_this_zone(a_lflags) != B_TRUE) {
1520*5c51f124SMoriah Waterland 		errors = B_TRUE;
1521*5c51f124SMoriah Waterland 	}
1522*5c51f124SMoriah Waterland 
1523*5c51f124SMoriah Waterland 	return (errors);
1524*5c51f124SMoriah Waterland }
1525*5c51f124SMoriah Waterland 
1526*5c51f124SMoriah Waterland /*
1527*5c51f124SMoriah Waterland  * Name:	z_verify_zone_spec
1528*5c51f124SMoriah Waterland  * Description:	Verify list of zones on which actions will be performed.
1529*5c51f124SMoriah Waterland  * Arguments:	None.
1530*5c51f124SMoriah Waterland  * Returns:	0 on success, -1 on error.
1531*5c51f124SMoriah Waterland  * NOTES:	Will call _z_program_error if there are zones on the specified
1532*5c51f124SMoriah Waterland  *		list that don't exist on the system. Requires that
1533*5c51f124SMoriah Waterland  *		z_set_zone_root is called first (if it is called at all).
1534*5c51f124SMoriah Waterland  */
1535*5c51f124SMoriah Waterland 
1536*5c51f124SMoriah Waterland int
1537*5c51f124SMoriah Waterland z_verify_zone_spec(void)
1538*5c51f124SMoriah Waterland {
1539*5c51f124SMoriah Waterland 	FILE		*zoneIndexFP;
1540*5c51f124SMoriah Waterland 	boolean_t	errors;
1541*5c51f124SMoriah Waterland 	char		zoneIndexPath[MAXPATHLEN];
1542*5c51f124SMoriah Waterland 	struct zoneent	*ze;
1543*5c51f124SMoriah Waterland 	zone_spec_t	*zent;
1544*5c51f124SMoriah Waterland 
1545*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
1546*5c51f124SMoriah Waterland 		_z_program_error(ERR_ZONES_NOT_IMPLEMENTED);
1547*5c51f124SMoriah Waterland 		return (-1);
1548*5c51f124SMoriah Waterland 	}
1549*5c51f124SMoriah Waterland 
1550*5c51f124SMoriah Waterland 	zoneIndexFP = setzoneent();
1551*5c51f124SMoriah Waterland 	if (zoneIndexFP == NULL) {
1552*5c51f124SMoriah Waterland 		_z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath,
1553*5c51f124SMoriah Waterland 		    strerror(errno));
1554*5c51f124SMoriah Waterland 		return (-1);
1555*5c51f124SMoriah Waterland 	}
1556*5c51f124SMoriah Waterland 
1557*5c51f124SMoriah Waterland 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1558*5c51f124SMoriah Waterland 		for (zent = _z_global_data._zone_spec;
1559*5c51f124SMoriah Waterland 		    zent != NULL; zent = zent->zl_next) {
1560*5c51f124SMoriah Waterland 			if (strcmp(zent->zl_name, ze->zone_name) == 0) {
1561*5c51f124SMoriah Waterland 				zent->zl_used = B_TRUE;
1562*5c51f124SMoriah Waterland 				break;
1563*5c51f124SMoriah Waterland 			}
1564*5c51f124SMoriah Waterland 		}
1565*5c51f124SMoriah Waterland 		free(ze);
1566*5c51f124SMoriah Waterland 	}
1567*5c51f124SMoriah Waterland 	endzoneent(zoneIndexFP);
1568*5c51f124SMoriah Waterland 
1569*5c51f124SMoriah Waterland 	errors = B_FALSE;
1570*5c51f124SMoriah Waterland 	for (zent = _z_global_data._zone_spec;
1571*5c51f124SMoriah Waterland 	    zent != NULL; zent = zent->zl_next) {
1572*5c51f124SMoriah Waterland 		if (!zent->zl_used) {
1573*5c51f124SMoriah Waterland 			_z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name);
1574*5c51f124SMoriah Waterland 			errors = B_TRUE;
1575*5c51f124SMoriah Waterland 		}
1576*5c51f124SMoriah Waterland 	}
1577*5c51f124SMoriah Waterland 	return (errors ? -1 : 0);
1578*5c51f124SMoriah Waterland }
1579*5c51f124SMoriah Waterland 
1580*5c51f124SMoriah Waterland /*
1581*5c51f124SMoriah Waterland  * Name:	z_zlist_change_zone_state
1582*5c51f124SMoriah Waterland  * Description:	Change the current state of the specified zone
1583*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1584*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return the
1585*5c51f124SMoriah Waterland  *		a_newState - the state to put the specified zone in
1586*5c51f124SMoriah Waterland  * Returns:	boolean_t
1587*5c51f124SMoriah Waterland  *			== B_TRUE - the zone is in the new state
1588*5c51f124SMoriah Waterland  *			== B_FALSE - unable to transition the zone to the
1589*5c51f124SMoriah Waterland  *				specified state
1590*5c51f124SMoriah Waterland  * NOTE:	This changes the "current kernel" state of the specified
1591*5c51f124SMoriah Waterland  *		zone. For example, to boot the zone, change the state
1592*5c51f124SMoriah Waterland  *		to "ZONE_STATE_RUNNING". To halt the zone, change the
1593*5c51f124SMoriah Waterland  *		state to "ZONE_STATE_INSTALLED".
1594*5c51f124SMoriah Waterland  */
1595*5c51f124SMoriah Waterland 
1596*5c51f124SMoriah Waterland boolean_t
1597*5c51f124SMoriah Waterland z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex,
1598*5c51f124SMoriah Waterland 	zone_state_t a_newState)
1599*5c51f124SMoriah Waterland {
1600*5c51f124SMoriah Waterland 	int	i;
1601*5c51f124SMoriah Waterland 
1602*5c51f124SMoriah Waterland 	/* entry debugging info */
1603*5c51f124SMoriah Waterland 
1604*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState);
1605*5c51f124SMoriah Waterland 
1606*5c51f124SMoriah Waterland 	/* ignore empty list */
1607*5c51f124SMoriah Waterland 
1608*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1609*5c51f124SMoriah Waterland 		return (B_FALSE);
1610*5c51f124SMoriah Waterland 	}
1611*5c51f124SMoriah Waterland 
1612*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1613*5c51f124SMoriah Waterland 
1614*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1615*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1616*5c51f124SMoriah Waterland 		;
1617*5c51f124SMoriah Waterland 
1618*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1619*5c51f124SMoriah Waterland 
1620*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1621*5c51f124SMoriah Waterland 		return (B_FALSE);
1622*5c51f124SMoriah Waterland 	}
1623*5c51f124SMoriah Waterland 
1624*5c51f124SMoriah Waterland 	/* return success if the zone is already in this state */
1625*5c51f124SMoriah Waterland 
1626*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlCurrKernelStatus == a_newState) {
1627*5c51f124SMoriah Waterland 		return (B_TRUE);
1628*5c51f124SMoriah Waterland 	}
1629*5c51f124SMoriah Waterland 
1630*5c51f124SMoriah Waterland 	/* take action on new state to set zone to */
1631*5c51f124SMoriah Waterland 
1632*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName,
1633*5c51f124SMoriah Waterland 	    a_zlst[i]._zlCurrKernelStatus, a_newState);
1634*5c51f124SMoriah Waterland 
1635*5c51f124SMoriah Waterland 	switch (a_newState) {
1636*5c51f124SMoriah Waterland 	case ZONE_STATE_RUNNING:
1637*5c51f124SMoriah Waterland 	case ZONE_STATE_MOUNTED:
1638*5c51f124SMoriah Waterland 		/* these states mean "boot the zone" */
1639*5c51f124SMoriah Waterland 		return (_z_make_zone_running(&a_zlst[i]));
1640*5c51f124SMoriah Waterland 
1641*5c51f124SMoriah Waterland 	case ZONE_STATE_DOWN:
1642*5c51f124SMoriah Waterland 	case ZONE_STATE_INSTALLED:
1643*5c51f124SMoriah Waterland 		/* these states mean "halt the zone" */
1644*5c51f124SMoriah Waterland 		return (_z_make_zone_down(&a_zlst[i]));
1645*5c51f124SMoriah Waterland 
1646*5c51f124SMoriah Waterland 	case ZONE_STATE_READY:
1647*5c51f124SMoriah Waterland 		return (_z_make_zone_ready(&a_zlst[i]));
1648*5c51f124SMoriah Waterland 
1649*5c51f124SMoriah Waterland 	case ZONE_STATE_CONFIGURED:
1650*5c51f124SMoriah Waterland 	case ZONE_STATE_INCOMPLETE:
1651*5c51f124SMoriah Waterland 	case ZONE_STATE_SHUTTING_DOWN:
1652*5c51f124SMoriah Waterland 	default:
1653*5c51f124SMoriah Waterland 		/* do not know how to change zone to this state */
1654*5c51f124SMoriah Waterland 		return (B_FALSE);
1655*5c51f124SMoriah Waterland 	}
1656*5c51f124SMoriah Waterland }
1657*5c51f124SMoriah Waterland 
1658*5c51f124SMoriah Waterland /*
1659*5c51f124SMoriah Waterland  * Name:	z_is_zone_branded
1660*5c51f124SMoriah Waterland  * Description:	Determine whether zone has a non-native brand
1661*5c51f124SMoriah Waterland  * Arguments:	a_zoneName - name of the zone to check for branding
1662*5c51f124SMoriah Waterland  * Returns:	boolean_t
1663*5c51f124SMoriah Waterland  *			== B_TRUE - zone has a non-native brand
1664*5c51f124SMoriah Waterland  *			== B_FALSE - zone is native
1665*5c51f124SMoriah Waterland  */
1666*5c51f124SMoriah Waterland boolean_t
1667*5c51f124SMoriah Waterland z_is_zone_branded(char *zoneName)
1668*5c51f124SMoriah Waterland {
1669*5c51f124SMoriah Waterland 	char			brandname[MAXNAMELEN];
1670*5c51f124SMoriah Waterland 	int			err;
1671*5c51f124SMoriah Waterland 
1672*5c51f124SMoriah Waterland 	/* if zones are not implemented, return FALSE */
1673*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
1674*5c51f124SMoriah Waterland 		return (B_FALSE);
1675*5c51f124SMoriah Waterland 	}
1676*5c51f124SMoriah Waterland 
1677*5c51f124SMoriah Waterland 	/* if brands are not implemented, return FALSE */
1678*5c51f124SMoriah Waterland 	if (!z_brands_are_implemented()) {
1679*5c51f124SMoriah Waterland 		return (B_FALSE);
1680*5c51f124SMoriah Waterland 	}
1681*5c51f124SMoriah Waterland 
1682*5c51f124SMoriah Waterland 	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1683*5c51f124SMoriah Waterland 	if (err != Z_OK) {
1684*5c51f124SMoriah Waterland 		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1685*5c51f124SMoriah Waterland 		return (B_FALSE);
1686*5c51f124SMoriah Waterland 	}
1687*5c51f124SMoriah Waterland 
1688*5c51f124SMoriah Waterland 	/*
1689*5c51f124SMoriah Waterland 	 * Both "native" and "cluster" are native brands
1690*5c51f124SMoriah Waterland 	 * that use the standard facilities in the areas
1691*5c51f124SMoriah Waterland 	 * of packaging/installation/patching/update.
1692*5c51f124SMoriah Waterland 	 */
1693*5c51f124SMoriah Waterland 	if (streq(brandname, NATIVE_BRAND_NAME) ||
1694*5c51f124SMoriah Waterland 	    streq(brandname, CLUSTER_BRAND_NAME)) {
1695*5c51f124SMoriah Waterland 		return (B_FALSE);
1696*5c51f124SMoriah Waterland 	} else {
1697*5c51f124SMoriah Waterland 		return (B_TRUE);
1698*5c51f124SMoriah Waterland 	}
1699*5c51f124SMoriah Waterland }
1700*5c51f124SMoriah Waterland 
1701*5c51f124SMoriah Waterland /*
1702*5c51f124SMoriah Waterland  * Name:	z_is_zone_brand_in_list
1703*5c51f124SMoriah Waterland  * Description:	Determine whether zone's brand has a match in the list
1704*5c51f124SMoriah Waterland  *              brands passed in.
1705*5c51f124SMoriah Waterland  * Arguments:	zoneName - name of the zone to check for branding
1706*5c51f124SMoriah Waterland  *              list - list of brands to check the zone against
1707*5c51f124SMoriah Waterland  * Returns:	boolean_t
1708*5c51f124SMoriah Waterland  *			== B_TRUE - zone has a matching brand
1709*5c51f124SMoriah Waterland  *			== B_FALSE - zone brand is not in list
1710*5c51f124SMoriah Waterland  */
1711*5c51f124SMoriah Waterland boolean_t
1712*5c51f124SMoriah Waterland z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list)
1713*5c51f124SMoriah Waterland {
1714*5c51f124SMoriah Waterland 	char			brandname[MAXNAMELEN];
1715*5c51f124SMoriah Waterland 	int			err;
1716*5c51f124SMoriah Waterland 	zoneBrandList_t		*sp;
1717*5c51f124SMoriah Waterland 
1718*5c51f124SMoriah Waterland 	if (zoneName == NULL || list == NULL)
1719*5c51f124SMoriah Waterland 		return (B_FALSE);
1720*5c51f124SMoriah Waterland 
1721*5c51f124SMoriah Waterland 	/* if zones are not implemented, return FALSE */
1722*5c51f124SMoriah Waterland 	if (!z_zones_are_implemented()) {
1723*5c51f124SMoriah Waterland 		return (B_FALSE);
1724*5c51f124SMoriah Waterland 	}
1725*5c51f124SMoriah Waterland 
1726*5c51f124SMoriah Waterland 	/* if brands are not implemented, return FALSE */
1727*5c51f124SMoriah Waterland 	if (!z_brands_are_implemented()) {
1728*5c51f124SMoriah Waterland 		return (B_FALSE);
1729*5c51f124SMoriah Waterland 	}
1730*5c51f124SMoriah Waterland 
1731*5c51f124SMoriah Waterland 	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1732*5c51f124SMoriah Waterland 	if (err != Z_OK) {
1733*5c51f124SMoriah Waterland 		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1734*5c51f124SMoriah Waterland 		return (B_FALSE);
1735*5c51f124SMoriah Waterland 	}
1736*5c51f124SMoriah Waterland 
1737*5c51f124SMoriah Waterland 	for (sp = list; sp != NULL; sp = sp->next) {
1738*5c51f124SMoriah Waterland 		if (sp->string_ptr != NULL &&
1739*5c51f124SMoriah Waterland 		    strcmp(sp->string_ptr, brandname) == 0) {
1740*5c51f124SMoriah Waterland 			return (B_TRUE);
1741*5c51f124SMoriah Waterland 		}
1742*5c51f124SMoriah Waterland 	}
1743*5c51f124SMoriah Waterland 
1744*5c51f124SMoriah Waterland 	return (B_FALSE);
1745*5c51f124SMoriah Waterland }
1746*5c51f124SMoriah Waterland 
1747*5c51f124SMoriah Waterland /*
1748*5c51f124SMoriah Waterland  * Name:	z_zlist_get_current_state
1749*5c51f124SMoriah Waterland  * Description:	Determine the current kernel state of the specified zone
1750*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1751*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return
1752*5c51f124SMoriah Waterland  * Returns:	zone_state_t
1753*5c51f124SMoriah Waterland  *			The current state of the specified zone is returned
1754*5c51f124SMoriah Waterland  */
1755*5c51f124SMoriah Waterland 
1756*5c51f124SMoriah Waterland zone_state_t
1757*5c51f124SMoriah Waterland z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex)
1758*5c51f124SMoriah Waterland {
1759*5c51f124SMoriah Waterland 	int	i;
1760*5c51f124SMoriah Waterland 
1761*5c51f124SMoriah Waterland 	/* ignore empty list */
1762*5c51f124SMoriah Waterland 
1763*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1764*5c51f124SMoriah Waterland 		return (ZONE_STATE_INCOMPLETE);
1765*5c51f124SMoriah Waterland 	}
1766*5c51f124SMoriah Waterland 
1767*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1768*5c51f124SMoriah Waterland 
1769*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1770*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1771*5c51f124SMoriah Waterland 		;
1772*5c51f124SMoriah Waterland 
1773*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1774*5c51f124SMoriah Waterland 
1775*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1776*5c51f124SMoriah Waterland 		return (ZONE_STATE_INCOMPLETE);
1777*5c51f124SMoriah Waterland 	}
1778*5c51f124SMoriah Waterland 
1779*5c51f124SMoriah Waterland 	/* return selected zone's current kernel state */
1780*5c51f124SMoriah Waterland 
1781*5c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_GET_ZONE_STATE,
1782*5c51f124SMoriah Waterland 	    a_zlst[i]._zlName ? a_zlst[i]._zlName : "",
1783*5c51f124SMoriah Waterland 	    a_zlst[i]._zlCurrKernelStatus);
1784*5c51f124SMoriah Waterland 
1785*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlCurrKernelStatus);
1786*5c51f124SMoriah Waterland }
1787*5c51f124SMoriah Waterland 
1788*5c51f124SMoriah Waterland /*
1789*5c51f124SMoriah Waterland  * Name:	z_zlist_get_inherited_pkg_dirs
1790*5c51f124SMoriah Waterland  * Description:	Determine directories inherited by specified zone
1791*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1792*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return the
1793*5c51f124SMoriah Waterland  *			inherited directories list
1794*5c51f124SMoriah Waterland  * Returns:	char **
1795*5c51f124SMoriah Waterland  *			== NULL - zone does not inherit any directories
1796*5c51f124SMoriah Waterland  *				- zone index is invalid
1797*5c51f124SMoriah Waterland  *			!= NULL - array of inherited directories
1798*5c51f124SMoriah Waterland  * NOTE:    	Any directory list returned is located in static storage that
1799*5c51f124SMoriah Waterland  *		must NEVER be free()ed by the caller.
1800*5c51f124SMoriah Waterland  */
1801*5c51f124SMoriah Waterland 
1802*5c51f124SMoriah Waterland extern char **
1803*5c51f124SMoriah Waterland z_zlist_get_inherited_pkg_dirs(zoneList_t a_zlst, int a_zoneIndex)
1804*5c51f124SMoriah Waterland {
1805*5c51f124SMoriah Waterland 	int	i;
1806*5c51f124SMoriah Waterland 
1807*5c51f124SMoriah Waterland 	/* if zones are not implemented, return empty list */
1808*5c51f124SMoriah Waterland 
1809*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
1810*5c51f124SMoriah Waterland 		return (NULL);
1811*5c51f124SMoriah Waterland 	}
1812*5c51f124SMoriah Waterland 
1813*5c51f124SMoriah Waterland 	/* ignore empty list */
1814*5c51f124SMoriah Waterland 
1815*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1816*5c51f124SMoriah Waterland 		return (NULL);
1817*5c51f124SMoriah Waterland 	}
1818*5c51f124SMoriah Waterland 
1819*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1820*5c51f124SMoriah Waterland 
1821*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1822*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1823*5c51f124SMoriah Waterland 		;
1824*5c51f124SMoriah Waterland 
1825*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1826*5c51f124SMoriah Waterland 
1827*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1828*5c51f124SMoriah Waterland 		return (NULL);
1829*5c51f124SMoriah Waterland 	}
1830*5c51f124SMoriah Waterland 
1831*5c51f124SMoriah Waterland 	/* return selected zone's inherited directories */
1832*5c51f124SMoriah Waterland 
1833*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlInheritedDirs);
1834*5c51f124SMoriah Waterland }
1835*5c51f124SMoriah Waterland 
1836*5c51f124SMoriah Waterland /*
1837*5c51f124SMoriah Waterland  * Name:	z_zlist_get_original_state
1838*5c51f124SMoriah Waterland  * Description:	Return the original kernal state of the specified zone
1839*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1840*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return the
1841*5c51f124SMoriah Waterland  * Returns:	zone_state_t
1842*5c51f124SMoriah Waterland  *			The original state of the specified zone is returned.
1843*5c51f124SMoriah Waterland  *			This is the state of the zone when the zoneList_t
1844*5c51f124SMoriah Waterland  *			object was first generated.
1845*5c51f124SMoriah Waterland  */
1846*5c51f124SMoriah Waterland 
1847*5c51f124SMoriah Waterland zone_state_t
1848*5c51f124SMoriah Waterland z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex)
1849*5c51f124SMoriah Waterland {
1850*5c51f124SMoriah Waterland 	int	i;
1851*5c51f124SMoriah Waterland 
1852*5c51f124SMoriah Waterland 	/* ignore empty list */
1853*5c51f124SMoriah Waterland 
1854*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1855*5c51f124SMoriah Waterland 		return (ZONE_STATE_INCOMPLETE);
1856*5c51f124SMoriah Waterland 	}
1857*5c51f124SMoriah Waterland 
1858*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1859*5c51f124SMoriah Waterland 
1860*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1861*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1862*5c51f124SMoriah Waterland 		;
1863*5c51f124SMoriah Waterland 
1864*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1865*5c51f124SMoriah Waterland 
1866*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1867*5c51f124SMoriah Waterland 		return (ZONE_STATE_INCOMPLETE);
1868*5c51f124SMoriah Waterland 	}
1869*5c51f124SMoriah Waterland 
1870*5c51f124SMoriah Waterland 	/* return selected zone's original kernel state */
1871*5c51f124SMoriah Waterland 
1872*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlOrigKernelStatus);
1873*5c51f124SMoriah Waterland }
1874*5c51f124SMoriah Waterland 
1875*5c51f124SMoriah Waterland /*
1876*5c51f124SMoriah Waterland  * Name:	z_zlist_get_scratch
1877*5c51f124SMoriah Waterland  * Description:	Determine name of scratch zone
1878*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1879*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to use
1880*5c51f124SMoriah Waterland  * Return:	char *
1881*5c51f124SMoriah Waterland  *			== NULL - zone name could not be determined
1882*5c51f124SMoriah Waterland  *			!= NULL - pointer to string representing scratch zone
1883*5c51f124SMoriah Waterland  * NOTE:    	Any name returned is placed in static storage that must
1884*5c51f124SMoriah Waterland  *		NEVER be free()ed by the caller.
1885*5c51f124SMoriah Waterland  */
1886*5c51f124SMoriah Waterland 
1887*5c51f124SMoriah Waterland char *
1888*5c51f124SMoriah Waterland z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex)
1889*5c51f124SMoriah Waterland {
1890*5c51f124SMoriah Waterland 	int	i;
1891*5c51f124SMoriah Waterland 
1892*5c51f124SMoriah Waterland 	/* ignore empty list */
1893*5c51f124SMoriah Waterland 
1894*5c51f124SMoriah Waterland 	if (a_zlst == NULL)
1895*5c51f124SMoriah Waterland 		return (NULL);
1896*5c51f124SMoriah Waterland 
1897*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1898*5c51f124SMoriah Waterland 
1899*5c51f124SMoriah Waterland 	for (i = 0; i != a_zoneIndex; i++) {
1900*5c51f124SMoriah Waterland 		if (a_zlst[i]._zlName == NULL)
1901*5c51f124SMoriah Waterland 			return (NULL);
1902*5c51f124SMoriah Waterland 	}
1903*5c51f124SMoriah Waterland 
1904*5c51f124SMoriah Waterland 	/* return selected zone's scratch name */
1905*5c51f124SMoriah Waterland 
1906*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName :
1907*5c51f124SMoriah Waterland 	    a_zlst[i]._zlScratchName);
1908*5c51f124SMoriah Waterland }
1909*5c51f124SMoriah Waterland 
1910*5c51f124SMoriah Waterland /*
1911*5c51f124SMoriah Waterland  * Name:	z_zlist_get_zonename
1912*5c51f124SMoriah Waterland  * Description:	Determine name of specified zone
1913*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1914*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return the
1915*5c51f124SMoriah Waterland  * Return:	char *
1916*5c51f124SMoriah Waterland  *			== NULL - zone name could not be determined
1917*5c51f124SMoriah Waterland  *			!= NULL - pointer to string representing zone name
1918*5c51f124SMoriah Waterland  * NOTE:    	Any zoneList_t returned is placed in static storage that must
1919*5c51f124SMoriah Waterland  *		NEVER be free()ed by the caller.
1920*5c51f124SMoriah Waterland  */
1921*5c51f124SMoriah Waterland 
1922*5c51f124SMoriah Waterland char *
1923*5c51f124SMoriah Waterland z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex)
1924*5c51f124SMoriah Waterland {
1925*5c51f124SMoriah Waterland 	int	i;
1926*5c51f124SMoriah Waterland 
1927*5c51f124SMoriah Waterland 	/* ignore empty list */
1928*5c51f124SMoriah Waterland 
1929*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1930*5c51f124SMoriah Waterland 		return ((char *)NULL);
1931*5c51f124SMoriah Waterland 	}
1932*5c51f124SMoriah Waterland 
1933*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1934*5c51f124SMoriah Waterland 
1935*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1936*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1937*5c51f124SMoriah Waterland 		;
1938*5c51f124SMoriah Waterland 
1939*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1940*5c51f124SMoriah Waterland 
1941*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1942*5c51f124SMoriah Waterland 		return (NULL);
1943*5c51f124SMoriah Waterland 	}
1944*5c51f124SMoriah Waterland 
1945*5c51f124SMoriah Waterland 	/* return selected zone's name */
1946*5c51f124SMoriah Waterland 
1947*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlName);
1948*5c51f124SMoriah Waterland }
1949*5c51f124SMoriah Waterland 
1950*5c51f124SMoriah Waterland /*
1951*5c51f124SMoriah Waterland  * Name:	z_zlist_get_zonepath
1952*5c51f124SMoriah Waterland  * Description:	Determine zonepath of specified zone
1953*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1954*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return
1955*5c51f124SMoriah Waterland  * Return:	char *
1956*5c51f124SMoriah Waterland  *			== NULL - zonepath could not be determined
1957*5c51f124SMoriah Waterland  *			!= NULL - pointer to string representing zonepath
1958*5c51f124SMoriah Waterland  * NOTE:    	Any zoneList_t returned is placed in static storage that must
1959*5c51f124SMoriah Waterland  *		NEVER be free()ed by the caller.
1960*5c51f124SMoriah Waterland  */
1961*5c51f124SMoriah Waterland 
1962*5c51f124SMoriah Waterland char *
1963*5c51f124SMoriah Waterland z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex)
1964*5c51f124SMoriah Waterland {
1965*5c51f124SMoriah Waterland 	int	i;
1966*5c51f124SMoriah Waterland 
1967*5c51f124SMoriah Waterland 	/* ignore empty list */
1968*5c51f124SMoriah Waterland 
1969*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
1970*5c51f124SMoriah Waterland 		return ((char *)NULL);
1971*5c51f124SMoriah Waterland 	}
1972*5c51f124SMoriah Waterland 
1973*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
1974*5c51f124SMoriah Waterland 
1975*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
1976*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1977*5c51f124SMoriah Waterland 		;
1978*5c51f124SMoriah Waterland 
1979*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
1980*5c51f124SMoriah Waterland 
1981*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
1982*5c51f124SMoriah Waterland 		return (NULL);
1983*5c51f124SMoriah Waterland 	}
1984*5c51f124SMoriah Waterland 
1985*5c51f124SMoriah Waterland 	/* return selected zone's zonepath */
1986*5c51f124SMoriah Waterland 
1987*5c51f124SMoriah Waterland 	return (a_zlst[i]._zlPath);
1988*5c51f124SMoriah Waterland }
1989*5c51f124SMoriah Waterland 
1990*5c51f124SMoriah Waterland boolean_t
1991*5c51f124SMoriah Waterland z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex)
1992*5c51f124SMoriah Waterland {
1993*5c51f124SMoriah Waterland 	int	i;
1994*5c51f124SMoriah Waterland 
1995*5c51f124SMoriah Waterland 	/* if zones are not implemented, return error */
1996*5c51f124SMoriah Waterland 
1997*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
1998*5c51f124SMoriah Waterland 		return (B_FALSE);
1999*5c51f124SMoriah Waterland 	}
2000*5c51f124SMoriah Waterland 
2001*5c51f124SMoriah Waterland 	/* ignore empty list */
2002*5c51f124SMoriah Waterland 
2003*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
2004*5c51f124SMoriah Waterland 		return (B_FALSE);
2005*5c51f124SMoriah Waterland 	}
2006*5c51f124SMoriah Waterland 
2007*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
2008*5c51f124SMoriah Waterland 
2009*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
2010*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
2011*5c51f124SMoriah Waterland 		;
2012*5c51f124SMoriah Waterland 
2013*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
2014*5c51f124SMoriah Waterland 
2015*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
2016*5c51f124SMoriah Waterland 		return (B_FALSE);
2017*5c51f124SMoriah Waterland 	}
2018*5c51f124SMoriah Waterland 
2019*5c51f124SMoriah Waterland 	/* choose based on current state */
2020*5c51f124SMoriah Waterland 
2021*5c51f124SMoriah Waterland 	switch (a_zlst[i]._zlCurrKernelStatus) {
2022*5c51f124SMoriah Waterland 	case ZONE_STATE_RUNNING:
2023*5c51f124SMoriah Waterland 	case ZONE_STATE_MOUNTED:
2024*5c51f124SMoriah Waterland 		/* already running */
2025*5c51f124SMoriah Waterland 		return (B_TRUE);
2026*5c51f124SMoriah Waterland 
2027*5c51f124SMoriah Waterland 	case ZONE_STATE_INSTALLED:
2028*5c51f124SMoriah Waterland 	case ZONE_STATE_DOWN:
2029*5c51f124SMoriah Waterland 	case ZONE_STATE_READY:
2030*5c51f124SMoriah Waterland 	case ZONE_STATE_SHUTTING_DOWN:
2031*5c51f124SMoriah Waterland 		/* return false if the zone cannot be booted */
2032*5c51f124SMoriah Waterland 
2033*5c51f124SMoriah Waterland 		if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) {
2034*5c51f124SMoriah Waterland 			return (B_FALSE);
2035*5c51f124SMoriah Waterland 		}
2036*5c51f124SMoriah Waterland 
2037*5c51f124SMoriah Waterland 		return (B_TRUE);
2038*5c51f124SMoriah Waterland 
2039*5c51f124SMoriah Waterland 	case ZONE_STATE_CONFIGURED:
2040*5c51f124SMoriah Waterland 	case ZONE_STATE_INCOMPLETE:
2041*5c51f124SMoriah Waterland 	default:
2042*5c51f124SMoriah Waterland 		/* cannot transition (boot) these states */
2043*5c51f124SMoriah Waterland 		return (B_FALSE);
2044*5c51f124SMoriah Waterland 	}
2045*5c51f124SMoriah Waterland }
2046*5c51f124SMoriah Waterland 
2047*5c51f124SMoriah Waterland /*
2048*5c51f124SMoriah Waterland  * Name:	z_zlist_restore_zone_state
2049*5c51f124SMoriah Waterland  * Description:	Return the zone to the state it was originally in
2050*5c51f124SMoriah Waterland  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
2051*5c51f124SMoriah Waterland  *		a_zoneIndex - index into a_zlst of the zone to return the
2052*5c51f124SMoriah Waterland  * Returns:	boolean_t
2053*5c51f124SMoriah Waterland  *			== B_TRUE - the zone's state has been restored
2054*5c51f124SMoriah Waterland  *			== B_FALSE - unable to transition the zone to its
2055*5c51f124SMoriah Waterland  *				original state
2056*5c51f124SMoriah Waterland  */
2057*5c51f124SMoriah Waterland 
2058*5c51f124SMoriah Waterland boolean_t
2059*5c51f124SMoriah Waterland z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex)
2060*5c51f124SMoriah Waterland {
2061*5c51f124SMoriah Waterland 	int		i;
2062*5c51f124SMoriah Waterland 
2063*5c51f124SMoriah Waterland 	/* ignore empty list */
2064*5c51f124SMoriah Waterland 
2065*5c51f124SMoriah Waterland 	if (a_zlst == (zoneList_t)NULL) {
2066*5c51f124SMoriah Waterland 		return (B_FALSE);
2067*5c51f124SMoriah Waterland 	}
2068*5c51f124SMoriah Waterland 
2069*5c51f124SMoriah Waterland 	/* find the specified zone in the list */
2070*5c51f124SMoriah Waterland 
2071*5c51f124SMoriah Waterland 	for (i = 0; (i != a_zoneIndex) &&
2072*5c51f124SMoriah Waterland 	    (a_zlst[i]._zlName != (char *)NULL); i++)
2073*5c51f124SMoriah Waterland 		;
2074*5c51f124SMoriah Waterland 
2075*5c51f124SMoriah Waterland 	/* return error if the specified zone does not exist */
2076*5c51f124SMoriah Waterland 
2077*5c51f124SMoriah Waterland 	if (a_zlst[i]._zlName == (char *)NULL) {
2078*5c51f124SMoriah Waterland 		return (B_FALSE);
2079*5c51f124SMoriah Waterland 	}
2080*5c51f124SMoriah Waterland 
2081*5c51f124SMoriah Waterland 	/* transition the zone back to its original state */
2082*5c51f124SMoriah Waterland 
2083*5c51f124SMoriah Waterland 	return (z_zlist_change_zone_state(a_zlst,
2084*5c51f124SMoriah Waterland 	    a_zoneIndex, a_zlst[i]._zlOrigKernelStatus));
2085*5c51f124SMoriah Waterland }
2086*5c51f124SMoriah Waterland 
2087*5c51f124SMoriah Waterland /*
2088*5c51f124SMoriah Waterland  * Name:	z_zone_exec
2089*5c51f124SMoriah Waterland  * Description:	Execute a Unix command in a specified zone and return results
2090*5c51f124SMoriah Waterland  * Arguments:	a_zoneName - pointer to string representing the name of the zone
2091*5c51f124SMoriah Waterland  *			to execute the specified command in
2092*5c51f124SMoriah Waterland  *		a_path - pointer to string representing the full path *in the
2093*5c51f124SMoriah Waterland  *			non-global zone named by a_zoneName* of the Unix command
2094*5c51f124SMoriah Waterland  *			to be executed
2095*5c51f124SMoriah Waterland  *		a_argv[] - Pointer to array of character strings representing
2096*5c51f124SMoriah Waterland  *			the arguments to be passed to the Unix command. The list
2097*5c51f124SMoriah Waterland  *			must be termianted with an element that is (char *)NULL
2098*5c51f124SMoriah Waterland  *		NOTE: a_argv[0] is the "command name" passed to the command
2099*5c51f124SMoriah Waterland  *		a_stdoutPath - Pointer to string representing the path to a file
2100*5c51f124SMoriah Waterland  *			into which all output to "stdout" from the Unix command
2101*5c51f124SMoriah Waterland  *			is placed.
2102*5c51f124SMoriah Waterland  *			== (char *)NULL - leave stdout open and pass through
2103*5c51f124SMoriah Waterland  *			== "/dev/null" - discard stdout output
2104*5c51f124SMoriah Waterland  *		a_strerrPath - Pointer to string representing the path to a file
2105*5c51f124SMoriah Waterland  *			into which all output to "stderr" from the Unix command
2106*5c51f124SMoriah Waterland  *			is placed.
2107*5c51f124SMoriah Waterland  *			== (char *)NULL - leave stderr open and pass through
2108*5c51f124SMoriah Waterland  *			== "/dev/null" - discard stderr output
2109*5c51f124SMoriah Waterland  *		a_fds - Pointer to array of integers representing file
2110*5c51f124SMoriah Waterland  *			descriptors to remain open during the call - all
2111*5c51f124SMoriah Waterland  *			file descriptors above STDERR_FILENO not in this
2112*5c51f124SMoriah Waterland  *			list will be closed.
2113*5c51f124SMoriah Waterland  * Returns:	int
2114*5c51f124SMoriah Waterland  *			The return (exit) code from the specified Unix command
2115*5c51f124SMoriah Waterland  *			Special return codes:
2116*5c51f124SMoriah Waterland  *			-1 : failure to exec process
2117*5c51f124SMoriah Waterland  *			-2 : could not create contract for greenline
2118*5c51f124SMoriah Waterland  *			-3 : fork() failed
2119*5c51f124SMoriah Waterland  *			-4 : could not open stdout capture file
2120*5c51f124SMoriah Waterland  *			-5 : error from 'waitpid' other than EINTR
2121*5c51f124SMoriah Waterland  *			-6 : zones are not supported
2122*5c51f124SMoriah Waterland  * NOTE:	All file descriptores other than 0, 1 and 2 are closed except
2123*5c51f124SMoriah Waterland  *		for those file descriptors listed in the a_fds array.
2124*5c51f124SMoriah Waterland  */
2125*5c51f124SMoriah Waterland 
2126*5c51f124SMoriah Waterland int
2127*5c51f124SMoriah Waterland z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[],
2128*5c51f124SMoriah Waterland 	char *a_stdoutPath, char *a_stderrPath, int *a_fds)
2129*5c51f124SMoriah Waterland {
2130*5c51f124SMoriah Waterland 	int			final_status;
2131*5c51f124SMoriah Waterland 	int			lerrno;
2132*5c51f124SMoriah Waterland 	int			status;
2133*5c51f124SMoriah Waterland 	int			tmpl_fd;
2134*5c51f124SMoriah Waterland 	pid_t			child_pid;
2135*5c51f124SMoriah Waterland 	pid_t			result_pid;
2136*5c51f124SMoriah Waterland 	struct sigaction	nact;
2137*5c51f124SMoriah Waterland 	struct sigaction	oact;
2138*5c51f124SMoriah Waterland 	void			(*funcSighup)();
2139*5c51f124SMoriah Waterland 	void			(*funcSigint)();
2140*5c51f124SMoriah Waterland 
2141*5c51f124SMoriah Waterland 	/* if zones are not implemented, return TRUE */
2142*5c51f124SMoriah Waterland 
2143*5c51f124SMoriah Waterland 	if (z_zones_are_implemented() == B_FALSE) {
2144*5c51f124SMoriah Waterland 		return (-6);	/* -6 : zones are not supported */
2145*5c51f124SMoriah Waterland 	}
2146*5c51f124SMoriah Waterland 
2147*5c51f124SMoriah Waterland 	if ((tmpl_fd = _zexec_init_template()) == -1) {
2148*5c51f124SMoriah Waterland 		_z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
2149*5c51f124SMoriah Waterland 		return (-2);	/* -2 : could not create greenline contract */
2150*5c51f124SMoriah Waterland 	}
2151*5c51f124SMoriah Waterland 
2152*5c51f124SMoriah Waterland 	/*
2153*5c51f124SMoriah Waterland 	 * hold SIGINT/SIGHUP signals and reset signal received counter;
2154*5c51f124SMoriah Waterland 	 * after the fork1() the parent and child need to setup their respective
2155*5c51f124SMoriah Waterland 	 * interrupt handling and release the hold on the signals
2156*5c51f124SMoriah Waterland 	 */
2157*5c51f124SMoriah Waterland 
2158*5c51f124SMoriah Waterland 	(void) sighold(SIGINT);
2159*5c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
2160*5c51f124SMoriah Waterland 
2161*5c51f124SMoriah Waterland 	_z_global_data._z_SigReceived = 0;	/* no signals received */
2162*5c51f124SMoriah Waterland 
2163*5c51f124SMoriah Waterland 	/*
2164*5c51f124SMoriah Waterland 	 * fork off a new process to execute command in;
2165*5c51f124SMoriah Waterland 	 * fork1() is used instead of vfork() so the child process can
2166*5c51f124SMoriah Waterland 	 * perform operations that would modify the parent process if
2167*5c51f124SMoriah Waterland 	 * vfork() were used
2168*5c51f124SMoriah Waterland 	 */
2169*5c51f124SMoriah Waterland 
2170*5c51f124SMoriah Waterland 	child_pid = fork1();
2171*5c51f124SMoriah Waterland 
2172*5c51f124SMoriah Waterland 	if (child_pid < 0) {
2173*5c51f124SMoriah Waterland 		/*
2174*5c51f124SMoriah Waterland 		 * *************************************************************
2175*5c51f124SMoriah Waterland 		 * fork failed!
2176*5c51f124SMoriah Waterland 		 * *************************************************************
2177*5c51f124SMoriah Waterland 		 */
2178*5c51f124SMoriah Waterland 
2179*5c51f124SMoriah Waterland 		(void) ct_tmpl_clear(tmpl_fd);
2180*5c51f124SMoriah Waterland 		(void) close(tmpl_fd);
2181*5c51f124SMoriah Waterland 		_z_program_error(ERR_FORK, strerror(errno));
2182*5c51f124SMoriah Waterland 
2183*5c51f124SMoriah Waterland 		/* release hold on signals */
2184*5c51f124SMoriah Waterland 
2185*5c51f124SMoriah Waterland 		(void) sigrelse(SIGHUP);
2186*5c51f124SMoriah Waterland 		(void) sigrelse(SIGINT);
2187*5c51f124SMoriah Waterland 
2188*5c51f124SMoriah Waterland 		return (-3);	/* -3 : fork() failed */
2189*5c51f124SMoriah Waterland 	}
2190*5c51f124SMoriah Waterland 
2191*5c51f124SMoriah Waterland 	if (child_pid == 0) {
2192*5c51f124SMoriah Waterland 		int	i;
2193*5c51f124SMoriah Waterland 
2194*5c51f124SMoriah Waterland 		/*
2195*5c51f124SMoriah Waterland 		 * *************************************************************
2196*5c51f124SMoriah Waterland 		 * This is the forked (child) process
2197*5c51f124SMoriah Waterland 		 * *************************************************************
2198*5c51f124SMoriah Waterland 		 */
2199*5c51f124SMoriah Waterland 
2200*5c51f124SMoriah Waterland 		(void) ct_tmpl_clear(tmpl_fd);
2201*5c51f124SMoriah Waterland 		(void) close(tmpl_fd);
2202*5c51f124SMoriah Waterland 
2203*5c51f124SMoriah Waterland 		/* reset any signals to default */
2204*5c51f124SMoriah Waterland 
2205*5c51f124SMoriah Waterland 		for (i = 0; i < NSIG; i++) {
2206*5c51f124SMoriah Waterland 			(void) sigset(i, SIG_DFL);
2207*5c51f124SMoriah Waterland 		}
2208*5c51f124SMoriah Waterland 
2209*5c51f124SMoriah Waterland 		/*
2210*5c51f124SMoriah Waterland 		 * close all file descriptors not in the a_fds list
2211*5c51f124SMoriah Waterland 		 */
2212*5c51f124SMoriah Waterland 
2213*5c51f124SMoriah Waterland 		(void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
2214*5c51f124SMoriah Waterland 
2215*5c51f124SMoriah Waterland 		/*
2216*5c51f124SMoriah Waterland 		 * if a file for stdout is present, open the file and use the
2217*5c51f124SMoriah Waterland 		 * file to capture stdout from the _zexec process
2218*5c51f124SMoriah Waterland 		 */
2219*5c51f124SMoriah Waterland 
2220*5c51f124SMoriah Waterland 		if (a_stdoutPath != (char *)NULL) {
2221*5c51f124SMoriah Waterland 			int	stdoutfd;
2222*5c51f124SMoriah Waterland 
2223*5c51f124SMoriah Waterland 			stdoutfd = open(a_stdoutPath,
2224*5c51f124SMoriah Waterland 			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2225*5c51f124SMoriah Waterland 			if (stdoutfd < 0) {
2226*5c51f124SMoriah Waterland 				_z_program_error(ERR_CAPTURE_FILE, a_stdoutPath,
2227*5c51f124SMoriah Waterland 				    strerror(errno));
2228*5c51f124SMoriah Waterland 				return (-4);
2229*5c51f124SMoriah Waterland 			}
2230*5c51f124SMoriah Waterland 
2231*5c51f124SMoriah Waterland 			(void) dup2(stdoutfd, STDOUT_FILENO);
2232*5c51f124SMoriah Waterland 			(void) close(stdoutfd);
2233*5c51f124SMoriah Waterland 		}
2234*5c51f124SMoriah Waterland 
2235*5c51f124SMoriah Waterland 		/*
2236*5c51f124SMoriah Waterland 		 * if a file for stderr is present, open the file and use the
2237*5c51f124SMoriah Waterland 		 * file to capture stderr from the _zexec process
2238*5c51f124SMoriah Waterland 		 */
2239*5c51f124SMoriah Waterland 
2240*5c51f124SMoriah Waterland 		if (a_stderrPath != (char *)NULL) {
2241*5c51f124SMoriah Waterland 			int	stderrfd;
2242*5c51f124SMoriah Waterland 
2243*5c51f124SMoriah Waterland 			stderrfd = open(a_stderrPath,
2244*5c51f124SMoriah Waterland 			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2245*5c51f124SMoriah Waterland 			if (stderrfd < 0) {
2246*5c51f124SMoriah Waterland 				_z_program_error(ERR_CAPTURE_FILE, a_stderrPath,
2247*5c51f124SMoriah Waterland 				    strerror(errno));
2248*5c51f124SMoriah Waterland 				return (-4);
2249*5c51f124SMoriah Waterland 			}
2250*5c51f124SMoriah Waterland 
2251*5c51f124SMoriah Waterland 			(void) dup2(stderrfd, STDERR_FILENO);
2252*5c51f124SMoriah Waterland 			(void) close(stderrfd);
2253*5c51f124SMoriah Waterland 		}
2254*5c51f124SMoriah Waterland 
2255*5c51f124SMoriah Waterland 		/* release all held signals */
2256*5c51f124SMoriah Waterland 
2257*5c51f124SMoriah Waterland 		(void) sigrelse(SIGHUP);
2258*5c51f124SMoriah Waterland 		(void) sigrelse(SIGINT);
2259*5c51f124SMoriah Waterland 
2260*5c51f124SMoriah Waterland 		/* execute command in the specified non-global zone */
2261*5c51f124SMoriah Waterland 
2262*5c51f124SMoriah Waterland 		_exit(_zexec(a_zoneName, a_path, a_argv));
2263*5c51f124SMoriah Waterland 	}
2264*5c51f124SMoriah Waterland 
2265*5c51f124SMoriah Waterland 	/*
2266*5c51f124SMoriah Waterland 	 * *********************************************************************
2267*5c51f124SMoriah Waterland 	 * This is the forking (parent) process
2268*5c51f124SMoriah Waterland 	 * *********************************************************************
2269*5c51f124SMoriah Waterland 	 */
2270*5c51f124SMoriah Waterland 
2271*5c51f124SMoriah Waterland 	/* register child process i.d. so signal handlers can pass signal on */
2272*5c51f124SMoriah Waterland 
2273*5c51f124SMoriah Waterland 	_z_global_data._z_ChildProcessId = child_pid;
2274*5c51f124SMoriah Waterland 
2275*5c51f124SMoriah Waterland 	/*
2276*5c51f124SMoriah Waterland 	 * setup signal handlers for SIGINT and SIGHUP and release hold
2277*5c51f124SMoriah Waterland 	 */
2278*5c51f124SMoriah Waterland 
2279*5c51f124SMoriah Waterland 	/* hook SIGINT to _z_sig_trap() */
2280*5c51f124SMoriah Waterland 
2281*5c51f124SMoriah Waterland 	nact.sa_handler = _z_sig_trap;
2282*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
2283*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
2284*5c51f124SMoriah Waterland 
2285*5c51f124SMoriah Waterland 	if (sigaction(SIGINT, &nact, &oact) < 0) {
2286*5c51f124SMoriah Waterland 		funcSigint = SIG_DFL;
2287*5c51f124SMoriah Waterland 	} else {
2288*5c51f124SMoriah Waterland 		funcSigint = oact.sa_handler;
2289*5c51f124SMoriah Waterland 	}
2290*5c51f124SMoriah Waterland 
2291*5c51f124SMoriah Waterland 	/* hook SIGHUP to _z_sig_trap() */
2292*5c51f124SMoriah Waterland 
2293*5c51f124SMoriah Waterland 	nact.sa_handler = _z_sig_trap;
2294*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
2295*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
2296*5c51f124SMoriah Waterland 
2297*5c51f124SMoriah Waterland 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
2298*5c51f124SMoriah Waterland 		funcSighup = SIG_DFL;
2299*5c51f124SMoriah Waterland 	} else {
2300*5c51f124SMoriah Waterland 		funcSighup = oact.sa_handler;
2301*5c51f124SMoriah Waterland 	}
2302*5c51f124SMoriah Waterland 
2303*5c51f124SMoriah Waterland 	/* release hold on signals */
2304*5c51f124SMoriah Waterland 
2305*5c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
2306*5c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
2307*5c51f124SMoriah Waterland 
2308*5c51f124SMoriah Waterland 	(void) ct_tmpl_clear(tmpl_fd);
2309*5c51f124SMoriah Waterland 	(void) close(tmpl_fd);
2310*5c51f124SMoriah Waterland 
2311*5c51f124SMoriah Waterland 	/*
2312*5c51f124SMoriah Waterland 	 * wait for the process to exit, reap child exit status
2313*5c51f124SMoriah Waterland 	 */
2314*5c51f124SMoriah Waterland 
2315*5c51f124SMoriah Waterland 	for (;;) {
2316*5c51f124SMoriah Waterland 		result_pid = waitpid(child_pid, &status, 0L);
2317*5c51f124SMoriah Waterland 		lerrno = (result_pid == -1 ? errno : 0);
2318*5c51f124SMoriah Waterland 
2319*5c51f124SMoriah Waterland 		/* break loop if child process status reaped */
2320*5c51f124SMoriah Waterland 
2321*5c51f124SMoriah Waterland 		if (result_pid != -1) {
2322*5c51f124SMoriah Waterland 			break;
2323*5c51f124SMoriah Waterland 		}
2324*5c51f124SMoriah Waterland 
2325*5c51f124SMoriah Waterland 		/* break loop if not interrupted out of waitpid */
2326*5c51f124SMoriah Waterland 
2327*5c51f124SMoriah Waterland 		if (errno != EINTR) {
2328*5c51f124SMoriah Waterland 			break;
2329*5c51f124SMoriah Waterland 		}
2330*5c51f124SMoriah Waterland 	}
2331*5c51f124SMoriah Waterland 
2332*5c51f124SMoriah Waterland 	/* reset child process i.d. so signal handlers do not pass signals on */
2333*5c51f124SMoriah Waterland 
2334*5c51f124SMoriah Waterland 	_z_global_data._z_ChildProcessId = -1;
2335*5c51f124SMoriah Waterland 
2336*5c51f124SMoriah Waterland 	/*
2337*5c51f124SMoriah Waterland 	 * If the child process terminated due to a call to exit(), then
2338*5c51f124SMoriah Waterland 	 * set results equal to the 8-bit exit status of the child process;
2339*5c51f124SMoriah Waterland 	 * otherwise, set the exit status to "-1" indicating that the child
2340*5c51f124SMoriah Waterland 	 * exited via a signal.
2341*5c51f124SMoriah Waterland 	 */
2342*5c51f124SMoriah Waterland 
2343*5c51f124SMoriah Waterland 	if (WIFEXITED(status)) {
2344*5c51f124SMoriah Waterland 		final_status = WEXITSTATUS(status);
2345*5c51f124SMoriah Waterland 		if ((_z_global_data._z_SigReceived != 0) &&
2346*5c51f124SMoriah Waterland 		    (final_status == 0)) {
2347*5c51f124SMoriah Waterland 			final_status = 1;
2348*5c51f124SMoriah Waterland 		}
2349*5c51f124SMoriah Waterland 	} else {
2350*5c51f124SMoriah Waterland 		final_status = -1;	/* -1 : failure to exec process */
2351*5c51f124SMoriah Waterland 	}
2352*5c51f124SMoriah Waterland 
2353*5c51f124SMoriah Waterland 	/* determine proper exit code */
2354*5c51f124SMoriah Waterland 
2355*5c51f124SMoriah Waterland 	if (result_pid == -1) {
2356*5c51f124SMoriah Waterland 		final_status = -5;	/* -5 : error from waitpid not EINTR */
2357*5c51f124SMoriah Waterland 	} else if (_z_global_data._z_SigReceived != 0) {
2358*5c51f124SMoriah Waterland 		final_status = -7;	/* -7 : interrupt received */
2359*5c51f124SMoriah Waterland 	}
2360*5c51f124SMoriah Waterland 
2361*5c51f124SMoriah Waterland 	/*
2362*5c51f124SMoriah Waterland 	 * reset signal handlers
2363*5c51f124SMoriah Waterland 	 */
2364*5c51f124SMoriah Waterland 
2365*5c51f124SMoriah Waterland 	/* reset SIGINT */
2366*5c51f124SMoriah Waterland 
2367*5c51f124SMoriah Waterland 	nact.sa_handler = funcSigint;
2368*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
2369*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
2370*5c51f124SMoriah Waterland 
2371*5c51f124SMoriah Waterland 	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2372*5c51f124SMoriah Waterland 
2373*5c51f124SMoriah Waterland 	/* reset SIGHUP */
2374*5c51f124SMoriah Waterland 
2375*5c51f124SMoriah Waterland 	nact.sa_handler = funcSighup;
2376*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
2377*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
2378*5c51f124SMoriah Waterland 
2379*5c51f124SMoriah Waterland 	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2380*5c51f124SMoriah Waterland 
2381*5c51f124SMoriah Waterland 	/*
2382*5c51f124SMoriah Waterland 	 * if signal received during command execution, interrupt
2383*5c51f124SMoriah Waterland 	 * this process now.
2384*5c51f124SMoriah Waterland 	 */
2385*5c51f124SMoriah Waterland 
2386*5c51f124SMoriah Waterland 	if (_z_global_data._z_SigReceived != 0) {
2387*5c51f124SMoriah Waterland 		(void) kill(getpid(), SIGINT);
2388*5c51f124SMoriah Waterland 	}
2389*5c51f124SMoriah Waterland 
2390*5c51f124SMoriah Waterland 	/* set errno and return */
2391*5c51f124SMoriah Waterland 
2392*5c51f124SMoriah Waterland 	errno = lerrno;
2393*5c51f124SMoriah Waterland 
2394*5c51f124SMoriah Waterland 	return (final_status);
2395*5c51f124SMoriah Waterland }
2396*5c51f124SMoriah Waterland 
2397*5c51f124SMoriah Waterland /*
2398*5c51f124SMoriah Waterland  * Name:	z_zones_are_implemented
2399*5c51f124SMoriah Waterland  * Description:	Determine if any zone operations can be performed
2400*5c51f124SMoriah Waterland  * Arguments:	void
2401*5c51f124SMoriah Waterland  * Returns:	boolean_t
2402*5c51f124SMoriah Waterland  *			== B_TRUE - zone operations are available
2403*5c51f124SMoriah Waterland  *			== B_FALSE - no zone operations can be done
2404*5c51f124SMoriah Waterland  */
2405*5c51f124SMoriah Waterland 
2406*5c51f124SMoriah Waterland boolean_t
2407*5c51f124SMoriah Waterland z_zones_are_implemented(void)
2408*5c51f124SMoriah Waterland {
2409*5c51f124SMoriah Waterland 	static	boolean_t	_zonesImplementedDetermined = B_FALSE;
2410*5c51f124SMoriah Waterland 	static	boolean_t	_zonesAreImplemented = B_FALSE;
2411*5c51f124SMoriah Waterland 
2412*5c51f124SMoriah Waterland 	/* if availability has not been determined, cache it now */
2413*5c51f124SMoriah Waterland 
2414*5c51f124SMoriah Waterland 	if (!_zonesImplementedDetermined) {
2415*5c51f124SMoriah Waterland 		_zonesImplementedDetermined = B_TRUE;
2416*5c51f124SMoriah Waterland 		_zonesAreImplemented = _z_zones_are_implemented();
2417*5c51f124SMoriah Waterland 		if (!_zonesAreImplemented) {
2418*5c51f124SMoriah Waterland 			_z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED);
2419*5c51f124SMoriah Waterland 		} else {
2420*5c51f124SMoriah Waterland 			_z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED);
2421*5c51f124SMoriah Waterland 		}
2422*5c51f124SMoriah Waterland 	}
2423*5c51f124SMoriah Waterland 
2424*5c51f124SMoriah Waterland 	return (_zonesAreImplemented);
2425*5c51f124SMoriah Waterland }
2426