xref: /titanic_53/usr/src/cmd/svr4pkg/pkgcond/main.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
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  * Program:	pkgcond
30*5c51f124SMoriah Waterland  *
31*5c51f124SMoriah Waterland  * Function:	Implements the package command suite public utility pkgcond(1M)
32*5c51f124SMoriah Waterland  *
33*5c51f124SMoriah Waterland  * Usage:	pkgcond [-nv] [-O debug] condition [ argument ]
34*5c51f124SMoriah Waterland  *
35*5c51f124SMoriah Waterland  *		command options:
36*5c51f124SMoriah Waterland  *			-n - negate results of condition test
37*5c51f124SMoriah Waterland  *			-v - verbose output of condition testing
38*5c51f124SMoriah Waterland  *
39*5c51f124SMoriah Waterland  *		<condition> may be any one of:
40*5c51f124SMoriah Waterland  *			can_add_driver [path]
41*5c51f124SMoriah Waterland  *			can_remove_driver [path]
42*5c51f124SMoriah Waterland  *			can_update_driver [path]
43*5c51f124SMoriah Waterland  *			is_alternative_root [path]
44*5c51f124SMoriah Waterland  *			is_boot_environment [path]
45*5c51f124SMoriah Waterland  *			is_diskless_client [path]
46*5c51f124SMoriah Waterland  *			is_global_zone [path]
47*5c51f124SMoriah Waterland  *			is_mounted_miniroot [path]
48*5c51f124SMoriah Waterland  *			is_netinstall_image [path]
49*5c51f124SMoriah Waterland  *			is_nonglobal_zone [path]
50*5c51f124SMoriah Waterland  *			is_path_writable path
51*5c51f124SMoriah Waterland  *			is_running_system [path]
52*5c51f124SMoriah Waterland  *			is_sparse_root_nonglobal_zone [path]
53*5c51f124SMoriah Waterland  *			is_what [path]
54*5c51f124SMoriah Waterland  *			is_whole_root_nonglobal_zone [path]
55*5c51f124SMoriah Waterland  *
56*5c51f124SMoriah Waterland  *		<option(s)> are specific to the condition used
57*5c51f124SMoriah Waterland  *
58*5c51f124SMoriah Waterland  * Input:	depends on command
59*5c51f124SMoriah Waterland  *
60*5c51f124SMoriah Waterland  * Output:	depends on command
61*5c51f124SMoriah Waterland  *
62*5c51f124SMoriah Waterland  * Exit status:	If the -n option is not specified:
63*5c51f124SMoriah Waterland  *		== 0 - the specified condition is true (or exists).
64*5c51f124SMoriah Waterland  *		== 1 - the specified condition is false (or does not exist).
65*5c51f124SMoriah Waterland  *		== 2 - command line usage errors (including bad keywords)
66*5c51f124SMoriah Waterland  *		== 3 - command failed to perform the test due to a fatal error
67*5c51f124SMoriah Waterland  *
68*5c51f124SMoriah Waterland  *		If the -n option is specified:
69*5c51f124SMoriah Waterland  *		== 0 - the specified condition is false (or does not exist).
70*5c51f124SMoriah Waterland  *		== 1 - the specified condition is true (or exists).
71*5c51f124SMoriah Waterland  *		== 2 - command line usage errors (including bad keywords)
72*5c51f124SMoriah Waterland  *		== 3 - command failed to perform the test due to a fatal error
73*5c51f124SMoriah Waterland  */
74*5c51f124SMoriah Waterland 
75*5c51f124SMoriah Waterland #include <stdio.h>
76*5c51f124SMoriah Waterland #include <sys/mnttab.h>
77*5c51f124SMoriah Waterland #include <sys/mntent.h>
78*5c51f124SMoriah Waterland #include <stdarg.h>
79*5c51f124SMoriah Waterland #include <stdlib.h>
80*5c51f124SMoriah Waterland #include <string.h>
81*5c51f124SMoriah Waterland #include <strings.h>
82*5c51f124SMoriah Waterland #include <fcntl.h>
83*5c51f124SMoriah Waterland #include <ctype.h>
84*5c51f124SMoriah Waterland #include <sys/types.h>
85*5c51f124SMoriah Waterland #include <sys/stat.h>
86*5c51f124SMoriah Waterland #include <unistd.h>
87*5c51f124SMoriah Waterland #include <locale.h>
88*5c51f124SMoriah Waterland #include <errno.h>
89*5c51f124SMoriah Waterland #include <sys/param.h>
90*5c51f124SMoriah Waterland #include <assert.h>
91*5c51f124SMoriah Waterland 
92*5c51f124SMoriah Waterland #include <instzones_api.h>
93*5c51f124SMoriah Waterland #include <pkglib.h>
94*5c51f124SMoriah Waterland #include <install.h>
95*5c51f124SMoriah Waterland #include <libinst.h>
96*5c51f124SMoriah Waterland #include <libadm.h>
97*5c51f124SMoriah Waterland #include <messages.h>
98*5c51f124SMoriah Waterland #include "pkgcond.h"
99*5c51f124SMoriah Waterland #include "pkgcond_msgs.h"
100*5c51f124SMoriah Waterland 
101*5c51f124SMoriah Waterland /* Should be defined by cc -D */
102*5c51f124SMoriah Waterland 
103*5c51f124SMoriah Waterland #if	!defined(TEXT_DOMAIN)
104*5c51f124SMoriah Waterland #define	TEXT_DOMAIN "SYS_TEST"
105*5c51f124SMoriah Waterland #endif
106*5c51f124SMoriah Waterland 
107*5c51f124SMoriah Waterland /* commands to execute */
108*5c51f124SMoriah Waterland 
109*5c51f124SMoriah Waterland #define	LS_CMD		"/usr/bin/ls"
110*5c51f124SMoriah Waterland 
111*5c51f124SMoriah Waterland /*
112*5c51f124SMoriah Waterland  * type definition and "types" for testPath()
113*5c51f124SMoriah Waterland  */
114*5c51f124SMoriah Waterland 
115*5c51f124SMoriah Waterland typedef enum {
116*5c51f124SMoriah Waterland 	TEST_EXISTS = 0x01,
117*5c51f124SMoriah Waterland 	TEST_NOT_EXISTS = 0x02,
118*5c51f124SMoriah Waterland 	TEST_IS_DIRECTORY = 0x04,
119*5c51f124SMoriah Waterland 	TEST_IS_FILE = 0x08,
120*5c51f124SMoriah Waterland 	TEST_NOT_DIRECTORY = 0x10,
121*5c51f124SMoriah Waterland 	TEST_NOT_FILE = 0x20,
122*5c51f124SMoriah Waterland 	TEST_IS_SYMBOLIC_LINK = 0x40,
123*5c51f124SMoriah Waterland 	TEST_NOT_SYMBOLIC_LINK = 0x80,
124*5c51f124SMoriah Waterland 	TEST_GLOBAL_TOKEN_IN_FILE = 0x100
125*5c51f124SMoriah Waterland } TEST_TYPES;
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland /* holds file system info */
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland struct fsi_t {
130*5c51f124SMoriah Waterland 	char	*fsi_mntOptions;
131*5c51f124SMoriah Waterland 	char	*fsi_fsType;
132*5c51f124SMoriah Waterland 	char	*fsi_mntPoint;
133*5c51f124SMoriah Waterland };
134*5c51f124SMoriah Waterland typedef struct fsi_t	FSI_T;
135*5c51f124SMoriah Waterland 
136*5c51f124SMoriah Waterland /* holds parsed global data */
137*5c51f124SMoriah Waterland 
138*5c51f124SMoriah Waterland struct globalData_t {
139*5c51f124SMoriah Waterland 		/* sparse root (are any file systems mounted read-only)? */
140*5c51f124SMoriah Waterland 	boolean_t gd_srFsMountedRO;
141*5c51f124SMoriah Waterland 		/* initial install: PKG_INIT_INSTALL=true */
142*5c51f124SMoriah Waterland 	boolean_t gd_initialInstall;
143*5c51f124SMoriah Waterland 		/* global zone install: SUNW_PKG_INSTALL_ZONENAME=global */
144*5c51f124SMoriah Waterland 	boolean_t gd_globalZoneInstall;
145*5c51f124SMoriah Waterland 		/* non-global zone install: SUNW_PKG_INSTALL_ZONENAME!=global */
146*5c51f124SMoriah Waterland 	boolean_t gd_nonglobalZoneInstall;
147*5c51f124SMoriah Waterland 		/* non-global zone is in a mounted state */
148*5c51f124SMoriah Waterland 	boolean_t inMountedState;
149*5c51f124SMoriah Waterland 		/* sorted list of all mounted file systems */
150*5c51f124SMoriah Waterland 	FSI_T	*gd_fileSystemConfig;
151*5c51f124SMoriah Waterland 		/* number of mounted file systems in list */
152*5c51f124SMoriah Waterland 	long	gd_fileSystemConfigLen;
153*5c51f124SMoriah Waterland 		/* current zone name */
154*5c51f124SMoriah Waterland 	char	*gd_zoneName;
155*5c51f124SMoriah Waterland 		/* version of target: PATCH_CLIENT_VERSION */
156*5c51f124SMoriah Waterland 	char	*gd_patchClientVersion;
157*5c51f124SMoriah Waterland 		/* SUNW_PKGCOND_GLOBAL_DATA:parentZone:zoneName */
158*5c51f124SMoriah Waterland 	char	*gd_parentZoneName;
159*5c51f124SMoriah Waterland 		/* SUNW_PKGCOND_GLOBAL_DATA:parentZone:zoneType */
160*5c51f124SMoriah Waterland 	char	*gd_parentZoneType;
161*5c51f124SMoriah Waterland 		/* root path to target: PKG_INSTALL_ROOT */
162*5c51f124SMoriah Waterland 	char	*gd_installRoot;
163*5c51f124SMoriah Waterland 		/* SUNW_PKGCOND_GLOBAL_DATA:currentZone:zoneName */
164*5c51f124SMoriah Waterland 	char	*gd_currentZoneName;
165*5c51f124SMoriah Waterland 		/* SUNW_PKGCOND_GLOBAL_DATA:currentZone:zoneType */
166*5c51f124SMoriah Waterland 	char	*gd_currentZoneType;
167*5c51f124SMoriah Waterland 		/* list of inherited file systems */
168*5c51f124SMoriah Waterland 	char	**gd_inheritedFileSystems;
169*5c51f124SMoriah Waterland 		/* path provided on command line */
170*5c51f124SMoriah Waterland 	char	*gd_cmdline_path;
171*5c51f124SMoriah Waterland };
172*5c51f124SMoriah Waterland typedef struct globalData_t	GLOBALDATA_T;
173*5c51f124SMoriah Waterland 
174*5c51f124SMoriah Waterland /* holds subcommands and their definitions */
175*5c51f124SMoriah Waterland 
176*5c51f124SMoriah Waterland struct cmd_t {
177*5c51f124SMoriah Waterland 	char		*c_name;
178*5c51f124SMoriah Waterland 	char		*c_args;
179*5c51f124SMoriah Waterland 	int		(*c_func)(int argc, char **argv, GLOBALDATA_T *a_gdt);
180*5c51f124SMoriah Waterland };
181*5c51f124SMoriah Waterland typedef struct cmd_t	CMD_T;
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland /* Command function prototypes */
184*5c51f124SMoriah Waterland 
185*5c51f124SMoriah Waterland static int		cmd_can_add_driver(int argc, char **argv,
186*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
187*5c51f124SMoriah Waterland static int		cmd_can_remove_driver(int argc, char **argv,
188*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
189*5c51f124SMoriah Waterland static int		cmd_can_update_driver(int argc, char **argv,
190*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
191*5c51f124SMoriah Waterland static int		cmd_is_alternative_root(int argc, char **argv,
192*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
193*5c51f124SMoriah Waterland static int		cmd_is_boot_environment(int argc, char **argv,
194*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
195*5c51f124SMoriah Waterland static int		cmd_is_diskless_client(int argc, char **argv,
196*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
197*5c51f124SMoriah Waterland static int		cmd_is_global_zone(int argc, char **argv,
198*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
199*5c51f124SMoriah Waterland static int		cmd_is_mounted_miniroot(int argc, char **argv,
200*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
201*5c51f124SMoriah Waterland static int		cmd_is_netinstall_image(int argc, char **argv,
202*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
203*5c51f124SMoriah Waterland static int		cmd_is_nonglobal_zone(int argc, char **argv,
204*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
205*5c51f124SMoriah Waterland static int		cmd_is_path_writable(int argc, char **argv,
206*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
207*5c51f124SMoriah Waterland static int		cmd_is_running_system(int argc, char **argv,
208*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
209*5c51f124SMoriah Waterland static int		cmd_is_sparse_root_ng_zone(int argc, char **argv,
210*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
211*5c51f124SMoriah Waterland static int		cmd_is_what(int argc, char **argv,
212*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
213*5c51f124SMoriah Waterland static int		cmd_is_whole_root_ng_zone(int argc, char **argv,
214*5c51f124SMoriah Waterland 				GLOBALDATA_T *a_gdt);
215*5c51f124SMoriah Waterland 
216*5c51f124SMoriah Waterland /* Utility function Prototypes */
217*5c51f124SMoriah Waterland 
218*5c51f124SMoriah Waterland static boolean_t	getNegateResults(void);
219*5c51f124SMoriah Waterland static boolean_t	recursionCheck(int *r_recursion, char *a_function);
220*5c51f124SMoriah Waterland static boolean_t	checkForReadOnlyMount(GLOBALDATA_T *a_gdt,
221*5c51f124SMoriah Waterland     char *a_mntPoint, char *a_fsType, char *a_mntOptions);
222*5c51f124SMoriah Waterland static int		adjustResults(int a_result);
223*5c51f124SMoriah Waterland static int		calculateFileSystemConfig(GLOBALDATA_T *a_gdt);
224*5c51f124SMoriah Waterland static int		getRootPath(char **r_rootPath);
225*5c51f124SMoriah Waterland static int		getZoneName(char **r_zoneName);
226*5c51f124SMoriah Waterland static int		mountOptionPresent(char *a_mntOptions, char *a_opt);
227*5c51f124SMoriah Waterland static int		parseGlobalData(char *a_envVar, GLOBALDATA_T **a_gdt);
228*5c51f124SMoriah Waterland static int		resolvePath(char **r_path);
229*5c51f124SMoriah Waterland static int		setRootPath(char *a_path, char *a_envVar,
230*5c51f124SMoriah Waterland     boolean_t a_mustExist);
231*5c51f124SMoriah Waterland static int		testPath(TEST_TYPES a_tt, char *format, ...);
232*5c51f124SMoriah Waterland static int		usage(char *a_format, ...);
233*5c51f124SMoriah Waterland static int		findToken(char *path, char *token);
234*5c51f124SMoriah Waterland static char		*getMountOption(char **p);
235*5c51f124SMoriah Waterland static void		dumpGlobalData(GLOBALDATA_T *a_gdt);
236*5c51f124SMoriah Waterland static void		removeLeadingWhitespace(char **a_str);
237*5c51f124SMoriah Waterland static void		setNegateResults(boolean_t setting);
238*5c51f124SMoriah Waterland static void		setVerbose(boolean_t);
239*5c51f124SMoriah Waterland static void		sortedInsert(FSI_T **r_list, long *a_listSize,
240*5c51f124SMoriah Waterland     char *a_mntPoint, char *a_fsType, char *a_mntOptions);
241*5c51f124SMoriah Waterland static void		setCmdLinePath(char **a_path, char **args,
242*5c51f124SMoriah Waterland     int num_args);
243*5c51f124SMoriah Waterland 
244*5c51f124SMoriah Waterland /* local static data */
245*5c51f124SMoriah Waterland 
246*5c51f124SMoriah Waterland static boolean_t	_negateResults = B_FALSE;
247*5c51f124SMoriah Waterland static char		*_rootPath = "/";
248*5c51f124SMoriah Waterland 
249*5c51f124SMoriah Waterland /* define subcommand data structure */
250*5c51f124SMoriah Waterland 
251*5c51f124SMoriah Waterland static CMD_T cmds[] = {
252*5c51f124SMoriah Waterland 	{ "can_add_driver",		" [path]",
253*5c51f124SMoriah Waterland 		cmd_can_add_driver },
254*5c51f124SMoriah Waterland 	{ "can_remove_driver",		" [path]",
255*5c51f124SMoriah Waterland 		cmd_can_remove_driver },
256*5c51f124SMoriah Waterland 	{ "can_update_driver",		" [path]",
257*5c51f124SMoriah Waterland 		cmd_can_update_driver },
258*5c51f124SMoriah Waterland 	{ "is_alternative_root",	" [path]",
259*5c51f124SMoriah Waterland 		cmd_is_alternative_root },
260*5c51f124SMoriah Waterland 	{ "is_boot_environment",	" [path]",
261*5c51f124SMoriah Waterland 		cmd_is_boot_environment },
262*5c51f124SMoriah Waterland 	{ "is_diskless_client",		" [path]",
263*5c51f124SMoriah Waterland 		cmd_is_diskless_client },
264*5c51f124SMoriah Waterland 	{ "is_global_zone",		" [path]",
265*5c51f124SMoriah Waterland 		cmd_is_global_zone },
266*5c51f124SMoriah Waterland 	{ "is_mounted_miniroot",	" [path]",
267*5c51f124SMoriah Waterland 		cmd_is_mounted_miniroot },
268*5c51f124SMoriah Waterland 	{ "is_netinstall_image",	" [path]",
269*5c51f124SMoriah Waterland 		cmd_is_netinstall_image },
270*5c51f124SMoriah Waterland 	{ "is_nonglobal_zone",		" [path]",
271*5c51f124SMoriah Waterland 		cmd_is_nonglobal_zone },
272*5c51f124SMoriah Waterland 	{ "is_path_writable",		" path",
273*5c51f124SMoriah Waterland 		cmd_is_path_writable },
274*5c51f124SMoriah Waterland 	{ "is_running_system",		" [path]",
275*5c51f124SMoriah Waterland 		cmd_is_running_system },
276*5c51f124SMoriah Waterland 	{ "is_sparse_root_nonglobal_zone", " [path]",
277*5c51f124SMoriah Waterland 		cmd_is_sparse_root_ng_zone },
278*5c51f124SMoriah Waterland 	{ "is_what", " [path]",
279*5c51f124SMoriah Waterland 		cmd_is_what },
280*5c51f124SMoriah Waterland 	{ "is_whole_root_nonglobal_zone", " [path]",
281*5c51f124SMoriah Waterland 		cmd_is_whole_root_ng_zone },
282*5c51f124SMoriah Waterland 	/* last one must be all NULLs */
283*5c51f124SMoriah Waterland 	{ NULL, NULL }
284*5c51f124SMoriah Waterland };
285*5c51f124SMoriah Waterland 
286*5c51f124SMoriah Waterland /*
287*5c51f124SMoriah Waterland  * *****************************************************************************
288*5c51f124SMoriah Waterland  * main
289*5c51f124SMoriah Waterland  * *****************************************************************************
290*5c51f124SMoriah Waterland  */
291*5c51f124SMoriah Waterland 
292*5c51f124SMoriah Waterland /*
293*5c51f124SMoriah Waterland  * Name:	main
294*5c51f124SMoriah Waterland  * Description:	main processing loop for pkgcond *
295*5c51f124SMoriah Waterland  * Return:	0 - condition is satisfied (true)
296*5c51f124SMoriah Waterland  *		1 - condition is not satisfied (false)
297*5c51f124SMoriah Waterland  *		2 - command line usage errors
298*5c51f124SMoriah Waterland  *		3 - failure to determine condition
299*5c51f124SMoriah Waterland  */
300*5c51f124SMoriah Waterland 
301*5c51f124SMoriah Waterland int
302*5c51f124SMoriah Waterland main(int argc, char **argv)
303*5c51f124SMoriah Waterland {
304*5c51f124SMoriah Waterland 	GLOBALDATA_T	*gdt = NULL;
305*5c51f124SMoriah Waterland 	char		**newargv;
306*5c51f124SMoriah Waterland 	char		*p;
307*5c51f124SMoriah Waterland 	int		cur_cmd;
308*5c51f124SMoriah Waterland 	int		i;
309*5c51f124SMoriah Waterland 	int		newargc;
310*5c51f124SMoriah Waterland 
311*5c51f124SMoriah Waterland 	/* make standard output non-buffered */
312*5c51f124SMoriah Waterland 
313*5c51f124SMoriah Waterland 	setbuf(stdout, NULL);
314*5c51f124SMoriah Waterland 
315*5c51f124SMoriah Waterland 	/* set the default text domain for messaging */
316*5c51f124SMoriah Waterland 
317*5c51f124SMoriah Waterland 	(void) setlocale(LC_ALL, "");
318*5c51f124SMoriah Waterland 	(void) textdomain(TEXT_DOMAIN);
319*5c51f124SMoriah Waterland 
320*5c51f124SMoriah Waterland 	/* remember command name */
321*5c51f124SMoriah Waterland 
322*5c51f124SMoriah Waterland 	set_prog_name(argv[0]);
323*5c51f124SMoriah Waterland 
324*5c51f124SMoriah Waterland 	/* tell spmi zones interface how to access package output functions */
325*5c51f124SMoriah Waterland 
326*5c51f124SMoriah Waterland 	z_set_output_functions(echo, echoDebug, progerr);
327*5c51f124SMoriah Waterland 
328*5c51f124SMoriah Waterland 	/* set verbose mode if appropriate environment variable is set */
329*5c51f124SMoriah Waterland 
330*5c51f124SMoriah Waterland 	if (getenv(ENV_VAR_VERBOSE)) {
331*5c51f124SMoriah Waterland 		/* same as -v */
332*5c51f124SMoriah Waterland 		setVerbose(B_TRUE);
333*5c51f124SMoriah Waterland 	}
334*5c51f124SMoriah Waterland 
335*5c51f124SMoriah Waterland 	/* set debug mode if appropriate environment variable is set */
336*5c51f124SMoriah Waterland 
337*5c51f124SMoriah Waterland 	if (getenv(ENV_VAR_DEBUG)) {
338*5c51f124SMoriah Waterland 		/* same as -O debug */
339*5c51f124SMoriah Waterland 
340*5c51f124SMoriah Waterland 		/* set sml tracing (sml.c) */
341*5c51f124SMoriah Waterland 		smlSetVerbose(B_TRUE);
342*5c51f124SMoriah Waterland 
343*5c51f124SMoriah Waterland 		/* set log and echo (interactive) message tracing */
344*5c51f124SMoriah Waterland 		setVerbose(B_TRUE);
345*5c51f124SMoriah Waterland 
346*5c51f124SMoriah Waterland 		/* enable echoDebug debugging messages */
347*5c51f124SMoriah Waterland 		echoDebugSetFlag(B_TRUE);
348*5c51f124SMoriah Waterland 	}
349*5c51f124SMoriah Waterland 
350*5c51f124SMoriah Waterland 	/* generate usage if no options or arguments specified */
351*5c51f124SMoriah Waterland 
352*5c51f124SMoriah Waterland 	if (argc <= 1) {
353*5c51f124SMoriah Waterland 		(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
354*5c51f124SMoriah Waterland 		return (R_USAGE);
355*5c51f124SMoriah Waterland 	}
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 	/*
358*5c51f124SMoriah Waterland 	 * process any arguments that can appear before the subcommand
359*5c51f124SMoriah Waterland 	 */
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland 	while ((i = getopt(argc, argv, ":O:vn?")) != EOF) {
362*5c51f124SMoriah Waterland 		switch (i) {
363*5c51f124SMoriah Waterland 		/*
364*5c51f124SMoriah Waterland 		 * Not a public interface: the -O option allows the behavior
365*5c51f124SMoriah Waterland 		 * of the package tools to be modified. Recognized options:
366*5c51f124SMoriah Waterland 		 * -> debug
367*5c51f124SMoriah Waterland 		 * ---> enable debugging output
368*5c51f124SMoriah Waterland 		 */
369*5c51f124SMoriah Waterland 
370*5c51f124SMoriah Waterland 		case 'O':
371*5c51f124SMoriah Waterland 			for (p = strtok(optarg, ","); p != NULL;
372*5c51f124SMoriah Waterland 				p = strtok(NULL, ",")) {
373*5c51f124SMoriah Waterland 
374*5c51f124SMoriah Waterland 				/* debug - enable all tracing */
375*5c51f124SMoriah Waterland 
376*5c51f124SMoriah Waterland 				if (strcmp(p, "debug") == 0) {
377*5c51f124SMoriah Waterland 					/* set sml tracing */
378*5c51f124SMoriah Waterland 					smlSetVerbose(B_TRUE);
379*5c51f124SMoriah Waterland 					/* set log/echo tracing */
380*5c51f124SMoriah Waterland 					setVerbose(B_TRUE);
381*5c51f124SMoriah Waterland 					/* enable debugging messages */
382*5c51f124SMoriah Waterland 					echoDebugSetFlag(B_TRUE);
383*5c51f124SMoriah Waterland 					continue;
384*5c51f124SMoriah Waterland 				}
385*5c51f124SMoriah Waterland 
386*5c51f124SMoriah Waterland 				progerr(ERR_INVALID_O_OPTION, p);
387*5c51f124SMoriah Waterland 				return (adjustResults(R_USAGE));
388*5c51f124SMoriah Waterland 			}
389*5c51f124SMoriah Waterland 			break;
390*5c51f124SMoriah Waterland 
391*5c51f124SMoriah Waterland 		/*
392*5c51f124SMoriah Waterland 		 * Public interface: enable verbose (debug) output.
393*5c51f124SMoriah Waterland 		 */
394*5c51f124SMoriah Waterland 
395*5c51f124SMoriah Waterland 		case 'v':	/* verbose mode enabled */
396*5c51f124SMoriah Waterland 			/* set command tracing only */
397*5c51f124SMoriah Waterland 			setVerbose(B_TRUE);
398*5c51f124SMoriah Waterland 			break;
399*5c51f124SMoriah Waterland 
400*5c51f124SMoriah Waterland 		/*
401*5c51f124SMoriah Waterland 		 * Public interface: negate output results.
402*5c51f124SMoriah Waterland 		 */
403*5c51f124SMoriah Waterland 
404*5c51f124SMoriah Waterland 		case 'n':
405*5c51f124SMoriah Waterland 			setNegateResults(B_TRUE);
406*5c51f124SMoriah Waterland 			break;
407*5c51f124SMoriah Waterland 
408*5c51f124SMoriah Waterland 		/*
409*5c51f124SMoriah Waterland 		 * unrecognized option
410*5c51f124SMoriah Waterland 		 */
411*5c51f124SMoriah Waterland 
412*5c51f124SMoriah Waterland 		case '?':
413*5c51f124SMoriah Waterland 		default:
414*5c51f124SMoriah Waterland 			(void) usage(MSG_INVALID_OPTION_SPECIFIED, optopt);
415*5c51f124SMoriah Waterland 			return (R_USAGE);
416*5c51f124SMoriah Waterland 		}
417*5c51f124SMoriah Waterland 	}
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 	/*
420*5c51f124SMoriah Waterland 	 * done processing options that can preceed subcommand
421*5c51f124SMoriah Waterland 	 */
422*5c51f124SMoriah Waterland 
423*5c51f124SMoriah Waterland 	/* error if no subcommand specified */
424*5c51f124SMoriah Waterland 
425*5c51f124SMoriah Waterland 	if ((argc-optind) <= 0) {
426*5c51f124SMoriah Waterland 		(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
427*5c51f124SMoriah Waterland 		return (R_USAGE);
428*5c51f124SMoriah Waterland 	}
429*5c51f124SMoriah Waterland 
430*5c51f124SMoriah Waterland 	/* parse global data if environment variable set */
431*5c51f124SMoriah Waterland 
432*5c51f124SMoriah Waterland 	if (parseGlobalData(PKGCOND_GLOBAL_VARIABLE, &gdt) != R_SUCCESS) {
433*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_CANNOT_USE_GLOBAL_DATA,
434*5c51f124SMoriah Waterland 			PKGCOND_GLOBAL_VARIABLE);
435*5c51f124SMoriah Waterland 		return (R_ERROR);
436*5c51f124SMoriah Waterland 	}
437*5c51f124SMoriah Waterland 
438*5c51f124SMoriah Waterland 	if (setRootPath(gdt->gd_installRoot,
439*5c51f124SMoriah Waterland 	    (strcmp(gdt->gd_installRoot, "/") == 0) ? NULL :
440*5c51f124SMoriah Waterland 	    ENV_VAR_SET, B_TRUE) != R_SUCCESS) {
441*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_CANNOT_SET_ROOT_PATH,
442*5c51f124SMoriah Waterland 			ENV_VAR_PKGROOT);
443*5c51f124SMoriah Waterland 		return (R_ERROR);
444*5c51f124SMoriah Waterland 	}
445*5c51f124SMoriah Waterland 
446*5c51f124SMoriah Waterland 	/* set path provided on the command line */
447*5c51f124SMoriah Waterland 
448*5c51f124SMoriah Waterland 	setCmdLinePath(&(gdt->gd_cmdline_path), argv, argc);
449*5c51f124SMoriah Waterland 	echoDebug(DBG_CMDLINE_PATH,
450*5c51f124SMoriah Waterland 	    gdt->gd_cmdline_path == NULL ? "" : gdt->gd_cmdline_path);
451*5c51f124SMoriah Waterland 
452*5c51f124SMoriah Waterland 	/* determine how file systems are layered in this zone */
453*5c51f124SMoriah Waterland 
454*5c51f124SMoriah Waterland 	if (calculateFileSystemConfig(gdt) != R_SUCCESS) {
455*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_CANNOT_CALC_FS_CONFIG);
456*5c51f124SMoriah Waterland 		return (R_ERROR);
457*5c51f124SMoriah Waterland 	}
458*5c51f124SMoriah Waterland 
459*5c51f124SMoriah Waterland 	/* dump global data read in (only if debugging) */
460*5c51f124SMoriah Waterland 
461*5c51f124SMoriah Waterland 	dumpGlobalData(gdt);
462*5c51f124SMoriah Waterland 
463*5c51f124SMoriah Waterland 	/* search for specified subcommand and execute if found */
464*5c51f124SMoriah Waterland 
465*5c51f124SMoriah Waterland 	for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
466*5c51f124SMoriah Waterland 		if (ci_streq(argv[optind], cmds[cur_cmd].c_name)) {
467*5c51f124SMoriah Waterland 			int	result;
468*5c51f124SMoriah Waterland 
469*5c51f124SMoriah Waterland 			/* make subcommand the first option */
470*5c51f124SMoriah Waterland 
471*5c51f124SMoriah Waterland 			newargc = argc - optind;
472*5c51f124SMoriah Waterland 			newargv = argv + optind;
473*5c51f124SMoriah Waterland 			opterr = optind = 1; optopt = 0;
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland 
476*5c51f124SMoriah Waterland 			/* call subcommand with its own argc/argv */
477*5c51f124SMoriah Waterland 
478*5c51f124SMoriah Waterland 			result = cmds[cur_cmd].c_func(newargc, newargv, gdt);
479*5c51f124SMoriah Waterland 
480*5c51f124SMoriah Waterland 			/* process result code and exit */
481*5c51f124SMoriah Waterland 
482*5c51f124SMoriah Waterland 			result = adjustResults(result);
483*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_RESULTS, result);
484*5c51f124SMoriah Waterland 			return (result);
485*5c51f124SMoriah Waterland 		}
486*5c51f124SMoriah Waterland 	}
487*5c51f124SMoriah Waterland 
488*5c51f124SMoriah Waterland 	/* subcommand not found - output error message and exit with error */
489*5c51f124SMoriah Waterland 
490*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_ERR, ERR_BAD_SUB, argv[optind]);
491*5c51f124SMoriah Waterland 	(void) usage(MSG_UNRECOGNIZED_CONDITION_SPECIFIED);
492*5c51f124SMoriah Waterland 	return (R_USAGE);
493*5c51f124SMoriah Waterland }
494*5c51f124SMoriah Waterland 
495*5c51f124SMoriah Waterland /*
496*5c51f124SMoriah Waterland  * *****************************************************************************
497*5c51f124SMoriah Waterland  * command implementation functions
498*5c51f124SMoriah Waterland  * *****************************************************************************
499*5c51f124SMoriah Waterland  */
500*5c51f124SMoriah Waterland 
501*5c51f124SMoriah Waterland /*
502*5c51f124SMoriah Waterland  * Name:	cmd_is_diskless_client
503*5c51f124SMoriah Waterland  * Description:	determine if target is a diskless client
504*5c51f124SMoriah Waterland  * Scope:	public
505*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
506*5c51f124SMoriah Waterland  *		  - optional path to target to test
507*5c51f124SMoriah Waterland  * Returns:	int
508*5c51f124SMoriah Waterland  *			== 0 - success
509*5c51f124SMoriah Waterland  *			!= 0 - failure
510*5c51f124SMoriah Waterland  * IMPLEMENTATION:
511*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
512*5c51f124SMoriah Waterland  *  - must not be installation of a zone
513*5c51f124SMoriah Waterland  *  - must not be a whole root non-global zone
514*5c51f124SMoriah Waterland  *  - must not be a non-global zone
515*5c51f124SMoriah Waterland  *  - must not be a mounted mini-root
516*5c51f124SMoriah Waterland  *  - must not be a netinstall image
517*5c51f124SMoriah Waterland  *  - must not be a boot environment
518*5c51f124SMoriah Waterland  *  - The package "SUNWdclnt" must be installed at "/"
519*5c51f124SMoriah Waterland  *  - The root path must not be "/"
520*5c51f124SMoriah Waterland  *  - The path "/export/exec/Solaris_\*\/usr" must exist at "/"
521*5c51f124SMoriah Waterland  *  - The directory "$ROOTDIR/../templates" must exist
522*5c51f124SMoriah Waterland  */
523*5c51f124SMoriah Waterland 
524*5c51f124SMoriah Waterland static int
525*5c51f124SMoriah Waterland cmd_is_diskless_client(int argc, char **argv, GLOBALDATA_T *a_gdt)
526*5c51f124SMoriah Waterland {
527*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
528*5c51f124SMoriah Waterland 	char	cmd[MAXPATHLEN+1];
529*5c51f124SMoriah Waterland 	int	c;
530*5c51f124SMoriah Waterland 	int	r;
531*5c51f124SMoriah Waterland 	int	rc;
532*5c51f124SMoriah Waterland static	char	*cmdName = "is_diskless_client";
533*5c51f124SMoriah Waterland static	int	recursion = 0;
534*5c51f124SMoriah Waterland 
535*5c51f124SMoriah Waterland 	/* process any command line options */
536*5c51f124SMoriah Waterland 
537*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
538*5c51f124SMoriah Waterland 		switch (c) {
539*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
540*5c51f124SMoriah Waterland 			break;
541*5c51f124SMoriah Waterland 		case '?':
542*5c51f124SMoriah Waterland 		default:
543*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
544*5c51f124SMoriah Waterland 			return (R_USAGE);
545*5c51f124SMoriah Waterland 		}
546*5c51f124SMoriah Waterland 	}
547*5c51f124SMoriah Waterland 
548*5c51f124SMoriah Waterland 	/* prevent recursion */
549*5c51f124SMoriah Waterland 
550*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
551*5c51f124SMoriah Waterland 
552*5c51f124SMoriah Waterland 		/*
553*5c51f124SMoriah Waterland 		 * a diskless client cannot be any of the following
554*5c51f124SMoriah Waterland 		 */
555*5c51f124SMoriah Waterland 
556*5c51f124SMoriah Waterland 		/* cannot be whole root non-global zone */
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 		r = cmd_is_whole_root_ng_zone(argc, argv, a_gdt);
559*5c51f124SMoriah Waterland 
560*5c51f124SMoriah Waterland 		/* cannot be nonglobal zone */
561*5c51f124SMoriah Waterland 
562*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
563*5c51f124SMoriah Waterland 			r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
564*5c51f124SMoriah Waterland 		}
565*5c51f124SMoriah Waterland 
566*5c51f124SMoriah Waterland 		/* cannot be mounted miniroot */
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
569*5c51f124SMoriah Waterland 			r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
570*5c51f124SMoriah Waterland 		}
571*5c51f124SMoriah Waterland 
572*5c51f124SMoriah Waterland 		/* cannot be a netinstall image */
573*5c51f124SMoriah Waterland 
574*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
575*5c51f124SMoriah Waterland 			r = cmd_is_netinstall_image(argc, argv, a_gdt);
576*5c51f124SMoriah Waterland 		}
577*5c51f124SMoriah Waterland 
578*5c51f124SMoriah Waterland 		/* cannot be a boot environment */
579*5c51f124SMoriah Waterland 
580*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
581*5c51f124SMoriah Waterland 			r = cmd_is_boot_environment(argc, argv, a_gdt);
582*5c51f124SMoriah Waterland 		}
583*5c51f124SMoriah Waterland 
584*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
585*5c51f124SMoriah Waterland 
586*5c51f124SMoriah Waterland 		recursion--;
587*5c51f124SMoriah Waterland 
588*5c51f124SMoriah Waterland 		/* return failure if any of the preceeding are true */
589*5c51f124SMoriah Waterland 
590*5c51f124SMoriah Waterland 		switch (r) {
591*5c51f124SMoriah Waterland 			case R_SUCCESS:
592*5c51f124SMoriah Waterland 				return (R_FAILURE);
593*5c51f124SMoriah Waterland 			case R_FAILURE:
594*5c51f124SMoriah Waterland 				break;
595*5c51f124SMoriah Waterland 			case R_USAGE:
596*5c51f124SMoriah Waterland 			case R_ERROR:
597*5c51f124SMoriah Waterland 			default:
598*5c51f124SMoriah Waterland 				return (r);
599*5c51f124SMoriah Waterland 		}
600*5c51f124SMoriah Waterland 	}
601*5c51f124SMoriah Waterland 
602*5c51f124SMoriah Waterland 	/* normalize argc/argv */
603*5c51f124SMoriah Waterland 
604*5c51f124SMoriah Waterland 	argc -= optind;
605*5c51f124SMoriah Waterland 	argv += optind;
606*5c51f124SMoriah Waterland 
607*5c51f124SMoriah Waterland 	/* error if more than one argument */
608*5c51f124SMoriah Waterland 
609*5c51f124SMoriah Waterland 	if (argc > 1) {
610*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
611*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
612*5c51f124SMoriah Waterland 		return (R_USAGE);
613*5c51f124SMoriah Waterland 	}
614*5c51f124SMoriah Waterland 
615*5c51f124SMoriah Waterland 	/* process root path if first argument present */
616*5c51f124SMoriah Waterland 
617*5c51f124SMoriah Waterland 	if (argc == 1) {
618*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
619*5c51f124SMoriah Waterland 			return (R_ERROR);
620*5c51f124SMoriah Waterland 		}
621*5c51f124SMoriah Waterland 	}
622*5c51f124SMoriah Waterland 
623*5c51f124SMoriah Waterland 	/* get current root path */
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
626*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
627*5c51f124SMoriah Waterland 		return (r);
628*5c51f124SMoriah Waterland 	}
629*5c51f124SMoriah Waterland 
630*5c51f124SMoriah Waterland 	/* start of command debugging information */
631*5c51f124SMoriah Waterland 
632*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
633*5c51f124SMoriah Waterland 
634*5c51f124SMoriah Waterland 	/* SUNWdclnt must be installed */
635*5c51f124SMoriah Waterland 
636*5c51f124SMoriah Waterland 	if (pkgTestInstalled("SUNWdclnt", "/") != B_TRUE) {
637*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_PKG_NOT_INSTALLED,
638*5c51f124SMoriah Waterland 			rootPath, "SUNWdclnt", "/");
639*5c51f124SMoriah Waterland 		return (R_FAILURE);
640*5c51f124SMoriah Waterland 	}
641*5c51f124SMoriah Waterland 
642*5c51f124SMoriah Waterland 	/*   - $ROOTDIR must not be "/" */
643*5c51f124SMoriah Waterland 
644*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") == 0) {
645*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_ROOTPATH_BAD, rootPath, "/");
646*5c51f124SMoriah Waterland 		return (R_FAILURE);
647*5c51f124SMoriah Waterland 	}
648*5c51f124SMoriah Waterland 
649*5c51f124SMoriah Waterland 	/*   - zone name must be global */
650*5c51f124SMoriah Waterland 
651*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
652*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_ZONE_BAD, rootPath,
653*5c51f124SMoriah Waterland 			GLOBAL_ZONENAME);
654*5c51f124SMoriah Waterland 		return (R_FAILURE);
655*5c51f124SMoriah Waterland 	}
656*5c51f124SMoriah Waterland 
657*5c51f124SMoriah Waterland 	/*
658*5c51f124SMoriah Waterland 	 * /export/exec/Solaris_"*"/usr must exist;
659*5c51f124SMoriah Waterland 	 * create ls command to test:
660*5c51f124SMoriah Waterland 	 * /usr/bin/ls /export/exec/Solaris_"*"/usr
661*5c51f124SMoriah Waterland 	 */
662*5c51f124SMoriah Waterland 
663*5c51f124SMoriah Waterland 	(void) snprintf(cmd, sizeof (cmd), "%s %s >/dev/null 2>&1",
664*5c51f124SMoriah Waterland 		LS_CMD, "/export/exec/Solaris_*/usr");
665*5c51f124SMoriah Waterland 
666*5c51f124SMoriah Waterland 	/* execute command */
667*5c51f124SMoriah Waterland 
668*5c51f124SMoriah Waterland 	rc = system(cmd);
669*5c51f124SMoriah Waterland 
670*5c51f124SMoriah Waterland 	/* return error if ls returns something other than "0" */
671*5c51f124SMoriah Waterland 
672*5c51f124SMoriah Waterland 	if (rc != 0) {
673*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_PATH_MISSING,
674*5c51f124SMoriah Waterland 			rootPath, "/export/exec/Solaris_*/usr");
675*5c51f124SMoriah Waterland 		return (R_FAILURE);
676*5c51f124SMoriah Waterland 	}
677*5c51f124SMoriah Waterland 
678*5c51f124SMoriah Waterland 	/*
679*5c51f124SMoriah Waterland 	 * /usr must be empty on a diskless client:
680*5c51f124SMoriah Waterland 	 * create ls command to test:
681*5c51f124SMoriah Waterland 	 * /usr/bin/ls -d1 $ROOTDIR/usr/\*
682*5c51f124SMoriah Waterland 	 */
683*5c51f124SMoriah Waterland 	(void) snprintf(cmd, sizeof (cmd), "%s %s %s/%s >/dev/null 2>&1",
684*5c51f124SMoriah Waterland 		LS_CMD, "-1d", rootPath, "usr/*");
685*5c51f124SMoriah Waterland 
686*5c51f124SMoriah Waterland 	/* execute command */
687*5c51f124SMoriah Waterland 
688*5c51f124SMoriah Waterland 	rc = system(cmd);
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 	/* return error if ls returns "0" */
691*5c51f124SMoriah Waterland 
692*5c51f124SMoriah Waterland 	if (rc == 0) {
693*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_USR_IS_NOT_EMPTY,
694*5c51f124SMoriah Waterland 			rootPath);
695*5c51f124SMoriah Waterland 		return (R_FAILURE);
696*5c51f124SMoriah Waterland 	}
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland 	/* there must be a templates directory at ${ROOTPATH}/../templates */
699*5c51f124SMoriah Waterland 
700*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
701*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "../templates");
702*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
703*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_NO_TEMPLATES_PATH,
704*5c51f124SMoriah Waterland 			rootPath, rootPath, "../templates");
705*5c51f124SMoriah Waterland 		return (R_FAILURE);
706*5c51f124SMoriah Waterland 	}
707*5c51f124SMoriah Waterland 
708*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
709*5c51f124SMoriah Waterland 
710*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
711*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
712*5c51f124SMoriah Waterland 		/* initial install: install root cannot be diskless client */
713*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_INITIAL_INSTALL, rootPath);
714*5c51f124SMoriah Waterland 		return (R_FAILURE);
715*5c51f124SMoriah Waterland 	}
716*5c51f124SMoriah Waterland 
717*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
718*5c51f124SMoriah Waterland 
719*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
720*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
721*5c51f124SMoriah Waterland 		/* initial zone install: no path can be diskless client */
722*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IDLC_ZONE_INSTALL, rootPath);
723*5c51f124SMoriah Waterland 		return (R_FAILURE);
724*5c51f124SMoriah Waterland 	}
725*5c51f124SMoriah Waterland 
726*5c51f124SMoriah Waterland 	/* the path is a diskless client */
727*5c51f124SMoriah Waterland 
728*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_IDLC_PATH_IS_DISKLESS_CLIENT, rootPath);
729*5c51f124SMoriah Waterland 
730*5c51f124SMoriah Waterland 	return (R_SUCCESS);
731*5c51f124SMoriah Waterland }
732*5c51f124SMoriah Waterland 
733*5c51f124SMoriah Waterland /*
734*5c51f124SMoriah Waterland  * Name:	cmd_is_global_zone
735*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
736*5c51f124SMoriah Waterland  * Scope:	public
737*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
738*5c51f124SMoriah Waterland  *		  - optional path to target to test
739*5c51f124SMoriah Waterland  * Returns:	int
740*5c51f124SMoriah Waterland  *			== 0 - success
741*5c51f124SMoriah Waterland  *			!= 0 - failure
742*5c51f124SMoriah Waterland  * IMPLEMENTATION:
743*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
744*5c51f124SMoriah Waterland  *  - must not be installation of a non-global zone
745*5c51f124SMoriah Waterland  *  - must not be a non-global zone
746*5c51f124SMoriah Waterland  *  - must not be a mounted mini-root
747*5c51f124SMoriah Waterland  *  - must not be a netinstall image
748*5c51f124SMoriah Waterland  *  - must not be a diskless client
749*5c51f124SMoriah Waterland  *  - if $ROOTDIR is "/":
750*5c51f124SMoriah Waterland  *  -- if zone name is "GLOBAL", then is a global zone;
751*5c51f124SMoriah Waterland  *  -- else not a global zone.
752*5c51f124SMoriah Waterland  *  - $ROOTDIR/etc/zones must exist and be a directory
753*5c51f124SMoriah Waterland  *  - $ROOTDIR/.tmp_proto must not exist
754*5c51f124SMoriah Waterland  *  - $ROOTDIR/var must exist and must not be a symbolic link
755*5c51f124SMoriah Waterland  */
756*5c51f124SMoriah Waterland 
757*5c51f124SMoriah Waterland static int
758*5c51f124SMoriah Waterland cmd_is_global_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
759*5c51f124SMoriah Waterland {
760*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
761*5c51f124SMoriah Waterland 	int	c;
762*5c51f124SMoriah Waterland 	int	r;
763*5c51f124SMoriah Waterland static	char	*cmdName = "is_global_zone";
764*5c51f124SMoriah Waterland static	int	recursion = 0;
765*5c51f124SMoriah Waterland 
766*5c51f124SMoriah Waterland 	/* process any command line options */
767*5c51f124SMoriah Waterland 
768*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
769*5c51f124SMoriah Waterland 		switch (c) {
770*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
771*5c51f124SMoriah Waterland 			break;
772*5c51f124SMoriah Waterland 		case '?':
773*5c51f124SMoriah Waterland 		default:
774*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
775*5c51f124SMoriah Waterland 			return (R_USAGE);
776*5c51f124SMoriah Waterland 		}
777*5c51f124SMoriah Waterland 	}
778*5c51f124SMoriah Waterland 
779*5c51f124SMoriah Waterland 	/* prevent recursion */
780*5c51f124SMoriah Waterland 
781*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
782*5c51f124SMoriah Waterland 
783*5c51f124SMoriah Waterland 		/*
784*5c51f124SMoriah Waterland 		 * a global zone cannot be any of the following
785*5c51f124SMoriah Waterland 		 */
786*5c51f124SMoriah Waterland 
787*5c51f124SMoriah Waterland 		/* cannot be a non-global zone */
788*5c51f124SMoriah Waterland 
789*5c51f124SMoriah Waterland 		r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
790*5c51f124SMoriah Waterland 
791*5c51f124SMoriah Waterland 		/* cannot be a mounted miniroot */
792*5c51f124SMoriah Waterland 
793*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
794*5c51f124SMoriah Waterland 			r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
795*5c51f124SMoriah Waterland 		}
796*5c51f124SMoriah Waterland 
797*5c51f124SMoriah Waterland 		/* cannot be a netinstall image */
798*5c51f124SMoriah Waterland 
799*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
800*5c51f124SMoriah Waterland 			r = cmd_is_netinstall_image(argc, argv, a_gdt);
801*5c51f124SMoriah Waterland 		}
802*5c51f124SMoriah Waterland 
803*5c51f124SMoriah Waterland 		/* cannot be a diskless client */
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
806*5c51f124SMoriah Waterland 			r = cmd_is_diskless_client(argc, argv, a_gdt);
807*5c51f124SMoriah Waterland 		}
808*5c51f124SMoriah Waterland 
809*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
810*5c51f124SMoriah Waterland 
811*5c51f124SMoriah Waterland 		recursion--;
812*5c51f124SMoriah Waterland 
813*5c51f124SMoriah Waterland 		/* return failure if any of the preceeding are true */
814*5c51f124SMoriah Waterland 
815*5c51f124SMoriah Waterland 		switch (r) {
816*5c51f124SMoriah Waterland 			case R_SUCCESS:
817*5c51f124SMoriah Waterland 				return (R_FAILURE);
818*5c51f124SMoriah Waterland 			case R_FAILURE:
819*5c51f124SMoriah Waterland 				break;
820*5c51f124SMoriah Waterland 			case R_USAGE:
821*5c51f124SMoriah Waterland 			case R_ERROR:
822*5c51f124SMoriah Waterland 			default:
823*5c51f124SMoriah Waterland 				return (r);
824*5c51f124SMoriah Waterland 		}
825*5c51f124SMoriah Waterland 	}
826*5c51f124SMoriah Waterland 
827*5c51f124SMoriah Waterland 	/* normalize argc/argv */
828*5c51f124SMoriah Waterland 
829*5c51f124SMoriah Waterland 	argc -= optind;
830*5c51f124SMoriah Waterland 	argv += optind;
831*5c51f124SMoriah Waterland 
832*5c51f124SMoriah Waterland 	/* error if more than one argument */
833*5c51f124SMoriah Waterland 
834*5c51f124SMoriah Waterland 	if (argc > 1) {
835*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
836*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
837*5c51f124SMoriah Waterland 		return (R_USAGE);
838*5c51f124SMoriah Waterland 	}
839*5c51f124SMoriah Waterland 
840*5c51f124SMoriah Waterland 	/* process root path if first argument present */
841*5c51f124SMoriah Waterland 
842*5c51f124SMoriah Waterland 	if (argc == 1) {
843*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
844*5c51f124SMoriah Waterland 			return (R_ERROR);
845*5c51f124SMoriah Waterland 		}
846*5c51f124SMoriah Waterland 	}
847*5c51f124SMoriah Waterland 
848*5c51f124SMoriah Waterland 	/* get current root path */
849*5c51f124SMoriah Waterland 
850*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
851*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
852*5c51f124SMoriah Waterland 		return (r);
853*5c51f124SMoriah Waterland 	}
854*5c51f124SMoriah Waterland 
855*5c51f124SMoriah Waterland 	/* start of command debugging information */
856*5c51f124SMoriah Waterland 
857*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
858*5c51f124SMoriah Waterland 
859*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
860*5c51f124SMoriah Waterland 
861*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
862*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
863*5c51f124SMoriah Waterland 		/* initial install: install root cannot be global zone */
864*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_INITIAL_INSTALL, rootPath);
865*5c51f124SMoriah Waterland 		return (R_FAILURE);
866*5c51f124SMoriah Waterland 	}
867*5c51f124SMoriah Waterland 
868*5c51f124SMoriah Waterland 	/* must not be installation of a non-global zone */
869*5c51f124SMoriah Waterland 
870*5c51f124SMoriah Waterland 	if (a_gdt->gd_nonglobalZoneInstall == B_TRUE) {
871*5c51f124SMoriah Waterland 		/* initial nonglobal zone install: no path can be global zone */
872*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_NGZ_ZONE_INSTALL, rootPath);
873*5c51f124SMoriah Waterland 		return (R_FAILURE);
874*5c51f124SMoriah Waterland 	}
875*5c51f124SMoriah Waterland 
876*5c51f124SMoriah Waterland 	/* handle if global zone installation to the install root */
877*5c51f124SMoriah Waterland 
878*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) &&
879*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
880*5c51f124SMoriah Waterland 			/* the path is a global zone */
881*5c51f124SMoriah Waterland 
882*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE,
883*5c51f124SMoriah Waterland 				rootPath);
884*5c51f124SMoriah Waterland 
885*5c51f124SMoriah Waterland 			return (R_SUCCESS);
886*5c51f124SMoriah Waterland 	}
887*5c51f124SMoriah Waterland 
888*5c51f124SMoriah Waterland 	/* true if current root is "/" and zone name is GLOBAL_ZONENAME */
889*5c51f124SMoriah Waterland 
890*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") == 0) {
891*5c51f124SMoriah Waterland 		if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
892*5c51f124SMoriah Waterland 			/* the path is a global zone */
893*5c51f124SMoriah Waterland 
894*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE,
895*5c51f124SMoriah Waterland 				rootPath);
896*5c51f124SMoriah Waterland 
897*5c51f124SMoriah Waterland 			return (R_SUCCESS);
898*5c51f124SMoriah Waterland 		}
899*5c51f124SMoriah Waterland 
900*5c51f124SMoriah Waterland 		/* inside a non-global zone */
901*5c51f124SMoriah Waterland 
902*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_ZONENAME_ISNT_GLOBAL,
903*5c51f124SMoriah Waterland 			rootPath, a_gdt->gd_zoneName);
904*5c51f124SMoriah Waterland 
905*5c51f124SMoriah Waterland 		return (R_FAILURE);
906*5c51f124SMoriah Waterland 	}
907*5c51f124SMoriah Waterland 
908*5c51f124SMoriah Waterland 	/*
909*5c51f124SMoriah Waterland 	 * current root is not "/" - see if target looks like a global zone
910*5c51f124SMoriah Waterland 	 *
911*5c51f124SMoriah Waterland 	 * - rootpath is not "/"
912*5c51f124SMoriah Waterland 	 * - and $ROOTDIR/etc/zones exists
913*5c51f124SMoriah Waterland 	 * - and $ROOTDIR/.tmp_proto does not exist
914*5c51f124SMoriah Waterland 	 * - and $ROOTDIR/var is not a symbolic link
915*5c51f124SMoriah Waterland 	 */
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 	/* not global zone if /etc/zones does not exist */
918*5c51f124SMoriah Waterland 
919*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
920*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/etc/zones");
921*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
922*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_ISNT_DIRECTORY,
923*5c51f124SMoriah Waterland 			rootPath, "/etc/zones");
924*5c51f124SMoriah Waterland 		return (R_FAILURE);
925*5c51f124SMoriah Waterland 	}
926*5c51f124SMoriah Waterland 
927*5c51f124SMoriah Waterland 	/* .tmp_proto must not exist */
928*5c51f124SMoriah Waterland 
929*5c51f124SMoriah Waterland 	r = testPath(TEST_NOT_EXISTS,
930*5c51f124SMoriah Waterland 		"%s/%s", rootPath, ".tmp_proto");
931*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
932*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_EXISTS,
933*5c51f124SMoriah Waterland 			rootPath, "/.tmp_proto");
934*5c51f124SMoriah Waterland 		return (R_FAILURE);
935*5c51f124SMoriah Waterland 	}
936*5c51f124SMoriah Waterland 
937*5c51f124SMoriah Waterland 	/* /var must not be a symbolic link */
938*5c51f124SMoriah Waterland 
939*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
940*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/var");
941*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
942*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_SYMLINK,
943*5c51f124SMoriah Waterland 			rootPath, "/var");
944*5c51f124SMoriah Waterland 		return (R_FAILURE);
945*5c51f124SMoriah Waterland 	}
946*5c51f124SMoriah Waterland 
947*5c51f124SMoriah Waterland 	/* the path is a global zone */
948*5c51f124SMoriah Waterland 
949*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE, rootPath);
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland 	return (R_SUCCESS);
952*5c51f124SMoriah Waterland }
953*5c51f124SMoriah Waterland 
954*5c51f124SMoriah Waterland /*
955*5c51f124SMoriah Waterland  * Name:	cmd_is_netinstall_image
956*5c51f124SMoriah Waterland  * Description:	determine if target is a net install image
957*5c51f124SMoriah Waterland  * Scope:	public
958*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
959*5c51f124SMoriah Waterland  *		  - optional path to target to test
960*5c51f124SMoriah Waterland  * Returns:	int
961*5c51f124SMoriah Waterland  *			== 0 - success
962*5c51f124SMoriah Waterland  *			!= 0 - failure
963*5c51f124SMoriah Waterland  * IMPLEMENTATION:
964*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
965*5c51f124SMoriah Waterland  *  - must not be installation of a zone
966*5c51f124SMoriah Waterland  *  - must not be a global zone
967*5c51f124SMoriah Waterland  *  - must not be a mounted mini-root
968*5c51f124SMoriah Waterland  *  - zone name must be "global"
969*5c51f124SMoriah Waterland  *  - $ROOTDIR/.tmp_proto must exist and must be a directory
970*5c51f124SMoriah Waterland  *  - $ROOTDIR/var must exist and must be a symbolic link
971*5c51f124SMoriah Waterland  *  - $ROOTDIR/tmp/kernel must exist and must be a directory
972*5c51f124SMoriah Waterland  *  - $ROOTDIR/.tmp_proto/kernel must exist and must be a symbolic link
973*5c51f124SMoriah Waterland  */
974*5c51f124SMoriah Waterland 
975*5c51f124SMoriah Waterland static int
976*5c51f124SMoriah Waterland cmd_is_netinstall_image(int argc, char **argv, GLOBALDATA_T *a_gdt)
977*5c51f124SMoriah Waterland {
978*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
979*5c51f124SMoriah Waterland 	int	c;
980*5c51f124SMoriah Waterland 	int	r;
981*5c51f124SMoriah Waterland static	char	*cmdName = "is_netinstall_image";
982*5c51f124SMoriah Waterland static	int	recursion = 0;
983*5c51f124SMoriah Waterland 
984*5c51f124SMoriah Waterland 	/* process any command line options */
985*5c51f124SMoriah Waterland 
986*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
987*5c51f124SMoriah Waterland 		switch (c) {
988*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
989*5c51f124SMoriah Waterland 			break;
990*5c51f124SMoriah Waterland 		case '?':
991*5c51f124SMoriah Waterland 		default:
992*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
993*5c51f124SMoriah Waterland 			return (R_USAGE);
994*5c51f124SMoriah Waterland 		}
995*5c51f124SMoriah Waterland 	}
996*5c51f124SMoriah Waterland 
997*5c51f124SMoriah Waterland 	/* prevent recursion */
998*5c51f124SMoriah Waterland 
999*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1000*5c51f124SMoriah Waterland 
1001*5c51f124SMoriah Waterland 		/* a netinstall image cannot be a global zone */
1002*5c51f124SMoriah Waterland 
1003*5c51f124SMoriah Waterland 		r = cmd_is_global_zone(argc, argv, a_gdt);
1004*5c51f124SMoriah Waterland 
1005*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
1006*5c51f124SMoriah Waterland 
1007*5c51f124SMoriah Waterland 		recursion--;
1008*5c51f124SMoriah Waterland 
1009*5c51f124SMoriah Waterland 		switch (r) {
1010*5c51f124SMoriah Waterland 			case R_SUCCESS:
1011*5c51f124SMoriah Waterland 				return (R_FAILURE);
1012*5c51f124SMoriah Waterland 			case R_FAILURE:
1013*5c51f124SMoriah Waterland 				break;
1014*5c51f124SMoriah Waterland 			case R_USAGE:
1015*5c51f124SMoriah Waterland 			case R_ERROR:
1016*5c51f124SMoriah Waterland 			default:
1017*5c51f124SMoriah Waterland 				return (r);
1018*5c51f124SMoriah Waterland 		}
1019*5c51f124SMoriah Waterland 	}
1020*5c51f124SMoriah Waterland 
1021*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 	argc -= optind;
1024*5c51f124SMoriah Waterland 	argv += optind;
1025*5c51f124SMoriah Waterland 
1026*5c51f124SMoriah Waterland 	/* error if more than one argument */
1027*5c51f124SMoriah Waterland 
1028*5c51f124SMoriah Waterland 	if (argc > 1) {
1029*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1030*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1031*5c51f124SMoriah Waterland 		return (R_USAGE);
1032*5c51f124SMoriah Waterland 	}
1033*5c51f124SMoriah Waterland 
1034*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1035*5c51f124SMoriah Waterland 
1036*5c51f124SMoriah Waterland 	if (argc == 1) {
1037*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1038*5c51f124SMoriah Waterland 			return (R_ERROR);
1039*5c51f124SMoriah Waterland 		}
1040*5c51f124SMoriah Waterland 	}
1041*5c51f124SMoriah Waterland 
1042*5c51f124SMoriah Waterland 	/* get current root path */
1043*5c51f124SMoriah Waterland 
1044*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1045*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1046*5c51f124SMoriah Waterland 		return (r);
1047*5c51f124SMoriah Waterland 	}
1048*5c51f124SMoriah Waterland 
1049*5c51f124SMoriah Waterland 	/* start of command debugging information */
1050*5c51f124SMoriah Waterland 
1051*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1052*5c51f124SMoriah Waterland 
1053*5c51f124SMoriah Waterland 	/* current zone name must be "global" */
1054*5c51f124SMoriah Waterland 
1055*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
1056*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_BAD_CURRENT_ZONE,
1057*5c51f124SMoriah Waterland 			rootPath, GLOBAL_ZONENAME);
1058*5c51f124SMoriah Waterland 		return (R_FAILURE);
1059*5c51f124SMoriah Waterland 	}
1060*5c51f124SMoriah Waterland 
1061*5c51f124SMoriah Waterland 	/* cannot be a mounted_miniroot */
1062*5c51f124SMoriah Waterland 
1063*5c51f124SMoriah Waterland 	if (cmd_is_mounted_miniroot(argc, argv, a_gdt) == R_SUCCESS) {
1064*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_IS_MOUNTED_MINIROOT,
1065*5c51f124SMoriah Waterland 			rootPath);
1066*5c51f124SMoriah Waterland 		return (R_FAILURE);
1067*5c51f124SMoriah Waterland 	}
1068*5c51f124SMoriah Waterland 
1069*5c51f124SMoriah Waterland 	/* $ROOTDIR/.tmp_proto exists */
1070*5c51f124SMoriah Waterland 
1071*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
1072*5c51f124SMoriah Waterland 		"%s/%s", rootPath, ".tmp_proto");
1073*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1074*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_DIRECTORY,
1075*5c51f124SMoriah Waterland 			rootPath, "/.tmp_proto");
1076*5c51f124SMoriah Waterland 		return (R_FAILURE);
1077*5c51f124SMoriah Waterland 	}
1078*5c51f124SMoriah Waterland 
1079*5c51f124SMoriah Waterland 	/* $ROOTDIR/var is a symbolic link */
1080*5c51f124SMoriah Waterland 
1081*5c51f124SMoriah Waterland 	r = testPath(TEST_IS_SYMBOLIC_LINK,
1082*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/var");
1083*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1084*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_SYMLINK,
1085*5c51f124SMoriah Waterland 			rootPath, "/var");
1086*5c51f124SMoriah Waterland 		return (R_FAILURE);
1087*5c51f124SMoriah Waterland 	}
1088*5c51f124SMoriah Waterland 
1089*5c51f124SMoriah Waterland 	/* $ROOTDIR/tmp/kernel does exist */
1090*5c51f124SMoriah Waterland 
1091*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
1092*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/tmp/kernel");
1093*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1094*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_DIRECTORY,
1095*5c51f124SMoriah Waterland 			rootPath, "/tmp/kernel");
1096*5c51f124SMoriah Waterland 		return (R_FAILURE);
1097*5c51f124SMoriah Waterland 	}
1098*5c51f124SMoriah Waterland 
1099*5c51f124SMoriah Waterland 	/* $ROOTDIR/.tmp_proto/kernel is a symbolic link */
1100*5c51f124SMoriah Waterland 
1101*5c51f124SMoriah Waterland 	r = testPath(TEST_IS_SYMBOLIC_LINK,
1102*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/.tmp_proto/kernel");
1103*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1104*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_SYMLINK,
1105*5c51f124SMoriah Waterland 			rootPath, "/.tmp_proto/kernel");
1106*5c51f124SMoriah Waterland 		return (R_FAILURE);
1107*5c51f124SMoriah Waterland 	}
1108*5c51f124SMoriah Waterland 
1109*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
1110*5c51f124SMoriah Waterland 
1111*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
1112*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
1113*5c51f124SMoriah Waterland 		/* initial install: install root cannot be netinstall image */
1114*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_INITIAL_INSTALL, rootPath);
1115*5c51f124SMoriah Waterland 		return (R_FAILURE);
1116*5c51f124SMoriah Waterland 	}
1117*5c51f124SMoriah Waterland 
1118*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
1119*5c51f124SMoriah Waterland 
1120*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
1121*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
1122*5c51f124SMoriah Waterland 		/* initial zone install: no path can be netinstall image */
1123*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_INIM_ZONE_INSTALL, rootPath);
1124*5c51f124SMoriah Waterland 		return (R_FAILURE);
1125*5c51f124SMoriah Waterland 	}
1126*5c51f124SMoriah Waterland 
1127*5c51f124SMoriah Waterland 	/* target is a netinstall image */
1128*5c51f124SMoriah Waterland 
1129*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_IS_NETINSTALL_IMAGE, rootPath);
1130*5c51f124SMoriah Waterland 
1131*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1132*5c51f124SMoriah Waterland }
1133*5c51f124SMoriah Waterland 
1134*5c51f124SMoriah Waterland /*
1135*5c51f124SMoriah Waterland  * Name:	cmd_is_mounted_miniroot
1136*5c51f124SMoriah Waterland  * Description:	determine if target is a mounted miniroot image
1137*5c51f124SMoriah Waterland  * Scope:	public
1138*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1139*5c51f124SMoriah Waterland  *		  - optional path to target to test
1140*5c51f124SMoriah Waterland  * Returns:	int
1141*5c51f124SMoriah Waterland  *			== 0 - success
1142*5c51f124SMoriah Waterland  *			!= 0 - failure
1143*5c51f124SMoriah Waterland  * IMPLEMENTATION:
1144*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
1145*5c51f124SMoriah Waterland  *  - must not be installation of a zone
1146*5c51f124SMoriah Waterland  *  - zone name must be "global"
1147*5c51f124SMoriah Waterland  *  - $ROOTDIR/tmp/kernel must exist and must be a symbolic link
1148*5c51f124SMoriah Waterland  *  - $ROOTDIR/tmp/root/kernel must exist and must be a directory
1149*5c51f124SMoriah Waterland  */
1150*5c51f124SMoriah Waterland 
1151*5c51f124SMoriah Waterland static int
1152*5c51f124SMoriah Waterland cmd_is_mounted_miniroot(int argc, char **argv, GLOBALDATA_T *a_gdt)
1153*5c51f124SMoriah Waterland {
1154*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1155*5c51f124SMoriah Waterland 	int	c;
1156*5c51f124SMoriah Waterland 	int	r;
1157*5c51f124SMoriah Waterland static	char	*cmdName = "is_mounted_miniroot";
1158*5c51f124SMoriah Waterland static	int	recursion = 0;
1159*5c51f124SMoriah Waterland 
1160*5c51f124SMoriah Waterland 	/* process any command line options */
1161*5c51f124SMoriah Waterland 
1162*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1163*5c51f124SMoriah Waterland 		switch (c) {
1164*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1165*5c51f124SMoriah Waterland 			break;
1166*5c51f124SMoriah Waterland 		case '?':
1167*5c51f124SMoriah Waterland 		default:
1168*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1169*5c51f124SMoriah Waterland 			return (R_USAGE);
1170*5c51f124SMoriah Waterland 		}
1171*5c51f124SMoriah Waterland 	}
1172*5c51f124SMoriah Waterland 
1173*5c51f124SMoriah Waterland 	/* prevent recursion */
1174*5c51f124SMoriah Waterland 
1175*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1176*5c51f124SMoriah Waterland 		recursion--;
1177*5c51f124SMoriah Waterland 	}
1178*5c51f124SMoriah Waterland 
1179*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1180*5c51f124SMoriah Waterland 
1181*5c51f124SMoriah Waterland 	argc -= optind;
1182*5c51f124SMoriah Waterland 	argv += optind;
1183*5c51f124SMoriah Waterland 
1184*5c51f124SMoriah Waterland 	/* error if more than one argument */
1185*5c51f124SMoriah Waterland 
1186*5c51f124SMoriah Waterland 	if (argc > 1) {
1187*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1188*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1189*5c51f124SMoriah Waterland 		return (R_USAGE);
1190*5c51f124SMoriah Waterland 	}
1191*5c51f124SMoriah Waterland 
1192*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1193*5c51f124SMoriah Waterland 
1194*5c51f124SMoriah Waterland 	if (argc == 1) {
1195*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1196*5c51f124SMoriah Waterland 			return (R_ERROR);
1197*5c51f124SMoriah Waterland 		}
1198*5c51f124SMoriah Waterland 	}
1199*5c51f124SMoriah Waterland 
1200*5c51f124SMoriah Waterland 	/* get current root path */
1201*5c51f124SMoriah Waterland 
1202*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1203*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1204*5c51f124SMoriah Waterland 		return (r);
1205*5c51f124SMoriah Waterland 	}
1206*5c51f124SMoriah Waterland 
1207*5c51f124SMoriah Waterland 	/* start of command debugging information */
1208*5c51f124SMoriah Waterland 
1209*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1210*5c51f124SMoriah Waterland 
1211*5c51f124SMoriah Waterland 	/* current zone name must be "global" */
1212*5c51f124SMoriah Waterland 
1213*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
1214*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_BAD_CURRENT_ZONE,
1215*5c51f124SMoriah Waterland 			rootPath, GLOBAL_ZONENAME);
1216*5c51f124SMoriah Waterland 		return (R_FAILURE);
1217*5c51f124SMoriah Waterland 	}
1218*5c51f124SMoriah Waterland 
1219*5c51f124SMoriah Waterland 	/* $ROOTDIR/tmp/kernel is a symbolic link */
1220*5c51f124SMoriah Waterland 
1221*5c51f124SMoriah Waterland 	r = testPath(TEST_IS_SYMBOLIC_LINK,
1222*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/tmp/kernel");
1223*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1224*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_ISNT_SYMLINK,
1225*5c51f124SMoriah Waterland 			rootPath, "/tmp/kernel");
1226*5c51f124SMoriah Waterland 		return (R_FAILURE);
1227*5c51f124SMoriah Waterland 	}
1228*5c51f124SMoriah Waterland 
1229*5c51f124SMoriah Waterland 	/* $ROOTDIR/tmp/root/kernel is a directory */
1230*5c51f124SMoriah Waterland 
1231*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
1232*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/tmp/root/kernel");
1233*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1234*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_ISNT_DIRECTORY,
1235*5c51f124SMoriah Waterland 			rootPath, "/tmp/root/kernel");
1236*5c51f124SMoriah Waterland 		return (R_FAILURE);
1237*5c51f124SMoriah Waterland 	}
1238*5c51f124SMoriah Waterland 
1239*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
1240*5c51f124SMoriah Waterland 
1241*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
1242*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
1243*5c51f124SMoriah Waterland 		/* initial install: install root cannot be mounted miniroot */
1244*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_INITIAL_INSTALL, rootPath);
1245*5c51f124SMoriah Waterland 		return (R_FAILURE);
1246*5c51f124SMoriah Waterland 	}
1247*5c51f124SMoriah Waterland 
1248*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
1249*5c51f124SMoriah Waterland 
1250*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
1251*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
1252*5c51f124SMoriah Waterland 		/* initial zone install: no path can be mounted miniroot */
1253*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IMRT_ZONE_INSTALL, rootPath);
1254*5c51f124SMoriah Waterland 		return (R_FAILURE);
1255*5c51f124SMoriah Waterland 	}
1256*5c51f124SMoriah Waterland 
1257*5c51f124SMoriah Waterland 	/* target is a mounted miniroot */
1258*5c51f124SMoriah Waterland 
1259*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_IS_MOUNTED_MINIROOT, rootPath);
1260*5c51f124SMoriah Waterland 
1261*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1262*5c51f124SMoriah Waterland }
1263*5c51f124SMoriah Waterland 
1264*5c51f124SMoriah Waterland /*
1265*5c51f124SMoriah Waterland  * Name:	cmd_is_nonglobal_zone
1266*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
1267*5c51f124SMoriah Waterland  * Scope:	public
1268*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1269*5c51f124SMoriah Waterland  *		  - optional path to target to test
1270*5c51f124SMoriah Waterland  * Returns:	int
1271*5c51f124SMoriah Waterland  *			== 0 - success
1272*5c51f124SMoriah Waterland  *			!= 0 - failure
1273*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
1274*5c51f124SMoriah Waterland  *  - must not be installation of a global zone
1275*5c51f124SMoriah Waterland  *  - success if installation of a non-global zone
1276*5c51f124SMoriah Waterland  */
1277*5c51f124SMoriah Waterland 
1278*5c51f124SMoriah Waterland static int
1279*5c51f124SMoriah Waterland cmd_is_nonglobal_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
1280*5c51f124SMoriah Waterland {
1281*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1282*5c51f124SMoriah Waterland 	int	c;
1283*5c51f124SMoriah Waterland 	int	r;
1284*5c51f124SMoriah Waterland static	char	*cmdName = "is_nonglobal_zone";
1285*5c51f124SMoriah Waterland static	int	recursion = 0;
1286*5c51f124SMoriah Waterland 
1287*5c51f124SMoriah Waterland 	/* process any command line options */
1288*5c51f124SMoriah Waterland 
1289*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1290*5c51f124SMoriah Waterland 		switch (c) {
1291*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1292*5c51f124SMoriah Waterland 			break;
1293*5c51f124SMoriah Waterland 		case '?':
1294*5c51f124SMoriah Waterland 		default:
1295*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1296*5c51f124SMoriah Waterland 			return (R_USAGE);
1297*5c51f124SMoriah Waterland 		}
1298*5c51f124SMoriah Waterland 	}
1299*5c51f124SMoriah Waterland 
1300*5c51f124SMoriah Waterland 	/* prevent recursion */
1301*5c51f124SMoriah Waterland 
1302*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1303*5c51f124SMoriah Waterland 		recursion--;
1304*5c51f124SMoriah Waterland 	}
1305*5c51f124SMoriah Waterland 
1306*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1307*5c51f124SMoriah Waterland 
1308*5c51f124SMoriah Waterland 	argc -= optind;
1309*5c51f124SMoriah Waterland 	argv += optind;
1310*5c51f124SMoriah Waterland 
1311*5c51f124SMoriah Waterland 	/* error if more than one argument */
1312*5c51f124SMoriah Waterland 
1313*5c51f124SMoriah Waterland 	if (argc > 1) {
1314*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1315*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1316*5c51f124SMoriah Waterland 		return (R_USAGE);
1317*5c51f124SMoriah Waterland 	}
1318*5c51f124SMoriah Waterland 
1319*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1320*5c51f124SMoriah Waterland 
1321*5c51f124SMoriah Waterland 	if (argc == 1) {
1322*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1323*5c51f124SMoriah Waterland 			return (R_ERROR);
1324*5c51f124SMoriah Waterland 		}
1325*5c51f124SMoriah Waterland 	}
1326*5c51f124SMoriah Waterland 
1327*5c51f124SMoriah Waterland 	/* get current root path */
1328*5c51f124SMoriah Waterland 
1329*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1330*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1331*5c51f124SMoriah Waterland 		return (r);
1332*5c51f124SMoriah Waterland 	}
1333*5c51f124SMoriah Waterland 
1334*5c51f124SMoriah Waterland 	/* start of command debugging information */
1335*5c51f124SMoriah Waterland 
1336*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1337*5c51f124SMoriah Waterland 
1338*5c51f124SMoriah Waterland 	/* handle if non-global zone installation to the install root */
1339*5c51f124SMoriah Waterland 
1340*5c51f124SMoriah Waterland 	if ((a_gdt->gd_nonglobalZoneInstall == B_TRUE) &&
1341*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
1342*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_INSTALL_ZONENAME_IS_NGZ,
1343*5c51f124SMoriah Waterland 			rootPath, a_gdt->gd_zoneName);
1344*5c51f124SMoriah Waterland 		return (R_SUCCESS);
1345*5c51f124SMoriah Waterland 	}
1346*5c51f124SMoriah Waterland 
1347*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
1348*5c51f124SMoriah Waterland 
1349*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
1350*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
1351*5c51f124SMoriah Waterland 		/* initial install: install root cannot be non-global zone */
1352*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_INITIAL_INSTALL, rootPath);
1353*5c51f124SMoriah Waterland 		return (R_FAILURE);
1354*5c51f124SMoriah Waterland 	}
1355*5c51f124SMoriah Waterland 
1356*5c51f124SMoriah Waterland 	/* must not be installation of a global zone */
1357*5c51f124SMoriah Waterland 
1358*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
1359*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
1360*5c51f124SMoriah Waterland 		/* initial global zone install: no path can be nonglobal zone */
1361*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_GLOBAL_ZONE_INSTALL, rootPath);
1362*5c51f124SMoriah Waterland 		return (R_FAILURE);
1363*5c51f124SMoriah Waterland 	}
1364*5c51f124SMoriah Waterland 
1365*5c51f124SMoriah Waterland 	/*
1366*5c51f124SMoriah Waterland 	 * *********************************************************************
1367*5c51f124SMoriah Waterland 	 * if root directory is "/" then the only thing that needs to be done is
1368*5c51f124SMoriah Waterland 	 * to test the zone name directly - if the zone name is "global" then
1369*5c51f124SMoriah Waterland 	 * the target is not a non-global zone; otherwise if the zone name is
1370*5c51f124SMoriah Waterland 	 * not "global" then the target IS a non-global zone.
1371*5c51f124SMoriah Waterland 	 * *********************************************************************
1372*5c51f124SMoriah Waterland 	 */
1373*5c51f124SMoriah Waterland 
1374*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") == 0) {
1375*5c51f124SMoriah Waterland 		/* target is current running root */
1376*5c51f124SMoriah Waterland 		if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
1377*5c51f124SMoriah Waterland 			/* in the global zone */
1378*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_ISNT_NGZ,
1379*5c51f124SMoriah Waterland 				rootPath, a_gdt->gd_zoneName);
1380*5c51f124SMoriah Waterland 			return (R_FAILURE);
1381*5c51f124SMoriah Waterland 		}
1382*5c51f124SMoriah Waterland 		/* in a non-global zone */
1383*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_IS_NGZ,
1384*5c51f124SMoriah Waterland 			rootPath, a_gdt->gd_zoneName);
1385*5c51f124SMoriah Waterland 		return (R_SUCCESS);
1386*5c51f124SMoriah Waterland 	}
1387*5c51f124SMoriah Waterland 
1388*5c51f124SMoriah Waterland 	/*
1389*5c51f124SMoriah Waterland 	 * $ROOTDIR/etc/zones/index must exist in a global zone. It also
1390*5c51f124SMoriah Waterland 	 * exists in a non-global zone after s10u4 but we can't check that
1391*5c51f124SMoriah Waterland 	 * since it is undeterministic for all releases so we only check
1392*5c51f124SMoriah Waterland 	 * for the global zone here.
1393*5c51f124SMoriah Waterland 	 */
1394*5c51f124SMoriah Waterland 
1395*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS, "%s/%s", rootPath, "/etc/zones/index");
1396*5c51f124SMoriah Waterland 	if (r == R_SUCCESS) {
1397*5c51f124SMoriah Waterland 
1398*5c51f124SMoriah Waterland 		/* See if "global" exists in .../etc/zones/index */
1399*5c51f124SMoriah Waterland 
1400*5c51f124SMoriah Waterland 		if (testPath(TEST_GLOBAL_TOKEN_IN_FILE, "%s/%s", rootPath,
1401*5c51f124SMoriah Waterland 		    "/etc/zones/index") != R_SUCCESS) {
1402*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_ISNT_NGZ,
1403*5c51f124SMoriah Waterland 			    rootPath, GLOBAL_ZONENAME);
1404*5c51f124SMoriah Waterland 			return (R_FAILURE);
1405*5c51f124SMoriah Waterland 		}
1406*5c51f124SMoriah Waterland 	}
1407*5c51f124SMoriah Waterland 
1408*5c51f124SMoriah Waterland 	/*
1409*5c51f124SMoriah Waterland 	 * *********************************************************************
1410*5c51f124SMoriah Waterland 	 * If the root directory is "/" then you can use only the zone
1411*5c51f124SMoriah Waterland 	 * name to determine if the zone is non-global or not since the
1412*5c51f124SMoriah Waterland 	 * package is being installed or removed to the current "zone".
1413*5c51f124SMoriah Waterland 	 *
1414*5c51f124SMoriah Waterland 	 * Since the root directory being tested is not "/" then you have to
1415*5c51f124SMoriah Waterland 	 * look into the target to try and infer zone type using means other
1416*5c51f124SMoriah Waterland 	 * than the zone name only.
1417*5c51f124SMoriah Waterland 	 * *********************************************************************
1418*5c51f124SMoriah Waterland 	 */
1419*5c51f124SMoriah Waterland 
1420*5c51f124SMoriah Waterland 	/* reject if any items found that cannot be in a non-global zone */
1421*5c51f124SMoriah Waterland 
1422*5c51f124SMoriah Waterland 	/* .tmp_proto must not exist */
1423*5c51f124SMoriah Waterland 
1424*5c51f124SMoriah Waterland 	r = testPath(TEST_NOT_EXISTS, "%s/%s", rootPath, ".tmp_proto");
1425*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1426*5c51f124SMoriah Waterland 		/* $R/.tmp_proto cannot exist in a non-global zone */
1427*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_EXISTS,
1428*5c51f124SMoriah Waterland 			rootPath, "/.tmp_proto");
1429*5c51f124SMoriah Waterland 		return (R_FAILURE);
1430*5c51f124SMoriah Waterland 	}
1431*5c51f124SMoriah Waterland 
1432*5c51f124SMoriah Waterland 	/* /var must not be a symbolic link */
1433*5c51f124SMoriah Waterland 
1434*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1435*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/var");
1436*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1437*5c51f124SMoriah Waterland 		/* $R/var cannot be a symbolic link in a non-global zone */
1438*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_DOES_NOT_EXIST,
1439*5c51f124SMoriah Waterland 			rootPath, "/var");
1440*5c51f124SMoriah Waterland 		return (R_FAILURE);
1441*5c51f124SMoriah Waterland 	}
1442*5c51f124SMoriah Waterland 
1443*5c51f124SMoriah Waterland 	/* $ROOTDIR/tmp/root/kernel must not exist */
1444*5c51f124SMoriah Waterland 
1445*5c51f124SMoriah Waterland 	r = testPath(TEST_NOT_EXISTS,
1446*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/tmp/root/kernel");
1447*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1448*5c51f124SMoriah Waterland 		/* $R/tmp/root/kernel cannot exist in a non-global zone */
1449*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_EXISTS,
1450*5c51f124SMoriah Waterland 			rootPath, "/tmp/root/kernel");
1451*5c51f124SMoriah Waterland 		return (R_FAILURE);
1452*5c51f124SMoriah Waterland 	}
1453*5c51f124SMoriah Waterland 
1454*5c51f124SMoriah Waterland 	/*
1455*5c51f124SMoriah Waterland 	 * *********************************************************************
1456*5c51f124SMoriah Waterland 	 * no items exist in $ROOTDIR that identify something other than
1457*5c51f124SMoriah Waterland 	 * a non-global zone.
1458*5c51f124SMoriah Waterland 	 *
1459*5c51f124SMoriah Waterland 	 * if in global zone no more tests possible: is a non-global zone
1460*5c51f124SMoriah Waterland 	 * *********************************************************************
1461*5c51f124SMoriah Waterland 	 */
1462*5c51f124SMoriah Waterland 
1463*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
1464*5c51f124SMoriah Waterland 		/* in the global zone */
1465*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_IN_GZ_IS_NONGLOBAL_ZONE,
1466*5c51f124SMoriah Waterland 			rootPath);
1467*5c51f124SMoriah Waterland 		return (R_SUCCESS);
1468*5c51f124SMoriah Waterland 	}
1469*5c51f124SMoriah Waterland 
1470*5c51f124SMoriah Waterland 	/*
1471*5c51f124SMoriah Waterland 	 * *********************************************************************
1472*5c51f124SMoriah Waterland 	 * In non-global zone: interrogate zone name and type.
1473*5c51f124SMoriah Waterland 	 *
1474*5c51f124SMoriah Waterland 	 * The parent zone is the zone that the "pkgadd" or "pkgrm" command was
1475*5c51f124SMoriah Waterland 	 * run in. The child zone is the zone that the "pkginstall" or
1476*5c51f124SMoriah Waterland 	 * "pkgremove" command was run in.
1477*5c51f124SMoriah Waterland 	 * *********************************************************************
1478*5c51f124SMoriah Waterland 	 */
1479*5c51f124SMoriah Waterland 
1480*5c51f124SMoriah Waterland 	/*
1481*5c51f124SMoriah Waterland 	 * If parent zone name and current zone name defined, and
1482*5c51f124SMoriah Waterland 	 * both zone names are the same, since pkgcond is running
1483*5c51f124SMoriah Waterland 	 * inside of a non-global zone, this is how the scratch
1484*5c51f124SMoriah Waterland 	 * zone is implemented, so target is a non-global zone
1485*5c51f124SMoriah Waterland 	 */
1486*5c51f124SMoriah Waterland 
1487*5c51f124SMoriah Waterland 	if ((a_gdt->gd_parentZoneName != NULL) &&
1488*5c51f124SMoriah Waterland 		(a_gdt->gd_currentZoneName != NULL) &&
1489*5c51f124SMoriah Waterland 		(strcmp(a_gdt->gd_parentZoneName,
1490*5c51f124SMoriah Waterland 					a_gdt->gd_currentZoneName) == 0)) {
1491*5c51f124SMoriah Waterland 			/* parent and current zone name identical: non-gz */
1492*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_DEBUG, DBG_NGZN_PARENT_CHILD_SAMEZONE,
1493*5c51f124SMoriah Waterland 				rootPath, a_gdt->gd_parentZoneName);
1494*5c51f124SMoriah Waterland 			return (R_SUCCESS);
1495*5c51f124SMoriah Waterland 	}
1496*5c51f124SMoriah Waterland 
1497*5c51f124SMoriah Waterland 	/*
1498*5c51f124SMoriah Waterland 	 * In non-global zone if inherited FS's exits
1499*5c51f124SMoriah Waterland 	 * or zone specific read only FS's exist
1500*5c51f124SMoriah Waterland 	 * or it is in a mounted state.
1501*5c51f124SMoriah Waterland 	 */
1502*5c51f124SMoriah Waterland 
1503*5c51f124SMoriah Waterland 	if (a_gdt->gd_inheritedFileSystems != NULL ||
1504*5c51f124SMoriah Waterland 		a_gdt->gd_srFsMountedRO || a_gdt->inMountedState) {
1505*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_IS_NONGLOBAL_ZONE, rootPath);
1506*5c51f124SMoriah Waterland 		return (R_SUCCESS);
1507*5c51f124SMoriah Waterland 	}
1508*5c51f124SMoriah Waterland 
1509*5c51f124SMoriah Waterland 	/*
1510*5c51f124SMoriah Waterland 	 * the parent and current zone name are not the same;
1511*5c51f124SMoriah Waterland 	 * interrogate the zone types: the parent must be global
1512*5c51f124SMoriah Waterland 	 * and the current must be non-global, which would be set
1513*5c51f124SMoriah Waterland 	 * when a package command is run in the global zone that in
1514*5c51f124SMoriah Waterland 	 * turn runs a package command within the non-global zone.
1515*5c51f124SMoriah Waterland 	 */
1516*5c51f124SMoriah Waterland 
1517*5c51f124SMoriah Waterland 	/* if defined, parent zone type must be "global" */
1518*5c51f124SMoriah Waterland 
1519*5c51f124SMoriah Waterland 	if ((a_gdt->gd_parentZoneType != NULL) &&
1520*5c51f124SMoriah Waterland 		(strcmp(a_gdt->gd_parentZoneType, "nonglobal") == 0)) {
1521*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_BAD_PARENT_ZONETYPE,
1522*5c51f124SMoriah Waterland 			rootPath, "nonglobal");
1523*5c51f124SMoriah Waterland 		return (R_FAILURE);
1524*5c51f124SMoriah Waterland 	}
1525*5c51f124SMoriah Waterland 
1526*5c51f124SMoriah Waterland 	/* if defined, current zone type must be "nonglobal" */
1527*5c51f124SMoriah Waterland 
1528*5c51f124SMoriah Waterland 	if ((a_gdt->gd_currentZoneType != NULL) &&
1529*5c51f124SMoriah Waterland 		(strcmp(a_gdt->gd_currentZoneType, GLOBAL_ZONENAME) == 0)) {
1530*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NGZN_BAD_CURRENT_ZONETYPE,
1531*5c51f124SMoriah Waterland 			rootPath, GLOBAL_ZONENAME);
1532*5c51f124SMoriah Waterland 		return (R_FAILURE);
1533*5c51f124SMoriah Waterland 	}
1534*5c51f124SMoriah Waterland 
1535*5c51f124SMoriah Waterland 	/*
1536*5c51f124SMoriah Waterland 	 * *********************************************************************
1537*5c51f124SMoriah Waterland 	 * no other tests possible: target is a non-global zone
1538*5c51f124SMoriah Waterland 	 * *********************************************************************
1539*5c51f124SMoriah Waterland 	 */
1540*5c51f124SMoriah Waterland 
1541*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_NGZN_IS_NONGLOBAL_ZONE, rootPath);
1542*5c51f124SMoriah Waterland 
1543*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1544*5c51f124SMoriah Waterland }
1545*5c51f124SMoriah Waterland 
1546*5c51f124SMoriah Waterland /*
1547*5c51f124SMoriah Waterland  * Name:	cmd_is_running_system
1548*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
1549*5c51f124SMoriah Waterland  * Scope:	public
1550*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1551*5c51f124SMoriah Waterland  *		  - optional path to target to test
1552*5c51f124SMoriah Waterland  * Returns:	int
1553*5c51f124SMoriah Waterland  *			== 0 - success
1554*5c51f124SMoriah Waterland  *			!= 0 - failure
1555*5c51f124SMoriah Waterland  * IMPLEMENTATION:
1556*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
1557*5c51f124SMoriah Waterland  *  - must not be installation of a zone
1558*5c51f124SMoriah Waterland  *  - must not be a diskless client
1559*5c51f124SMoriah Waterland  *  - $ROOTDIR must be "/"
1560*5c51f124SMoriah Waterland  *  - zone name must be "global"
1561*5c51f124SMoriah Waterland  */
1562*5c51f124SMoriah Waterland 
1563*5c51f124SMoriah Waterland static int
1564*5c51f124SMoriah Waterland cmd_is_running_system(int argc, char **argv, GLOBALDATA_T *a_gdt)
1565*5c51f124SMoriah Waterland {
1566*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1567*5c51f124SMoriah Waterland 	int	c;
1568*5c51f124SMoriah Waterland 	int	r;
1569*5c51f124SMoriah Waterland static	char	*cmdName = "is_running_system";
1570*5c51f124SMoriah Waterland static	int	recursion = 0;
1571*5c51f124SMoriah Waterland 
1572*5c51f124SMoriah Waterland 	/* process any command line options */
1573*5c51f124SMoriah Waterland 
1574*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1575*5c51f124SMoriah Waterland 		switch (c) {
1576*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1577*5c51f124SMoriah Waterland 			break;
1578*5c51f124SMoriah Waterland 		case '?':
1579*5c51f124SMoriah Waterland 		default:
1580*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1581*5c51f124SMoriah Waterland 			return (R_USAGE);
1582*5c51f124SMoriah Waterland 		}
1583*5c51f124SMoriah Waterland 	}
1584*5c51f124SMoriah Waterland 
1585*5c51f124SMoriah Waterland 	/* prevent recursion */
1586*5c51f124SMoriah Waterland 
1587*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1588*5c51f124SMoriah Waterland 
1589*5c51f124SMoriah Waterland 		/* a running system cannot be a diskless client */
1590*5c51f124SMoriah Waterland 
1591*5c51f124SMoriah Waterland 		r = cmd_is_diskless_client(argc, argv, a_gdt);
1592*5c51f124SMoriah Waterland 
1593*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
1594*5c51f124SMoriah Waterland 
1595*5c51f124SMoriah Waterland 		recursion--;
1596*5c51f124SMoriah Waterland 
1597*5c51f124SMoriah Waterland 		switch (r) {
1598*5c51f124SMoriah Waterland 			case R_SUCCESS:
1599*5c51f124SMoriah Waterland 				return (R_FAILURE);
1600*5c51f124SMoriah Waterland 			case R_FAILURE:
1601*5c51f124SMoriah Waterland 				break;
1602*5c51f124SMoriah Waterland 			case R_USAGE:
1603*5c51f124SMoriah Waterland 			case R_ERROR:
1604*5c51f124SMoriah Waterland 			default:
1605*5c51f124SMoriah Waterland 				return (r);
1606*5c51f124SMoriah Waterland 		}
1607*5c51f124SMoriah Waterland 	}
1608*5c51f124SMoriah Waterland 
1609*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1610*5c51f124SMoriah Waterland 
1611*5c51f124SMoriah Waterland 	argc -= optind;
1612*5c51f124SMoriah Waterland 	argv += optind;
1613*5c51f124SMoriah Waterland 
1614*5c51f124SMoriah Waterland 	/* error if more than one argument */
1615*5c51f124SMoriah Waterland 
1616*5c51f124SMoriah Waterland 	if (argc > 1) {
1617*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1618*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1619*5c51f124SMoriah Waterland 		return (R_USAGE);
1620*5c51f124SMoriah Waterland 	}
1621*5c51f124SMoriah Waterland 
1622*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1623*5c51f124SMoriah Waterland 
1624*5c51f124SMoriah Waterland 	if (argc == 1) {
1625*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1626*5c51f124SMoriah Waterland 			return (R_ERROR);
1627*5c51f124SMoriah Waterland 		}
1628*5c51f124SMoriah Waterland 	}
1629*5c51f124SMoriah Waterland 
1630*5c51f124SMoriah Waterland 	/* get current root path */
1631*5c51f124SMoriah Waterland 
1632*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1633*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1634*5c51f124SMoriah Waterland 		return (r);
1635*5c51f124SMoriah Waterland 	}
1636*5c51f124SMoriah Waterland 
1637*5c51f124SMoriah Waterland 	/* start of command debugging information */
1638*5c51f124SMoriah Waterland 
1639*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1640*5c51f124SMoriah Waterland 
1641*5c51f124SMoriah Waterland 	/* if root path is "/" then check zone name */
1642*5c51f124SMoriah Waterland 
1643*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") != 0) {
1644*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IRST_ROOTPATH_BAD, rootPath, "/");
1645*5c51f124SMoriah Waterland 		return (R_FAILURE);
1646*5c51f124SMoriah Waterland 	}
1647*5c51f124SMoriah Waterland 
1648*5c51f124SMoriah Waterland 	/* zone name must be global */
1649*5c51f124SMoriah Waterland 
1650*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
1651*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IRST_ZONE_BAD, rootPath,
1652*5c51f124SMoriah Waterland 			GLOBAL_ZONENAME);
1653*5c51f124SMoriah Waterland 		return (R_FAILURE);
1654*5c51f124SMoriah Waterland 	}
1655*5c51f124SMoriah Waterland 
1656*5c51f124SMoriah Waterland 	/* must not be initial installation to the install root */
1657*5c51f124SMoriah Waterland 
1658*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
1659*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
1660*5c51f124SMoriah Waterland 		/* initial install: install root cannot be the running system */
1661*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IRST_INITIAL_INSTALL, rootPath);
1662*5c51f124SMoriah Waterland 		return (R_FAILURE);
1663*5c51f124SMoriah Waterland 	}
1664*5c51f124SMoriah Waterland 
1665*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
1666*5c51f124SMoriah Waterland 
1667*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
1668*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
1669*5c51f124SMoriah Waterland 		/* initial zone install: no path can be running system */
1670*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IRST_ZONE_INSTALL, rootPath);
1671*5c51f124SMoriah Waterland 		return (R_FAILURE);
1672*5c51f124SMoriah Waterland 	}
1673*5c51f124SMoriah Waterland 
1674*5c51f124SMoriah Waterland 	/* target is a running system */
1675*5c51f124SMoriah Waterland 
1676*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_IRST_PATH_IS_RUNNING_SYSTEM, rootPath);
1677*5c51f124SMoriah Waterland 
1678*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1679*5c51f124SMoriah Waterland }
1680*5c51f124SMoriah Waterland 
1681*5c51f124SMoriah Waterland /*
1682*5c51f124SMoriah Waterland  * Name:	cmd_can_add_driver
1683*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
1684*5c51f124SMoriah Waterland  * Scope:	public
1685*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1686*5c51f124SMoriah Waterland  *		  - optional path to target to test
1687*5c51f124SMoriah Waterland  * Returns:	int
1688*5c51f124SMoriah Waterland  *			== 0 - success
1689*5c51f124SMoriah Waterland  *			!= 0 - failure
1690*5c51f124SMoriah Waterland  * Implementation:
1691*5c51f124SMoriah Waterland  * A driver can be added to the system if the components of a Solaris
1692*5c51f124SMoriah Waterland  * instance capable of loading drivers is present and it is not the
1693*5c51f124SMoriah Waterland  * currently running system.
1694*5c51f124SMoriah Waterland  */
1695*5c51f124SMoriah Waterland 
1696*5c51f124SMoriah Waterland static int
1697*5c51f124SMoriah Waterland cmd_can_add_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
1698*5c51f124SMoriah Waterland {
1699*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1700*5c51f124SMoriah Waterland 	int	c;
1701*5c51f124SMoriah Waterland 	int	r;
1702*5c51f124SMoriah Waterland static	char	*cmdName = "can_add_driver";
1703*5c51f124SMoriah Waterland static	int	recursion = 0;
1704*5c51f124SMoriah Waterland 
1705*5c51f124SMoriah Waterland 	/* process any command line options */
1706*5c51f124SMoriah Waterland 
1707*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1708*5c51f124SMoriah Waterland 		switch (c) {
1709*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1710*5c51f124SMoriah Waterland 			break;
1711*5c51f124SMoriah Waterland 		case '?':
1712*5c51f124SMoriah Waterland 		default:
1713*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1714*5c51f124SMoriah Waterland 			return (R_USAGE);
1715*5c51f124SMoriah Waterland 		}
1716*5c51f124SMoriah Waterland 	}
1717*5c51f124SMoriah Waterland 
1718*5c51f124SMoriah Waterland 	/* prevent recursion */
1719*5c51f124SMoriah Waterland 
1720*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1721*5c51f124SMoriah Waterland 
1722*5c51f124SMoriah Waterland 		/* see if this is the current running system */
1723*5c51f124SMoriah Waterland 
1724*5c51f124SMoriah Waterland 		r = cmd_is_running_system(argc, argv, a_gdt);
1725*5c51f124SMoriah Waterland 
1726*5c51f124SMoriah Waterland 		/* cannot be a diskless client */
1727*5c51f124SMoriah Waterland 
1728*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
1729*5c51f124SMoriah Waterland 			r = cmd_is_diskless_client(argc, argv, a_gdt);
1730*5c51f124SMoriah Waterland 		}
1731*5c51f124SMoriah Waterland 
1732*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
1733*5c51f124SMoriah Waterland 
1734*5c51f124SMoriah Waterland 		recursion--;
1735*5c51f124SMoriah Waterland 
1736*5c51f124SMoriah Waterland 		switch (r) {
1737*5c51f124SMoriah Waterland 			case R_SUCCESS:
1738*5c51f124SMoriah Waterland 				/* is a running system */
1739*5c51f124SMoriah Waterland 				return (R_FAILURE);
1740*5c51f124SMoriah Waterland 			case R_FAILURE:
1741*5c51f124SMoriah Waterland 				/* not a running syste */
1742*5c51f124SMoriah Waterland 				break;
1743*5c51f124SMoriah Waterland 			case R_USAGE:
1744*5c51f124SMoriah Waterland 			case R_ERROR:
1745*5c51f124SMoriah Waterland 			default:
1746*5c51f124SMoriah Waterland 				/* cannot determine if is a running system */
1747*5c51f124SMoriah Waterland 				return (r);
1748*5c51f124SMoriah Waterland 		}
1749*5c51f124SMoriah Waterland 	}
1750*5c51f124SMoriah Waterland 
1751*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1752*5c51f124SMoriah Waterland 
1753*5c51f124SMoriah Waterland 	argc -= optind;
1754*5c51f124SMoriah Waterland 	argv += optind;
1755*5c51f124SMoriah Waterland 
1756*5c51f124SMoriah Waterland 	/* error if more than one argument */
1757*5c51f124SMoriah Waterland 
1758*5c51f124SMoriah Waterland 	if (argc > 1) {
1759*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1760*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1761*5c51f124SMoriah Waterland 		return (R_USAGE);
1762*5c51f124SMoriah Waterland 	}
1763*5c51f124SMoriah Waterland 
1764*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1765*5c51f124SMoriah Waterland 
1766*5c51f124SMoriah Waterland 	if (argc == 1) {
1767*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1768*5c51f124SMoriah Waterland 			return (R_ERROR);
1769*5c51f124SMoriah Waterland 		}
1770*5c51f124SMoriah Waterland 	}
1771*5c51f124SMoriah Waterland 
1772*5c51f124SMoriah Waterland 	/* get current root path */
1773*5c51f124SMoriah Waterland 
1774*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1775*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1776*5c51f124SMoriah Waterland 		return (r);
1777*5c51f124SMoriah Waterland 	}
1778*5c51f124SMoriah Waterland 
1779*5c51f124SMoriah Waterland 	/* start of command debugging information */
1780*5c51f124SMoriah Waterland 
1781*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1782*5c51f124SMoriah Waterland 
1783*5c51f124SMoriah Waterland 	/* /etc must exist and must not be a symbolic link */
1784*5c51f124SMoriah Waterland 
1785*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1786*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/etc");
1787*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1788*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
1789*5c51f124SMoriah Waterland 			rootPath, "/etc");
1790*5c51f124SMoriah Waterland 		return (R_FAILURE);
1791*5c51f124SMoriah Waterland 	}
1792*5c51f124SMoriah Waterland 
1793*5c51f124SMoriah Waterland 	/* /platform must exist and must not be a symbolic link */
1794*5c51f124SMoriah Waterland 
1795*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1796*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/platform");
1797*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1798*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
1799*5c51f124SMoriah Waterland 			rootPath, "/platform");
1800*5c51f124SMoriah Waterland 		return (R_FAILURE);
1801*5c51f124SMoriah Waterland 	}
1802*5c51f124SMoriah Waterland 
1803*5c51f124SMoriah Waterland 	/* /kernel must exist and must not be a symbolic link */
1804*5c51f124SMoriah Waterland 
1805*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1806*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/kernel");
1807*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1808*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
1809*5c51f124SMoriah Waterland 			rootPath, "/kernel");
1810*5c51f124SMoriah Waterland 		return (R_FAILURE);
1811*5c51f124SMoriah Waterland 	}
1812*5c51f124SMoriah Waterland 
1813*5c51f124SMoriah Waterland 	/* can add a driver */
1814*5c51f124SMoriah Waterland 
1815*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_ADDV_YES, rootPath);
1816*5c51f124SMoriah Waterland 
1817*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1818*5c51f124SMoriah Waterland }
1819*5c51f124SMoriah Waterland 
1820*5c51f124SMoriah Waterland /*
1821*5c51f124SMoriah Waterland  * Name:	cmd_can_update_driver
1822*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
1823*5c51f124SMoriah Waterland  * Scope:	public
1824*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1825*5c51f124SMoriah Waterland  *		  - optional path to target to test
1826*5c51f124SMoriah Waterland  * Returns:	int
1827*5c51f124SMoriah Waterland  *			== 0 - success
1828*5c51f124SMoriah Waterland  *			!= 0 - failure
1829*5c51f124SMoriah Waterland  * Implementation:
1830*5c51f124SMoriah Waterland  * A driver can be added to the system if the components of a Solaris
1831*5c51f124SMoriah Waterland  * instance capable of loading drivers is present and it is not the
1832*5c51f124SMoriah Waterland  * currently running system.
1833*5c51f124SMoriah Waterland  */
1834*5c51f124SMoriah Waterland 
1835*5c51f124SMoriah Waterland static int
1836*5c51f124SMoriah Waterland cmd_can_update_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
1837*5c51f124SMoriah Waterland {
1838*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1839*5c51f124SMoriah Waterland 	int	c;
1840*5c51f124SMoriah Waterland 	int	r;
1841*5c51f124SMoriah Waterland static	char	*cmdName = "can_update_driver";
1842*5c51f124SMoriah Waterland static	int	recursion = 0;
1843*5c51f124SMoriah Waterland 
1844*5c51f124SMoriah Waterland 	/* process any command line options */
1845*5c51f124SMoriah Waterland 
1846*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1847*5c51f124SMoriah Waterland 		switch (c) {
1848*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1849*5c51f124SMoriah Waterland 			break;
1850*5c51f124SMoriah Waterland 		case '?':
1851*5c51f124SMoriah Waterland 		default:
1852*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1853*5c51f124SMoriah Waterland 			return (R_USAGE);
1854*5c51f124SMoriah Waterland 		}
1855*5c51f124SMoriah Waterland 	}
1856*5c51f124SMoriah Waterland 
1857*5c51f124SMoriah Waterland 	/* prevent recursion */
1858*5c51f124SMoriah Waterland 
1859*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1860*5c51f124SMoriah Waterland 
1861*5c51f124SMoriah Waterland 		/* see if this is the current running system */
1862*5c51f124SMoriah Waterland 
1863*5c51f124SMoriah Waterland 		r = cmd_is_running_system(argc, argv, a_gdt);
1864*5c51f124SMoriah Waterland 
1865*5c51f124SMoriah Waterland 		/* cannot be a diskless client */
1866*5c51f124SMoriah Waterland 
1867*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
1868*5c51f124SMoriah Waterland 			r = cmd_is_diskless_client(argc, argv, a_gdt);
1869*5c51f124SMoriah Waterland 		}
1870*5c51f124SMoriah Waterland 
1871*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
1872*5c51f124SMoriah Waterland 
1873*5c51f124SMoriah Waterland 		recursion--;
1874*5c51f124SMoriah Waterland 
1875*5c51f124SMoriah Waterland 		switch (r) {
1876*5c51f124SMoriah Waterland 			case R_SUCCESS:
1877*5c51f124SMoriah Waterland 				/* is a running system */
1878*5c51f124SMoriah Waterland 				return (R_FAILURE);
1879*5c51f124SMoriah Waterland 			case R_FAILURE:
1880*5c51f124SMoriah Waterland 				/* not a running syste */
1881*5c51f124SMoriah Waterland 				break;
1882*5c51f124SMoriah Waterland 			case R_USAGE:
1883*5c51f124SMoriah Waterland 			case R_ERROR:
1884*5c51f124SMoriah Waterland 			default:
1885*5c51f124SMoriah Waterland 				/* cannot determine if is a running system */
1886*5c51f124SMoriah Waterland 				return (r);
1887*5c51f124SMoriah Waterland 		}
1888*5c51f124SMoriah Waterland 	}
1889*5c51f124SMoriah Waterland 
1890*5c51f124SMoriah Waterland 	/* normalize argc/argv */
1891*5c51f124SMoriah Waterland 
1892*5c51f124SMoriah Waterland 	argc -= optind;
1893*5c51f124SMoriah Waterland 	argv += optind;
1894*5c51f124SMoriah Waterland 
1895*5c51f124SMoriah Waterland 	/* error if more than one argument */
1896*5c51f124SMoriah Waterland 
1897*5c51f124SMoriah Waterland 	if (argc > 1) {
1898*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
1899*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
1900*5c51f124SMoriah Waterland 		return (R_USAGE);
1901*5c51f124SMoriah Waterland 	}
1902*5c51f124SMoriah Waterland 
1903*5c51f124SMoriah Waterland 	/* process root path if first argument present */
1904*5c51f124SMoriah Waterland 
1905*5c51f124SMoriah Waterland 	if (argc == 1) {
1906*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
1907*5c51f124SMoriah Waterland 			return (R_ERROR);
1908*5c51f124SMoriah Waterland 		}
1909*5c51f124SMoriah Waterland 	}
1910*5c51f124SMoriah Waterland 
1911*5c51f124SMoriah Waterland 	/* get current root path */
1912*5c51f124SMoriah Waterland 
1913*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
1914*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1915*5c51f124SMoriah Waterland 		return (r);
1916*5c51f124SMoriah Waterland 	}
1917*5c51f124SMoriah Waterland 
1918*5c51f124SMoriah Waterland 	/* start of command debugging information */
1919*5c51f124SMoriah Waterland 
1920*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
1921*5c51f124SMoriah Waterland 
1922*5c51f124SMoriah Waterland 	/* /etc must exist and must not be a symbolic link */
1923*5c51f124SMoriah Waterland 
1924*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1925*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/etc");
1926*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1927*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
1928*5c51f124SMoriah Waterland 			rootPath, "/etc");
1929*5c51f124SMoriah Waterland 		return (R_FAILURE);
1930*5c51f124SMoriah Waterland 	}
1931*5c51f124SMoriah Waterland 
1932*5c51f124SMoriah Waterland 	/* /platform must exist and must not be a symbolic link */
1933*5c51f124SMoriah Waterland 
1934*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1935*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/platform");
1936*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1937*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
1938*5c51f124SMoriah Waterland 			rootPath, "/platform");
1939*5c51f124SMoriah Waterland 		return (R_FAILURE);
1940*5c51f124SMoriah Waterland 	}
1941*5c51f124SMoriah Waterland 
1942*5c51f124SMoriah Waterland 	/* /kernel must exist and must not be a symbolic link */
1943*5c51f124SMoriah Waterland 
1944*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
1945*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/kernel");
1946*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
1947*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
1948*5c51f124SMoriah Waterland 			rootPath, "/kernel");
1949*5c51f124SMoriah Waterland 		return (R_FAILURE);
1950*5c51f124SMoriah Waterland 	}
1951*5c51f124SMoriah Waterland 
1952*5c51f124SMoriah Waterland 	/* can update driver */
1953*5c51f124SMoriah Waterland 
1954*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_UPDV_YES, rootPath);
1955*5c51f124SMoriah Waterland 
1956*5c51f124SMoriah Waterland 	return (R_SUCCESS);
1957*5c51f124SMoriah Waterland }
1958*5c51f124SMoriah Waterland 
1959*5c51f124SMoriah Waterland /*
1960*5c51f124SMoriah Waterland  * Name:	cmd_can_remove_driver
1961*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
1962*5c51f124SMoriah Waterland  * Scope:	public
1963*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
1964*5c51f124SMoriah Waterland  *		  - optional path to target to test
1965*5c51f124SMoriah Waterland  * Returns:	int
1966*5c51f124SMoriah Waterland  *			== 0 - success
1967*5c51f124SMoriah Waterland  *			!= 0 - failure
1968*5c51f124SMoriah Waterland  * Implementation:
1969*5c51f124SMoriah Waterland  * A driver can be added to the system if the components of a Solaris
1970*5c51f124SMoriah Waterland  * instance capable of loading drivers is present and it is not the
1971*5c51f124SMoriah Waterland  * currently running system.
1972*5c51f124SMoriah Waterland  */
1973*5c51f124SMoriah Waterland 
1974*5c51f124SMoriah Waterland static int
1975*5c51f124SMoriah Waterland cmd_can_remove_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
1976*5c51f124SMoriah Waterland {
1977*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
1978*5c51f124SMoriah Waterland 	int	c;
1979*5c51f124SMoriah Waterland 	int	r;
1980*5c51f124SMoriah Waterland static	char	*cmdName = "can_remove_driver";
1981*5c51f124SMoriah Waterland static	int	recursion = 0;
1982*5c51f124SMoriah Waterland 
1983*5c51f124SMoriah Waterland 	/* process any command line options */
1984*5c51f124SMoriah Waterland 
1985*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
1986*5c51f124SMoriah Waterland 		switch (c) {
1987*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
1988*5c51f124SMoriah Waterland 			break;
1989*5c51f124SMoriah Waterland 		case '?':
1990*5c51f124SMoriah Waterland 		default:
1991*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
1992*5c51f124SMoriah Waterland 			return (R_USAGE);
1993*5c51f124SMoriah Waterland 		}
1994*5c51f124SMoriah Waterland 	}
1995*5c51f124SMoriah Waterland 
1996*5c51f124SMoriah Waterland 	/* prevent recursion */
1997*5c51f124SMoriah Waterland 
1998*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
1999*5c51f124SMoriah Waterland 
2000*5c51f124SMoriah Waterland 		/* see if this is the current running system */
2001*5c51f124SMoriah Waterland 
2002*5c51f124SMoriah Waterland 		r = cmd_is_running_system(argc, argv, a_gdt);
2003*5c51f124SMoriah Waterland 
2004*5c51f124SMoriah Waterland 		/* cannot be a diskless client */
2005*5c51f124SMoriah Waterland 
2006*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2007*5c51f124SMoriah Waterland 			r = cmd_is_diskless_client(argc, argv, a_gdt);
2008*5c51f124SMoriah Waterland 		}
2009*5c51f124SMoriah Waterland 
2010*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
2011*5c51f124SMoriah Waterland 
2012*5c51f124SMoriah Waterland 		recursion--;
2013*5c51f124SMoriah Waterland 
2014*5c51f124SMoriah Waterland 		switch (r) {
2015*5c51f124SMoriah Waterland 			case R_SUCCESS:
2016*5c51f124SMoriah Waterland 				/* is a running system */
2017*5c51f124SMoriah Waterland 				return (R_FAILURE);
2018*5c51f124SMoriah Waterland 			case R_FAILURE:
2019*5c51f124SMoriah Waterland 				/* not a running syste */
2020*5c51f124SMoriah Waterland 				break;
2021*5c51f124SMoriah Waterland 			case R_USAGE:
2022*5c51f124SMoriah Waterland 			case R_ERROR:
2023*5c51f124SMoriah Waterland 			default:
2024*5c51f124SMoriah Waterland 				/* cannot determine if is a running system */
2025*5c51f124SMoriah Waterland 				return (r);
2026*5c51f124SMoriah Waterland 		}
2027*5c51f124SMoriah Waterland 	}
2028*5c51f124SMoriah Waterland 
2029*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2030*5c51f124SMoriah Waterland 
2031*5c51f124SMoriah Waterland 	argc -= optind;
2032*5c51f124SMoriah Waterland 	argv += optind;
2033*5c51f124SMoriah Waterland 
2034*5c51f124SMoriah Waterland 	/* error if more than one argument */
2035*5c51f124SMoriah Waterland 
2036*5c51f124SMoriah Waterland 	if (argc > 1) {
2037*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2038*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2039*5c51f124SMoriah Waterland 		return (R_USAGE);
2040*5c51f124SMoriah Waterland 	}
2041*5c51f124SMoriah Waterland 
2042*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2043*5c51f124SMoriah Waterland 
2044*5c51f124SMoriah Waterland 	if (argc == 1) {
2045*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2046*5c51f124SMoriah Waterland 			return (R_ERROR);
2047*5c51f124SMoriah Waterland 		}
2048*5c51f124SMoriah Waterland 	}
2049*5c51f124SMoriah Waterland 
2050*5c51f124SMoriah Waterland 	/* get current root path */
2051*5c51f124SMoriah Waterland 
2052*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2053*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2054*5c51f124SMoriah Waterland 		return (r);
2055*5c51f124SMoriah Waterland 	}
2056*5c51f124SMoriah Waterland 
2057*5c51f124SMoriah Waterland 	/* start of command debugging information */
2058*5c51f124SMoriah Waterland 
2059*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2060*5c51f124SMoriah Waterland 
2061*5c51f124SMoriah Waterland 	/* /etc must exist and must not be a symbolic link */
2062*5c51f124SMoriah Waterland 
2063*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
2064*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/etc");
2065*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2066*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
2067*5c51f124SMoriah Waterland 			rootPath, "/etc");
2068*5c51f124SMoriah Waterland 		return (R_FAILURE);
2069*5c51f124SMoriah Waterland 	}
2070*5c51f124SMoriah Waterland 
2071*5c51f124SMoriah Waterland 	/* /platform must exist and must not be a symbolic link */
2072*5c51f124SMoriah Waterland 
2073*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
2074*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/platform");
2075*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2076*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
2077*5c51f124SMoriah Waterland 			rootPath, "/platform");
2078*5c51f124SMoriah Waterland 		return (R_FAILURE);
2079*5c51f124SMoriah Waterland 	}
2080*5c51f124SMoriah Waterland 
2081*5c51f124SMoriah Waterland 	/* /kernel must exist and must not be a symbolic link */
2082*5c51f124SMoriah Waterland 
2083*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
2084*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/kernel");
2085*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2086*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
2087*5c51f124SMoriah Waterland 			rootPath, "/kernel");
2088*5c51f124SMoriah Waterland 		return (R_FAILURE);
2089*5c51f124SMoriah Waterland 	}
2090*5c51f124SMoriah Waterland 
2091*5c51f124SMoriah Waterland 	/* can remove driver */
2092*5c51f124SMoriah Waterland 
2093*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_RMDV_YES, rootPath);
2094*5c51f124SMoriah Waterland 
2095*5c51f124SMoriah Waterland 	return (R_SUCCESS);
2096*5c51f124SMoriah Waterland }
2097*5c51f124SMoriah Waterland 
2098*5c51f124SMoriah Waterland /*
2099*5c51f124SMoriah Waterland  * Name:	cmd_is_path_writable
2100*5c51f124SMoriah Waterland  * Description:	determine if target path is writable (not inherited)
2101*5c51f124SMoriah Waterland  * Scope:	public
2102*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2103*5c51f124SMoriah Waterland  *		  - optional path to target to test
2104*5c51f124SMoriah Waterland  * Returns:	int
2105*5c51f124SMoriah Waterland  *			== 0 - success
2106*5c51f124SMoriah Waterland  *			!= 0 - failure
2107*5c51f124SMoriah Waterland  * IMPLEMENTATION:
2108*5c51f124SMoriah Waterland  * - path must be found in the file systems configured
2109*5c51f124SMoriah Waterland  * - file system type must not be "inherited"
2110*5c51f124SMoriah Waterland  * - mount options must not include "read only"
2111*5c51f124SMoriah Waterland  */
2112*5c51f124SMoriah Waterland 
2113*5c51f124SMoriah Waterland static int
2114*5c51f124SMoriah Waterland cmd_is_path_writable(int argc, char **argv, GLOBALDATA_T *a_gdt)
2115*5c51f124SMoriah Waterland {
2116*5c51f124SMoriah Waterland 	FSI_T	*list;
2117*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2118*5c51f124SMoriah Waterland 	int	c;
2119*5c51f124SMoriah Waterland 	int	n;
2120*5c51f124SMoriah Waterland 	int	nn;
2121*5c51f124SMoriah Waterland 	int	r;
2122*5c51f124SMoriah Waterland 	long	listSize;
2123*5c51f124SMoriah Waterland 	long	rootPathLen;
2124*5c51f124SMoriah Waterland static	char	*cmdName = "is_path_writable";
2125*5c51f124SMoriah Waterland static	int	recursion = 0;
2126*5c51f124SMoriah Waterland 
2127*5c51f124SMoriah Waterland 	/* process any command line options */
2128*5c51f124SMoriah Waterland 
2129*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2130*5c51f124SMoriah Waterland 		switch (c) {
2131*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2132*5c51f124SMoriah Waterland 			break;
2133*5c51f124SMoriah Waterland 		case '?':
2134*5c51f124SMoriah Waterland 		default:
2135*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2136*5c51f124SMoriah Waterland 			return (R_USAGE);
2137*5c51f124SMoriah Waterland 		}
2138*5c51f124SMoriah Waterland 	}
2139*5c51f124SMoriah Waterland 
2140*5c51f124SMoriah Waterland 	/* prevent recursion */
2141*5c51f124SMoriah Waterland 
2142*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
2143*5c51f124SMoriah Waterland 		recursion--;
2144*5c51f124SMoriah Waterland 	}
2145*5c51f124SMoriah Waterland 
2146*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2147*5c51f124SMoriah Waterland 
2148*5c51f124SMoriah Waterland 	argc -= optind;
2149*5c51f124SMoriah Waterland 	argv += optind;
2150*5c51f124SMoriah Waterland 
2151*5c51f124SMoriah Waterland 	/* error if more than one argument */
2152*5c51f124SMoriah Waterland 
2153*5c51f124SMoriah Waterland 	if (argc > 1) {
2154*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2155*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2156*5c51f124SMoriah Waterland 		return (R_USAGE);
2157*5c51f124SMoriah Waterland 	}
2158*5c51f124SMoriah Waterland 
2159*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2160*5c51f124SMoriah Waterland 
2161*5c51f124SMoriah Waterland 	if (argc != 1) {
2162*5c51f124SMoriah Waterland 		(void) usage(ERR_REQUIRED_ROOTPATH_MISSING, cmdName);
2163*5c51f124SMoriah Waterland 		return (R_USAGE);
2164*5c51f124SMoriah Waterland 	}
2165*5c51f124SMoriah Waterland 
2166*5c51f124SMoriah Waterland 	if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2167*5c51f124SMoriah Waterland 		return (R_ERROR);
2168*5c51f124SMoriah Waterland 	}
2169*5c51f124SMoriah Waterland 
2170*5c51f124SMoriah Waterland 	/* get current root path */
2171*5c51f124SMoriah Waterland 
2172*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2173*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2174*5c51f124SMoriah Waterland 		return (r);
2175*5c51f124SMoriah Waterland 	}
2176*5c51f124SMoriah Waterland 
2177*5c51f124SMoriah Waterland 	/* start of command debugging information */
2178*5c51f124SMoriah Waterland 
2179*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2180*5c51f124SMoriah Waterland 
2181*5c51f124SMoriah Waterland 	/* search file system conf for this path */
2182*5c51f124SMoriah Waterland 
2183*5c51f124SMoriah Waterland 	rootPathLen = strlen(rootPath);
2184*5c51f124SMoriah Waterland 	list = a_gdt->gd_fileSystemConfig;
2185*5c51f124SMoriah Waterland 	listSize = a_gdt->gd_fileSystemConfigLen;
2186*5c51f124SMoriah Waterland 	for (nn = 0, n = 0; n < listSize; n++) {
2187*5c51f124SMoriah Waterland 		long	mplen = strlen(list[n].fsi_mntPoint);
2188*5c51f124SMoriah Waterland 		if (rootPathLen < mplen) {
2189*5c51f124SMoriah Waterland 			/* root path is longer than target, ignore */
2190*5c51f124SMoriah Waterland 			continue;
2191*5c51f124SMoriah Waterland 		}
2192*5c51f124SMoriah Waterland 		if (strncmp(rootPath, list[n].fsi_mntPoint, mplen) == 0) {
2193*5c51f124SMoriah Waterland 			/* remember last partial match */
2194*5c51f124SMoriah Waterland 			nn = n;
2195*5c51f124SMoriah Waterland 		}
2196*5c51f124SMoriah Waterland 	}
2197*5c51f124SMoriah Waterland 
2198*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_PWRT_INFO,
2199*5c51f124SMoriah Waterland 		rootPath, list[nn].fsi_mntPoint, list[nn].fsi_fsType,
2200*5c51f124SMoriah Waterland 		list[nn].fsi_mntOptions);
2201*5c51f124SMoriah Waterland 
2202*5c51f124SMoriah Waterland 	/*
2203*5c51f124SMoriah Waterland 	 * need to determine if the mount point is writeable:
2204*5c51f124SMoriah Waterland 	 * If parent mount point is "inherited" then it is not writeable
2205*5c51f124SMoriah Waterland 	 */
2206*5c51f124SMoriah Waterland 
2207*5c51f124SMoriah Waterland 	if (strcmp(list[nn].fsi_fsType, FSTYPE_INHERITED) == 0) {
2208*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_PWRT_INHERITED, rootPath,
2209*5c51f124SMoriah Waterland 			list[nn].fsi_mntOptions);
2210*5c51f124SMoriah Waterland 		return (R_FAILURE);
2211*5c51f124SMoriah Waterland 	}
2212*5c51f124SMoriah Waterland 
2213*5c51f124SMoriah Waterland 	/* see if the file system is mounted with the "read only" option */
2214*5c51f124SMoriah Waterland 
2215*5c51f124SMoriah Waterland 	r = mountOptionPresent(list[nn].fsi_mntOptions, MNTOPT_RO);
2216*5c51f124SMoriah Waterland 	if (r == R_SUCCESS) {
2217*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_PWRT_READONLY,
2218*5c51f124SMoriah Waterland 			rootPath, list[nn].fsi_mntOptions);
2219*5c51f124SMoriah Waterland 		return (R_FAILURE);
2220*5c51f124SMoriah Waterland 	}
2221*5c51f124SMoriah Waterland 
2222*5c51f124SMoriah Waterland 	/* target path is writable */
2223*5c51f124SMoriah Waterland 
2224*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_PWRT_IS, rootPath);
2225*5c51f124SMoriah Waterland 
2226*5c51f124SMoriah Waterland 	return (R_SUCCESS);
2227*5c51f124SMoriah Waterland }
2228*5c51f124SMoriah Waterland 
2229*5c51f124SMoriah Waterland /*
2230*5c51f124SMoriah Waterland  * Name:	cmd_is_alternative_root
2231*5c51f124SMoriah Waterland  * Description:	determine if target is an alternative root
2232*5c51f124SMoriah Waterland  * Scope:	public
2233*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2234*5c51f124SMoriah Waterland  *		  - optional path to target to test
2235*5c51f124SMoriah Waterland  * Returns:	int
2236*5c51f124SMoriah Waterland  *			== 0 - success
2237*5c51f124SMoriah Waterland  *			!= 0 - failure
2238*5c51f124SMoriah Waterland  * Implementation:
2239*5c51f124SMoriah Waterland  *  - success if an initial installation to the install root
2240*5c51f124SMoriah Waterland  *	(an initial install to $PKG_INSTALL_ROOT means that $PKG_INSTALL_ROOT
2241*5c51f124SMoriah Waterland  *	points to an alternative root that is under construction)
2242*5c51f124SMoriah Waterland  *  - must not be installation of a zone
2243*5c51f124SMoriah Waterland  *  - must not be a boot environment
2244*5c51f124SMoriah Waterland  *  - must not be a diskless client
2245*5c51f124SMoriah Waterland  *  - must not be a mounted miniroot
2246*5c51f124SMoriah Waterland  *  - must not be a netinstall image
2247*5c51f124SMoriah Waterland  *  - must not be a nonglobal zone
2248*5c51f124SMoriah Waterland  *  - must not be a running system
2249*5c51f124SMoriah Waterland  *  - $ROOTDIR must not be "/"
2250*5c51f124SMoriah Waterland  *  - $ROOTDIR/var must exist
2251*5c51f124SMoriah Waterland  */
2252*5c51f124SMoriah Waterland 
2253*5c51f124SMoriah Waterland static int
2254*5c51f124SMoriah Waterland cmd_is_alternative_root(int argc, char **argv, GLOBALDATA_T *a_gdt)
2255*5c51f124SMoriah Waterland {
2256*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2257*5c51f124SMoriah Waterland 	int	c;
2258*5c51f124SMoriah Waterland 	int	r;
2259*5c51f124SMoriah Waterland static	char	*cmdName = "is_alternative_root";
2260*5c51f124SMoriah Waterland static	int	recursion = 0;
2261*5c51f124SMoriah Waterland 
2262*5c51f124SMoriah Waterland 	/* process any command line options */
2263*5c51f124SMoriah Waterland 
2264*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2265*5c51f124SMoriah Waterland 		switch (c) {
2266*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2267*5c51f124SMoriah Waterland 			break;
2268*5c51f124SMoriah Waterland 		case '?':
2269*5c51f124SMoriah Waterland 		default:
2270*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2271*5c51f124SMoriah Waterland 			return (R_USAGE);
2272*5c51f124SMoriah Waterland 		}
2273*5c51f124SMoriah Waterland 	}
2274*5c51f124SMoriah Waterland 
2275*5c51f124SMoriah Waterland 	/* prevent recursion */
2276*5c51f124SMoriah Waterland 
2277*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
2278*5c51f124SMoriah Waterland 
2279*5c51f124SMoriah Waterland 		/*
2280*5c51f124SMoriah Waterland 		 * an alternative root cannot be any of the following
2281*5c51f124SMoriah Waterland 		 */
2282*5c51f124SMoriah Waterland 
2283*5c51f124SMoriah Waterland 		/* cannot be a boot_environment */
2284*5c51f124SMoriah Waterland 
2285*5c51f124SMoriah Waterland 		r = cmd_is_boot_environment(argc, argv, a_gdt);
2286*5c51f124SMoriah Waterland 
2287*5c51f124SMoriah Waterland 		/* cannot be a diskless_client */
2288*5c51f124SMoriah Waterland 
2289*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2290*5c51f124SMoriah Waterland 			r = cmd_is_diskless_client(argc, argv, a_gdt);
2291*5c51f124SMoriah Waterland 		}
2292*5c51f124SMoriah Waterland 
2293*5c51f124SMoriah Waterland 		/* cannot be a mounted_miniroot */
2294*5c51f124SMoriah Waterland 
2295*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2296*5c51f124SMoriah Waterland 			r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
2297*5c51f124SMoriah Waterland 		}
2298*5c51f124SMoriah Waterland 
2299*5c51f124SMoriah Waterland 		/* cannot be a netinstall_image */
2300*5c51f124SMoriah Waterland 
2301*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2302*5c51f124SMoriah Waterland 			r = cmd_is_netinstall_image(argc, argv, a_gdt);
2303*5c51f124SMoriah Waterland 		}
2304*5c51f124SMoriah Waterland 
2305*5c51f124SMoriah Waterland 		/* cannot be a nonglobal_zone */
2306*5c51f124SMoriah Waterland 
2307*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2308*5c51f124SMoriah Waterland 			r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
2309*5c51f124SMoriah Waterland 		}
2310*5c51f124SMoriah Waterland 
2311*5c51f124SMoriah Waterland 		/* cannot be a running_system */
2312*5c51f124SMoriah Waterland 
2313*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2314*5c51f124SMoriah Waterland 			r = cmd_is_running_system(argc, argv, a_gdt);
2315*5c51f124SMoriah Waterland 		}
2316*5c51f124SMoriah Waterland 
2317*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
2318*5c51f124SMoriah Waterland 
2319*5c51f124SMoriah Waterland 		recursion--;
2320*5c51f124SMoriah Waterland 
2321*5c51f124SMoriah Waterland 		/* return failure if any of the preceeding are true */
2322*5c51f124SMoriah Waterland 
2323*5c51f124SMoriah Waterland 		switch (r) {
2324*5c51f124SMoriah Waterland 			case R_SUCCESS:
2325*5c51f124SMoriah Waterland 				return (R_FAILURE);
2326*5c51f124SMoriah Waterland 			case R_FAILURE:
2327*5c51f124SMoriah Waterland 				break;
2328*5c51f124SMoriah Waterland 			case R_USAGE:
2329*5c51f124SMoriah Waterland 			case R_ERROR:
2330*5c51f124SMoriah Waterland 			default:
2331*5c51f124SMoriah Waterland 				return (r);
2332*5c51f124SMoriah Waterland 		}
2333*5c51f124SMoriah Waterland 	}
2334*5c51f124SMoriah Waterland 
2335*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2336*5c51f124SMoriah Waterland 
2337*5c51f124SMoriah Waterland 	argc -= optind;
2338*5c51f124SMoriah Waterland 	argv += optind;
2339*5c51f124SMoriah Waterland 
2340*5c51f124SMoriah Waterland 	/* error if more than one argument */
2341*5c51f124SMoriah Waterland 
2342*5c51f124SMoriah Waterland 	if (argc > 1) {
2343*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2344*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2345*5c51f124SMoriah Waterland 		return (R_USAGE);
2346*5c51f124SMoriah Waterland 	}
2347*5c51f124SMoriah Waterland 
2348*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2349*5c51f124SMoriah Waterland 
2350*5c51f124SMoriah Waterland 	if (argc == 1) {
2351*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2352*5c51f124SMoriah Waterland 			return (R_ERROR);
2353*5c51f124SMoriah Waterland 		}
2354*5c51f124SMoriah Waterland 	}
2355*5c51f124SMoriah Waterland 
2356*5c51f124SMoriah Waterland 	/* get current root path */
2357*5c51f124SMoriah Waterland 
2358*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2359*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2360*5c51f124SMoriah Waterland 		return (r);
2361*5c51f124SMoriah Waterland 	}
2362*5c51f124SMoriah Waterland 
2363*5c51f124SMoriah Waterland 	/* start of command debugging information */
2364*5c51f124SMoriah Waterland 
2365*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2366*5c51f124SMoriah Waterland 
2367*5c51f124SMoriah Waterland 	/* return success if initial installation */
2368*5c51f124SMoriah Waterland 
2369*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
2370*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
2371*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IALR_INITIAL_INSTALL, rootPath);
2372*5c51f124SMoriah Waterland 		return (R_SUCCESS);
2373*5c51f124SMoriah Waterland 	}
2374*5c51f124SMoriah Waterland 
2375*5c51f124SMoriah Waterland 	/* root path must not be "/" */
2376*5c51f124SMoriah Waterland 
2377*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") == 0) {
2378*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IALR_BAD_ROOTPATH, rootPath, "/");
2379*5c51f124SMoriah Waterland 		return (R_FAILURE);
2380*5c51f124SMoriah Waterland 	}
2381*5c51f124SMoriah Waterland 
2382*5c51f124SMoriah Waterland 	/* /var must exist */
2383*5c51f124SMoriah Waterland 
2384*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS,
2385*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/var");
2386*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2387*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IALR_PATH_DOES_NOT_EXIST,
2388*5c51f124SMoriah Waterland 			rootPath, "/var");
2389*5c51f124SMoriah Waterland 		return (R_FAILURE);
2390*5c51f124SMoriah Waterland 	}
2391*5c51f124SMoriah Waterland 
2392*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
2393*5c51f124SMoriah Waterland 
2394*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
2395*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
2396*5c51f124SMoriah Waterland 		/* initial zone install: no path can be alternative root */
2397*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_IALR_ZONE_INSTALL, rootPath);
2398*5c51f124SMoriah Waterland 		return (R_FAILURE);
2399*5c51f124SMoriah Waterland 	}
2400*5c51f124SMoriah Waterland 
2401*5c51f124SMoriah Waterland 	/* target is an alternative root */
2402*5c51f124SMoriah Waterland 
2403*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_IALR_IS, rootPath);
2404*5c51f124SMoriah Waterland 
2405*5c51f124SMoriah Waterland 	return (R_SUCCESS);
2406*5c51f124SMoriah Waterland }
2407*5c51f124SMoriah Waterland 
2408*5c51f124SMoriah Waterland /*
2409*5c51f124SMoriah Waterland  * Name:	cmd_is_boot_environment
2410*5c51f124SMoriah Waterland  * Description:	determine if target is an alternative, inactive boot environment
2411*5c51f124SMoriah Waterland  * Scope:	public
2412*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2413*5c51f124SMoriah Waterland  *		  - optional path to target to test
2414*5c51f124SMoriah Waterland  * Returns:	int
2415*5c51f124SMoriah Waterland  *			== 0 - success
2416*5c51f124SMoriah Waterland  *			!= 0 - failure
2417*5c51f124SMoriah Waterland  * IMPLEMENTATION:
2418*5c51f124SMoriah Waterland  *  - must not be initial installation to the install root
2419*5c51f124SMoriah Waterland  *  - must not be installation of a zone
2420*5c51f124SMoriah Waterland  *  - must not be a diskless client
2421*5c51f124SMoriah Waterland  *  - must not be a netinstall image
2422*5c51f124SMoriah Waterland  *  - must not be a mounted miniroot
2423*5c51f124SMoriah Waterland  *  - $ROOTDIR must not be "/"
2424*5c51f124SMoriah Waterland  *  - $ROOTDIR/etc/lutab must exist
2425*5c51f124SMoriah Waterland  *  - $ROOTDIR/etc/lu must exist and must be a directory
2426*5c51f124SMoriah Waterland  */
2427*5c51f124SMoriah Waterland 
2428*5c51f124SMoriah Waterland static int
2429*5c51f124SMoriah Waterland cmd_is_boot_environment(int argc, char **argv, GLOBALDATA_T *a_gdt)
2430*5c51f124SMoriah Waterland {
2431*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2432*5c51f124SMoriah Waterland 	int	c;
2433*5c51f124SMoriah Waterland 	int	r;
2434*5c51f124SMoriah Waterland static	char	*cmdName = "is_boot_environment";
2435*5c51f124SMoriah Waterland static	int	recursion = 0;
2436*5c51f124SMoriah Waterland 
2437*5c51f124SMoriah Waterland 	/* process any command line options */
2438*5c51f124SMoriah Waterland 
2439*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2440*5c51f124SMoriah Waterland 		switch (c) {
2441*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2442*5c51f124SMoriah Waterland 			break;
2443*5c51f124SMoriah Waterland 		case '?':
2444*5c51f124SMoriah Waterland 		default:
2445*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2446*5c51f124SMoriah Waterland 			return (R_USAGE);
2447*5c51f124SMoriah Waterland 		}
2448*5c51f124SMoriah Waterland 	}
2449*5c51f124SMoriah Waterland 
2450*5c51f124SMoriah Waterland 	/* prevent recursion */
2451*5c51f124SMoriah Waterland 
2452*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
2453*5c51f124SMoriah Waterland 		/*
2454*5c51f124SMoriah Waterland 		 * a boot environment cannot be any of the following
2455*5c51f124SMoriah Waterland 		 */
2456*5c51f124SMoriah Waterland 
2457*5c51f124SMoriah Waterland 		/* cannot be a diskless client */
2458*5c51f124SMoriah Waterland 
2459*5c51f124SMoriah Waterland 		r = cmd_is_diskless_client(argc, argv, a_gdt);
2460*5c51f124SMoriah Waterland 
2461*5c51f124SMoriah Waterland 		/* cannot be a netinstall_image */
2462*5c51f124SMoriah Waterland 
2463*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2464*5c51f124SMoriah Waterland 			r = cmd_is_netinstall_image(argc, argv, a_gdt);
2465*5c51f124SMoriah Waterland 		}
2466*5c51f124SMoriah Waterland 
2467*5c51f124SMoriah Waterland 		/* cannot be a mounted_miniroot */
2468*5c51f124SMoriah Waterland 
2469*5c51f124SMoriah Waterland 		if (r != R_SUCCESS) {
2470*5c51f124SMoriah Waterland 			r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
2471*5c51f124SMoriah Waterland 		}
2472*5c51f124SMoriah Waterland 
2473*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
2474*5c51f124SMoriah Waterland 
2475*5c51f124SMoriah Waterland 		recursion--;
2476*5c51f124SMoriah Waterland 
2477*5c51f124SMoriah Waterland 		/* return failure if any of the preceeding are true */
2478*5c51f124SMoriah Waterland 
2479*5c51f124SMoriah Waterland 		switch (r) {
2480*5c51f124SMoriah Waterland 			case R_SUCCESS:
2481*5c51f124SMoriah Waterland 				return (R_FAILURE);
2482*5c51f124SMoriah Waterland 			case R_FAILURE:
2483*5c51f124SMoriah Waterland 				break;
2484*5c51f124SMoriah Waterland 			case R_USAGE:
2485*5c51f124SMoriah Waterland 			case R_ERROR:
2486*5c51f124SMoriah Waterland 			default:
2487*5c51f124SMoriah Waterland 				return (r);
2488*5c51f124SMoriah Waterland 		}
2489*5c51f124SMoriah Waterland 	}
2490*5c51f124SMoriah Waterland 
2491*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2492*5c51f124SMoriah Waterland 
2493*5c51f124SMoriah Waterland 	argc -= optind;
2494*5c51f124SMoriah Waterland 	argv += optind;
2495*5c51f124SMoriah Waterland 
2496*5c51f124SMoriah Waterland 	/* error if more than one argument */
2497*5c51f124SMoriah Waterland 
2498*5c51f124SMoriah Waterland 	if (argc > 1) {
2499*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2500*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2501*5c51f124SMoriah Waterland 		return (R_USAGE);
2502*5c51f124SMoriah Waterland 	}
2503*5c51f124SMoriah Waterland 
2504*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2505*5c51f124SMoriah Waterland 
2506*5c51f124SMoriah Waterland 	if (argc == 1) {
2507*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2508*5c51f124SMoriah Waterland 			return (R_ERROR);
2509*5c51f124SMoriah Waterland 		}
2510*5c51f124SMoriah Waterland 	}
2511*5c51f124SMoriah Waterland 
2512*5c51f124SMoriah Waterland 	/* get current root path */
2513*5c51f124SMoriah Waterland 
2514*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2515*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2516*5c51f124SMoriah Waterland 		return (r);
2517*5c51f124SMoriah Waterland 	}
2518*5c51f124SMoriah Waterland 
2519*5c51f124SMoriah Waterland 	/* start of command debugging information */
2520*5c51f124SMoriah Waterland 
2521*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2522*5c51f124SMoriah Waterland 
2523*5c51f124SMoriah Waterland 	/* root path must not be "/" */
2524*5c51f124SMoriah Waterland 
2525*5c51f124SMoriah Waterland 	if (strcmp(rootPath, "/") == 0) {
2526*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_BAD_ROOTPATH, rootPath, "/");
2527*5c51f124SMoriah Waterland 		return (R_FAILURE);
2528*5c51f124SMoriah Waterland 	}
2529*5c51f124SMoriah Waterland 
2530*5c51f124SMoriah Waterland 	/* zone name must be global */
2531*5c51f124SMoriah Waterland 
2532*5c51f124SMoriah Waterland 	if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
2533*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_BAD_ZONE, rootPath,
2534*5c51f124SMoriah Waterland 			GLOBAL_ZONENAME);
2535*5c51f124SMoriah Waterland 		return (R_FAILURE);
2536*5c51f124SMoriah Waterland 	}
2537*5c51f124SMoriah Waterland 
2538*5c51f124SMoriah Waterland 	/* $ROOTDIR/etc/lutab must exist */
2539*5c51f124SMoriah Waterland 
2540*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS, "%s/%s", rootPath, "/etc/lutab");
2541*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2542*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_NO_ETCLUTAB, rootPath,
2543*5c51f124SMoriah Waterland 			"/etc/lutab");
2544*5c51f124SMoriah Waterland 		return (R_FAILURE);
2545*5c51f124SMoriah Waterland 	}
2546*5c51f124SMoriah Waterland 
2547*5c51f124SMoriah Waterland 	/* $ROOTDIR/etc/lu must exist */
2548*5c51f124SMoriah Waterland 
2549*5c51f124SMoriah Waterland 	r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
2550*5c51f124SMoriah Waterland 		"%s/%s", rootPath, "/etc/lu");
2551*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2552*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_NO_ETCLU, rootPath, "/etc/lu");
2553*5c51f124SMoriah Waterland 		return (R_FAILURE);
2554*5c51f124SMoriah Waterland 	}
2555*5c51f124SMoriah Waterland 
2556*5c51f124SMoriah Waterland 	/* must not be initial installation */
2557*5c51f124SMoriah Waterland 
2558*5c51f124SMoriah Waterland 	if ((a_gdt->gd_initialInstall == B_TRUE) &&
2559*5c51f124SMoriah Waterland 	    (strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
2560*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_INITIAL_INSTALL, rootPath);
2561*5c51f124SMoriah Waterland 		return (R_FAILURE);
2562*5c51f124SMoriah Waterland 	}
2563*5c51f124SMoriah Waterland 
2564*5c51f124SMoriah Waterland 	/* must not be installation of a zone */
2565*5c51f124SMoriah Waterland 
2566*5c51f124SMoriah Waterland 	if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
2567*5c51f124SMoriah Waterland 	    (a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
2568*5c51f124SMoriah Waterland 		/* initial zone install: no path can be boot environment */
2569*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_BENV_ZONE_INSTALL, rootPath);
2570*5c51f124SMoriah Waterland 		return (R_FAILURE);
2571*5c51f124SMoriah Waterland 	}
2572*5c51f124SMoriah Waterland 
2573*5c51f124SMoriah Waterland 	/* target is a boot environment */
2574*5c51f124SMoriah Waterland 
2575*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_BENV_IS, rootPath);
2576*5c51f124SMoriah Waterland 
2577*5c51f124SMoriah Waterland 	return (R_SUCCESS);
2578*5c51f124SMoriah Waterland }
2579*5c51f124SMoriah Waterland 
2580*5c51f124SMoriah Waterland /*
2581*5c51f124SMoriah Waterland  * Name:	cmd_is_sparse_root_ng_zone
2582*5c51f124SMoriah Waterland  * Description:	determine if target is a sparse non-global zone
2583*5c51f124SMoriah Waterland  * Scope:	public
2584*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2585*5c51f124SMoriah Waterland  *		  - optional path to target to test
2586*5c51f124SMoriah Waterland  * Returns:	int
2587*5c51f124SMoriah Waterland  *			== 0 - success
2588*5c51f124SMoriah Waterland  *			!= 0 - failure
2589*5c51f124SMoriah Waterland  * IMPLEMENATION:
2590*5c51f124SMoriah Waterland  *  - must be a non-global zone
2591*5c51f124SMoriah Waterland  *  - inherited file systems must be present, and/or
2592*5c51f124SMoriah Waterland  *  - read-only lofs file systems must be present
2593*5c51f124SMoriah Waterland  */
2594*5c51f124SMoriah Waterland 
2595*5c51f124SMoriah Waterland static int
2596*5c51f124SMoriah Waterland cmd_is_sparse_root_ng_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
2597*5c51f124SMoriah Waterland {
2598*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2599*5c51f124SMoriah Waterland 	int	c;
2600*5c51f124SMoriah Waterland 	int	r;
2601*5c51f124SMoriah Waterland static	char	*cmdName = "is_sparse_root_nonglobal_zone";
2602*5c51f124SMoriah Waterland static	int	recursion = 0;
2603*5c51f124SMoriah Waterland 
2604*5c51f124SMoriah Waterland 	/* process any command line options */
2605*5c51f124SMoriah Waterland 
2606*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2607*5c51f124SMoriah Waterland 		switch (c) {
2608*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2609*5c51f124SMoriah Waterland 			break;
2610*5c51f124SMoriah Waterland 		case '?':
2611*5c51f124SMoriah Waterland 		default:
2612*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2613*5c51f124SMoriah Waterland 			return (R_USAGE);
2614*5c51f124SMoriah Waterland 		}
2615*5c51f124SMoriah Waterland 	}
2616*5c51f124SMoriah Waterland 
2617*5c51f124SMoriah Waterland 	/* prevent recursion */
2618*5c51f124SMoriah Waterland 
2619*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
2620*5c51f124SMoriah Waterland 
2621*5c51f124SMoriah Waterland 		/* see if this is a non-global zone */
2622*5c51f124SMoriah Waterland 
2623*5c51f124SMoriah Waterland 		r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
2624*5c51f124SMoriah Waterland 
2625*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
2626*5c51f124SMoriah Waterland 
2627*5c51f124SMoriah Waterland 		recursion--;
2628*5c51f124SMoriah Waterland 
2629*5c51f124SMoriah Waterland 		switch (r) {
2630*5c51f124SMoriah Waterland 			case R_SUCCESS:
2631*5c51f124SMoriah Waterland 				/* is a non-global zone */
2632*5c51f124SMoriah Waterland 				break;
2633*5c51f124SMoriah Waterland 			case R_FAILURE:
2634*5c51f124SMoriah Waterland 				/* not a non-global zone */
2635*5c51f124SMoriah Waterland 				return (R_FAILURE);
2636*5c51f124SMoriah Waterland 			case R_USAGE:
2637*5c51f124SMoriah Waterland 			case R_ERROR:
2638*5c51f124SMoriah Waterland 			default:
2639*5c51f124SMoriah Waterland 				/* cannot determine if non-global zone */
2640*5c51f124SMoriah Waterland 				return (r);
2641*5c51f124SMoriah Waterland 		}
2642*5c51f124SMoriah Waterland 	}
2643*5c51f124SMoriah Waterland 
2644*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2645*5c51f124SMoriah Waterland 
2646*5c51f124SMoriah Waterland 	argc -= optind;
2647*5c51f124SMoriah Waterland 	argv += optind;
2648*5c51f124SMoriah Waterland 
2649*5c51f124SMoriah Waterland 	/* error if more than one argument */
2650*5c51f124SMoriah Waterland 
2651*5c51f124SMoriah Waterland 	if (argc > 1) {
2652*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2653*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2654*5c51f124SMoriah Waterland 		return (R_USAGE);
2655*5c51f124SMoriah Waterland 	}
2656*5c51f124SMoriah Waterland 
2657*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2658*5c51f124SMoriah Waterland 
2659*5c51f124SMoriah Waterland 	if (argc == 1) {
2660*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2661*5c51f124SMoriah Waterland 			return (R_ERROR);
2662*5c51f124SMoriah Waterland 		}
2663*5c51f124SMoriah Waterland 	}
2664*5c51f124SMoriah Waterland 
2665*5c51f124SMoriah Waterland 	/* get current root path */
2666*5c51f124SMoriah Waterland 
2667*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2668*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2669*5c51f124SMoriah Waterland 		return (r);
2670*5c51f124SMoriah Waterland 	}
2671*5c51f124SMoriah Waterland 
2672*5c51f124SMoriah Waterland 	/* start of command debugging information */
2673*5c51f124SMoriah Waterland 
2674*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2675*5c51f124SMoriah Waterland 
2676*5c51f124SMoriah Waterland 	/*
2677*5c51f124SMoriah Waterland 	 * in a non-global zone:
2678*5c51f124SMoriah Waterland 	 * if any file systems are inherited, or if /usr is read only,
2679*5c51f124SMoriah Waterland 	 * then the target is a sparse root non-global zone.
2680*5c51f124SMoriah Waterland 	 */
2681*5c51f124SMoriah Waterland 
2682*5c51f124SMoriah Waterland 	if ((a_gdt->gd_inheritedFileSystems != (char **)NULL) ||
2683*5c51f124SMoriah Waterland 		(a_gdt->gd_srFsMountedRO == B_TRUE)) {
2684*5c51f124SMoriah Waterland 		/* no inherited file systems */
2685*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_SRNG_IS, rootPath);
2686*5c51f124SMoriah Waterland 		return (R_SUCCESS);
2687*5c51f124SMoriah Waterland 	}
2688*5c51f124SMoriah Waterland 
2689*5c51f124SMoriah Waterland 	/* target is not a sparse root non-global zone */
2690*5c51f124SMoriah Waterland 
2691*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_SRNG_IS_NOT, rootPath);
2692*5c51f124SMoriah Waterland 
2693*5c51f124SMoriah Waterland 	return (R_FAILURE);
2694*5c51f124SMoriah Waterland 
2695*5c51f124SMoriah Waterland }
2696*5c51f124SMoriah Waterland 
2697*5c51f124SMoriah Waterland /*
2698*5c51f124SMoriah Waterland  * Name:	cmd_is_what
2699*5c51f124SMoriah Waterland  * Description:	determine what the target is
2700*5c51f124SMoriah Waterland  * Scope:	public
2701*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2702*5c51f124SMoriah Waterland  *		  - optional path to target to test
2703*5c51f124SMoriah Waterland  * Returns:	int
2704*5c51f124SMoriah Waterland  *			== 0 - success
2705*5c51f124SMoriah Waterland  *			!= 0 - failure
2706*5c51f124SMoriah Waterland  */
2707*5c51f124SMoriah Waterland 
2708*5c51f124SMoriah Waterland static int
2709*5c51f124SMoriah Waterland cmd_is_what(int argc, char **argv, GLOBALDATA_T *a_gdt)
2710*5c51f124SMoriah Waterland {
2711*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2712*5c51f124SMoriah Waterland 	int	c;
2713*5c51f124SMoriah Waterland 	int	cur_cmd;
2714*5c51f124SMoriah Waterland 	int	r;
2715*5c51f124SMoriah Waterland static	char	*cmdName = "is_what";
2716*5c51f124SMoriah Waterland 
2717*5c51f124SMoriah Waterland 	/* process any command line options */
2718*5c51f124SMoriah Waterland 
2719*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2720*5c51f124SMoriah Waterland 		switch (c) {
2721*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2722*5c51f124SMoriah Waterland 			break;
2723*5c51f124SMoriah Waterland 		case '?':
2724*5c51f124SMoriah Waterland 		default:
2725*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2726*5c51f124SMoriah Waterland 			return (R_USAGE);
2727*5c51f124SMoriah Waterland 		}
2728*5c51f124SMoriah Waterland 	}
2729*5c51f124SMoriah Waterland 
2730*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2731*5c51f124SMoriah Waterland 
2732*5c51f124SMoriah Waterland 	argc -= optind;
2733*5c51f124SMoriah Waterland 	argv += optind;
2734*5c51f124SMoriah Waterland 
2735*5c51f124SMoriah Waterland 	/* error if more than one argument */
2736*5c51f124SMoriah Waterland 
2737*5c51f124SMoriah Waterland 	if (argc > 1) {
2738*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2739*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2740*5c51f124SMoriah Waterland 		return (R_USAGE);
2741*5c51f124SMoriah Waterland 	}
2742*5c51f124SMoriah Waterland 
2743*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2744*5c51f124SMoriah Waterland 
2745*5c51f124SMoriah Waterland 	if (argc == 1) {
2746*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2747*5c51f124SMoriah Waterland 			return (R_ERROR);
2748*5c51f124SMoriah Waterland 		}
2749*5c51f124SMoriah Waterland 	}
2750*5c51f124SMoriah Waterland 
2751*5c51f124SMoriah Waterland 	/* get current root path */
2752*5c51f124SMoriah Waterland 
2753*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2754*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2755*5c51f124SMoriah Waterland 		return (r);
2756*5c51f124SMoriah Waterland 	}
2757*5c51f124SMoriah Waterland 
2758*5c51f124SMoriah Waterland 	/*
2759*5c51f124SMoriah Waterland 	 * construct the command line for all of the packages
2760*5c51f124SMoriah Waterland 	 */
2761*5c51f124SMoriah Waterland 
2762*5c51f124SMoriah Waterland 	argc = 0;
2763*5c51f124SMoriah Waterland 	argv[argc++] = strdup(get_prog_name());
2764*5c51f124SMoriah Waterland 	argv[argc++] = strdup(rootPath);
2765*5c51f124SMoriah Waterland 
2766*5c51f124SMoriah Waterland 	/* start of command debugging information */
2767*5c51f124SMoriah Waterland 
2768*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2769*5c51f124SMoriah Waterland 
2770*5c51f124SMoriah Waterland 	/* search for specified subcommand and execute if found */
2771*5c51f124SMoriah Waterland 
2772*5c51f124SMoriah Waterland 	for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
2773*5c51f124SMoriah Waterland 		int	result;
2774*5c51f124SMoriah Waterland 
2775*5c51f124SMoriah Waterland 		/* do not recursively call this function */
2776*5c51f124SMoriah Waterland 
2777*5c51f124SMoriah Waterland 		if (cmds[cur_cmd].c_func == cmd_is_what) {
2778*5c51f124SMoriah Waterland 			continue;
2779*5c51f124SMoriah Waterland 		}
2780*5c51f124SMoriah Waterland 
2781*5c51f124SMoriah Waterland 		/* call subcommand with its own argc/argv */
2782*5c51f124SMoriah Waterland 
2783*5c51f124SMoriah Waterland 		result = cmds[cur_cmd].c_func(argc, argv, a_gdt);
2784*5c51f124SMoriah Waterland 
2785*5c51f124SMoriah Waterland 		/* process result code and exit */
2786*5c51f124SMoriah Waterland 
2787*5c51f124SMoriah Waterland 		result = adjustResults(result);
2788*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_INFO, MSG_IS_WHAT_RESULT,
2789*5c51f124SMoriah Waterland 			cmds[cur_cmd].c_name, result);
2790*5c51f124SMoriah Waterland 	}
2791*5c51f124SMoriah Waterland 	return (R_SUCCESS);
2792*5c51f124SMoriah Waterland }
2793*5c51f124SMoriah Waterland 
2794*5c51f124SMoriah Waterland /*
2795*5c51f124SMoriah Waterland  * Name:	cmd_is_whole_root_ng_zone
2796*5c51f124SMoriah Waterland  * Description:	determine if target is a global zone
2797*5c51f124SMoriah Waterland  * Scope:	public
2798*5c51f124SMoriah Waterland  * Arguments:	argc,argv:
2799*5c51f124SMoriah Waterland  *		  - optional path to target to test
2800*5c51f124SMoriah Waterland  * Returns:	int
2801*5c51f124SMoriah Waterland  *			== 0 - success
2802*5c51f124SMoriah Waterland  *			!= 0 - failure
2803*5c51f124SMoriah Waterland  * IMPLEMENTATION:
2804*5c51f124SMoriah Waterland  *  - must be a non-global zone
2805*5c51f124SMoriah Waterland  *  - no inherited file systems may be present
2806*5c51f124SMoriah Waterland  *  - no read-only lofs file systems may be present
2807*5c51f124SMoriah Waterland  */
2808*5c51f124SMoriah Waterland 
2809*5c51f124SMoriah Waterland static int
2810*5c51f124SMoriah Waterland cmd_is_whole_root_ng_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
2811*5c51f124SMoriah Waterland {
2812*5c51f124SMoriah Waterland 	char	*rootPath = NULL;
2813*5c51f124SMoriah Waterland 	int	c;
2814*5c51f124SMoriah Waterland 	int	r;
2815*5c51f124SMoriah Waterland static	char	*cmdName = "is_whole_root_nonglobal_zone";
2816*5c51f124SMoriah Waterland static	int	recursion = 0;
2817*5c51f124SMoriah Waterland 
2818*5c51f124SMoriah Waterland 	/* process any command line options */
2819*5c51f124SMoriah Waterland 
2820*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, ":")) != EOF) {
2821*5c51f124SMoriah Waterland 		switch (c) {
2822*5c51f124SMoriah Waterland 		case '\0':	/* prevent end-of-loop not reached warning */
2823*5c51f124SMoriah Waterland 			break;
2824*5c51f124SMoriah Waterland 		case '?':
2825*5c51f124SMoriah Waterland 		default:
2826*5c51f124SMoriah Waterland 			(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
2827*5c51f124SMoriah Waterland 			return (R_USAGE);
2828*5c51f124SMoriah Waterland 		}
2829*5c51f124SMoriah Waterland 	}
2830*5c51f124SMoriah Waterland 
2831*5c51f124SMoriah Waterland 	/* prevent recursion */
2832*5c51f124SMoriah Waterland 
2833*5c51f124SMoriah Waterland 	if (recursionCheck(&recursion, cmdName) == B_FALSE) {
2834*5c51f124SMoriah Waterland 
2835*5c51f124SMoriah Waterland 		/* see if this is a non-global zone */
2836*5c51f124SMoriah Waterland 
2837*5c51f124SMoriah Waterland 		r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
2838*5c51f124SMoriah Waterland 
2839*5c51f124SMoriah Waterland 		/* no need to guard against recursion any more */
2840*5c51f124SMoriah Waterland 
2841*5c51f124SMoriah Waterland 		recursion--;
2842*5c51f124SMoriah Waterland 
2843*5c51f124SMoriah Waterland 		switch (r) {
2844*5c51f124SMoriah Waterland 			case R_SUCCESS:
2845*5c51f124SMoriah Waterland 				/* is a non-global zone */
2846*5c51f124SMoriah Waterland 				break;
2847*5c51f124SMoriah Waterland 			case R_FAILURE:
2848*5c51f124SMoriah Waterland 				/* not a non-global zone */
2849*5c51f124SMoriah Waterland 				return (R_FAILURE);
2850*5c51f124SMoriah Waterland 			case R_USAGE:
2851*5c51f124SMoriah Waterland 			case R_ERROR:
2852*5c51f124SMoriah Waterland 			default:
2853*5c51f124SMoriah Waterland 				/* cannot determine if non-global zone */
2854*5c51f124SMoriah Waterland 				return (r);
2855*5c51f124SMoriah Waterland 		}
2856*5c51f124SMoriah Waterland 	}
2857*5c51f124SMoriah Waterland 
2858*5c51f124SMoriah Waterland 	/* normalize argc/argv */
2859*5c51f124SMoriah Waterland 
2860*5c51f124SMoriah Waterland 	argc -= optind;
2861*5c51f124SMoriah Waterland 	argv += optind;
2862*5c51f124SMoriah Waterland 
2863*5c51f124SMoriah Waterland 	/* error if more than one argument */
2864*5c51f124SMoriah Waterland 
2865*5c51f124SMoriah Waterland 	if (argc > 1) {
2866*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
2867*5c51f124SMoriah Waterland 		(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
2868*5c51f124SMoriah Waterland 		return (R_USAGE);
2869*5c51f124SMoriah Waterland 	}
2870*5c51f124SMoriah Waterland 
2871*5c51f124SMoriah Waterland 	/* process root path if first argument present */
2872*5c51f124SMoriah Waterland 
2873*5c51f124SMoriah Waterland 	if (argc == 1) {
2874*5c51f124SMoriah Waterland 		if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
2875*5c51f124SMoriah Waterland 			return (R_ERROR);
2876*5c51f124SMoriah Waterland 		}
2877*5c51f124SMoriah Waterland 	}
2878*5c51f124SMoriah Waterland 
2879*5c51f124SMoriah Waterland 	/* get current root path */
2880*5c51f124SMoriah Waterland 
2881*5c51f124SMoriah Waterland 	r = getRootPath(&rootPath);
2882*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
2883*5c51f124SMoriah Waterland 		return (r);
2884*5c51f124SMoriah Waterland 	}
2885*5c51f124SMoriah Waterland 
2886*5c51f124SMoriah Waterland 	/* start of command debugging information */
2887*5c51f124SMoriah Waterland 
2888*5c51f124SMoriah Waterland 	echoDebug(DBG_ROOTPATH_IS, rootPath);
2889*5c51f124SMoriah Waterland 
2890*5c51f124SMoriah Waterland 	/*
2891*5c51f124SMoriah Waterland 	 * in a non-global zone:
2892*5c51f124SMoriah Waterland 	 * if no file systems are inherited, and if /usr is not
2893*5c51f124SMoriah Waterland 	 * read only, then the target is a whole root non-global zone.
2894*5c51f124SMoriah Waterland 	 */
2895*5c51f124SMoriah Waterland 
2896*5c51f124SMoriah Waterland 	if ((a_gdt->gd_inheritedFileSystems == (char **)NULL) &&
2897*5c51f124SMoriah Waterland 		(a_gdt->gd_srFsMountedRO == B_FALSE)) {
2898*5c51f124SMoriah Waterland 		/* no inherited file systems */
2899*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_WRNG_IS, rootPath);
2900*5c51f124SMoriah Waterland 		return (R_SUCCESS);
2901*5c51f124SMoriah Waterland 	}
2902*5c51f124SMoriah Waterland 
2903*5c51f124SMoriah Waterland 	/* target is not a whole-root non-global zone */
2904*5c51f124SMoriah Waterland 
2905*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_WRNG_IS_NOT, rootPath);
2906*5c51f124SMoriah Waterland 
2907*5c51f124SMoriah Waterland 	return (R_FAILURE);
2908*5c51f124SMoriah Waterland }
2909*5c51f124SMoriah Waterland 
2910*5c51f124SMoriah Waterland /*
2911*5c51f124SMoriah Waterland  * *****************************************************************************
2912*5c51f124SMoriah Waterland  * utility support functions
2913*5c51f124SMoriah Waterland  * *****************************************************************************
2914*5c51f124SMoriah Waterland  */
2915*5c51f124SMoriah Waterland 
2916*5c51f124SMoriah Waterland /*
2917*5c51f124SMoriah Waterland  * Name:	getMountOption
2918*5c51f124SMoriah Waterland  * Description:	return next mount option in a string
2919*5c51f124SMoriah Waterland  * Arguments:	p - pointer to string containing mount options
2920*5c51f124SMoriah Waterland  * Output:	none
2921*5c51f124SMoriah Waterland  * Returns:	char * - pointer to next option in string "p"
2922*5c51f124SMoriah Waterland  * Side Effects: advances input "p" and inserts \0 in place of the
2923*5c51f124SMoriah Waterland  *		option separator found.
2924*5c51f124SMoriah Waterland  */
2925*5c51f124SMoriah Waterland 
2926*5c51f124SMoriah Waterland static char *
2927*5c51f124SMoriah Waterland getMountOption(char **p)
2928*5c51f124SMoriah Waterland {
2929*5c51f124SMoriah Waterland 	char *cp = *p;
2930*5c51f124SMoriah Waterland 	char *retstr;
2931*5c51f124SMoriah Waterland 
2932*5c51f124SMoriah Waterland 	/* advance past all white space */
2933*5c51f124SMoriah Waterland 
2934*5c51f124SMoriah Waterland 	while (*cp && isspace(*cp))
2935*5c51f124SMoriah Waterland 		cp++;
2936*5c51f124SMoriah Waterland 
2937*5c51f124SMoriah Waterland 	/* remember start of next option */
2938*5c51f124SMoriah Waterland 
2939*5c51f124SMoriah Waterland 	retstr = cp;
2940*5c51f124SMoriah Waterland 
2941*5c51f124SMoriah Waterland 	/* advance to end of string or option separator */
2942*5c51f124SMoriah Waterland 
2943*5c51f124SMoriah Waterland 	while (*cp && *cp != ',')
2944*5c51f124SMoriah Waterland 		cp++;
2945*5c51f124SMoriah Waterland 
2946*5c51f124SMoriah Waterland 	/* replace separator with '\0' if not at end of string */
2947*5c51f124SMoriah Waterland 	if (*cp) {
2948*5c51f124SMoriah Waterland 		*cp = '\0';
2949*5c51f124SMoriah Waterland 		cp++;
2950*5c51f124SMoriah Waterland 	}
2951*5c51f124SMoriah Waterland 
2952*5c51f124SMoriah Waterland 	/* reset caller's pointer and return pointer to option */
2953*5c51f124SMoriah Waterland 
2954*5c51f124SMoriah Waterland 	*p = cp;
2955*5c51f124SMoriah Waterland 	return (retstr);
2956*5c51f124SMoriah Waterland }
2957*5c51f124SMoriah Waterland 
2958*5c51f124SMoriah Waterland /*
2959*5c51f124SMoriah Waterland  * Name:	mountOptionPresent
2960*5c51f124SMoriah Waterland  * Description:	determine if specified mount option is present in list
2961*5c51f124SMoriah Waterland  *		of mount point options
2962*5c51f124SMoriah Waterland  * Arguments:	a_mntOptions - pointer to string containing list of mount
2963*5c51f124SMoriah Waterland  *			point options to search
2964*5c51f124SMoriah Waterland  *		a_opt - pointer to string containing option to search for
2965*5c51f124SMoriah Waterland  * Output:	none
2966*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - option is present in list of mount point options
2967*5c51f124SMoriah Waterland  *		R_FAILURE - options is not present
2968*5c51f124SMoriah Waterland  *		R_ERROR - unable to determine if option is present or not
2969*5c51f124SMoriah Waterland  */
2970*5c51f124SMoriah Waterland 
2971*5c51f124SMoriah Waterland static int
2972*5c51f124SMoriah Waterland mountOptionPresent(char *a_mntOptions, char *a_opt)
2973*5c51f124SMoriah Waterland {
2974*5c51f124SMoriah Waterland 	char tmpopts[MNT_LINE_MAX];
2975*5c51f124SMoriah Waterland 	char *f, *opts = tmpopts;
2976*5c51f124SMoriah Waterland 
2977*5c51f124SMoriah Waterland 	/* return false if no mount options present */
2978*5c51f124SMoriah Waterland 
2979*5c51f124SMoriah Waterland 	if ((a_opt == NULL) || (*a_opt == '\0')) {
2980*5c51f124SMoriah Waterland 		return (R_FAILURE);
2981*5c51f124SMoriah Waterland 	}
2982*5c51f124SMoriah Waterland 
2983*5c51f124SMoriah Waterland 	/* return not present if no list of options to search */
2984*5c51f124SMoriah Waterland 
2985*5c51f124SMoriah Waterland 	if (a_mntOptions == NULL) {
2986*5c51f124SMoriah Waterland 		return (R_FAILURE);
2987*5c51f124SMoriah Waterland 	}
2988*5c51f124SMoriah Waterland 
2989*5c51f124SMoriah Waterland 	/* return not present if list of options to search is empty */
2990*5c51f124SMoriah Waterland 
2991*5c51f124SMoriah Waterland 	if (*a_mntOptions == '\0') {
2992*5c51f124SMoriah Waterland 		return (R_FAILURE);
2993*5c51f124SMoriah Waterland 	}
2994*5c51f124SMoriah Waterland 
2995*5c51f124SMoriah Waterland 	/* make local copy of option list to search */
2996*5c51f124SMoriah Waterland 
2997*5c51f124SMoriah Waterland 	(void) strcpy(opts, a_mntOptions);
2998*5c51f124SMoriah Waterland 
2999*5c51f124SMoriah Waterland 	/* scan each option looking for the specified option */
3000*5c51f124SMoriah Waterland 
3001*5c51f124SMoriah Waterland 	f = getMountOption(&opts);
3002*5c51f124SMoriah Waterland 	for (; *f; f = getMountOption(&opts)) {
3003*5c51f124SMoriah Waterland 		/* return success if option matches target */
3004*5c51f124SMoriah Waterland 		if (strncmp(a_opt, f, strlen(a_opt)) == 0) {
3005*5c51f124SMoriah Waterland 			return (R_SUCCESS);
3006*5c51f124SMoriah Waterland 		}
3007*5c51f124SMoriah Waterland 	}
3008*5c51f124SMoriah Waterland 
3009*5c51f124SMoriah Waterland 	/* option not found */
3010*5c51f124SMoriah Waterland 
3011*5c51f124SMoriah Waterland 	return (R_FAILURE);
3012*5c51f124SMoriah Waterland }
3013*5c51f124SMoriah Waterland 
3014*5c51f124SMoriah Waterland /*
3015*5c51f124SMoriah Waterland  * Name:	sortedInsert
3016*5c51f124SMoriah Waterland  * Description:	perform an alphabetical sorted insert into a list
3017*5c51f124SMoriah Waterland  * Arguments:	r_list - pointer to list to insert next entry into
3018*5c51f124SMoriah Waterland  *		a_listSize - pointer to current list size
3019*5c51f124SMoriah Waterland  *		a_mntPoint - mount point to insert (is sort key)
3020*5c51f124SMoriah Waterland  *		a_fsType - file system type for mount point
3021*5c51f124SMoriah Waterland  *		a_mntOptions - file syste mount options for mount point
3022*5c51f124SMoriah Waterland  * Output:	None
3023*5c51f124SMoriah Waterland  * Returns:	None
3024*5c51f124SMoriah Waterland  */
3025*5c51f124SMoriah Waterland 
3026*5c51f124SMoriah Waterland static void
3027*5c51f124SMoriah Waterland sortedInsert(FSI_T **r_list, long *a_listSize, char *a_mntPoint,
3028*5c51f124SMoriah Waterland 	char *a_fsType, char *a_mntOptions)
3029*5c51f124SMoriah Waterland {
3030*5c51f124SMoriah Waterland 	int	listSize;
3031*5c51f124SMoriah Waterland 	FSI_T	*list;
3032*5c51f124SMoriah Waterland 	int	n;
3033*5c51f124SMoriah Waterland 
3034*5c51f124SMoriah Waterland 	/* entry assertions */
3035*5c51f124SMoriah Waterland 
3036*5c51f124SMoriah Waterland 	assert(a_listSize != (long *)NULL);
3037*5c51f124SMoriah Waterland 	assert(a_mntPoint != NULL);
3038*5c51f124SMoriah Waterland 	assert(a_fsType != NULL);
3039*5c51f124SMoriah Waterland 	assert(a_mntOptions != NULL);
3040*5c51f124SMoriah Waterland 
3041*5c51f124SMoriah Waterland 	/* entry debugging info */
3042*5c51f124SMoriah Waterland 
3043*5c51f124SMoriah Waterland 	echoDebug(DBG_SINS_ENTRY, a_mntPoint, a_fsType, a_mntOptions);
3044*5c51f124SMoriah Waterland 
3045*5c51f124SMoriah Waterland 	/* localize references to the list and list size */
3046*5c51f124SMoriah Waterland 
3047*5c51f124SMoriah Waterland 	listSize = *a_listSize;
3048*5c51f124SMoriah Waterland 	list = *r_list;
3049*5c51f124SMoriah Waterland 
3050*5c51f124SMoriah Waterland 	/*
3051*5c51f124SMoriah Waterland 	 * if list empty insert this entry as the first one in the list
3052*5c51f124SMoriah Waterland 	 */
3053*5c51f124SMoriah Waterland 
3054*5c51f124SMoriah Waterland 	if (listSize == 0) {
3055*5c51f124SMoriah Waterland 		/* allocate new entry for list */
3056*5c51f124SMoriah Waterland 		listSize++;
3057*5c51f124SMoriah Waterland 		list = (FSI_T *)realloc(list, sizeof (FSI_T)*(listSize+1));
3058*5c51f124SMoriah Waterland 
3059*5c51f124SMoriah Waterland 		/* first entry is data passed to this function */
3060*5c51f124SMoriah Waterland 		list[0].fsi_mntPoint = strdup(a_mntPoint);
3061*5c51f124SMoriah Waterland 		list[0].fsi_fsType = strdup(a_fsType);
3062*5c51f124SMoriah Waterland 		list[0].fsi_mntOptions = strdup(a_mntOptions);
3063*5c51f124SMoriah Waterland 
3064*5c51f124SMoriah Waterland 		/* second entry is all NULL - end of entry marker */
3065*5c51f124SMoriah Waterland 		list[1].fsi_mntPoint = NULL;
3066*5c51f124SMoriah Waterland 		list[1].fsi_fsType = NULL;
3067*5c51f124SMoriah Waterland 		list[1].fsi_mntOptions = NULL;
3068*5c51f124SMoriah Waterland 
3069*5c51f124SMoriah Waterland 		/* restore list and list size references to caller */
3070*5c51f124SMoriah Waterland 		*a_listSize = listSize;
3071*5c51f124SMoriah Waterland 		*r_list = list;
3072*5c51f124SMoriah Waterland 
3073*5c51f124SMoriah Waterland 		return;
3074*5c51f124SMoriah Waterland 	}
3075*5c51f124SMoriah Waterland 
3076*5c51f124SMoriah Waterland 	/*
3077*5c51f124SMoriah Waterland 	 * list not empty - scan looking for largest match
3078*5c51f124SMoriah Waterland 	 */
3079*5c51f124SMoriah Waterland 
3080*5c51f124SMoriah Waterland 	for (n = 0; n < listSize; n++) {
3081*5c51f124SMoriah Waterland 		int	c;
3082*5c51f124SMoriah Waterland 
3083*5c51f124SMoriah Waterland 		/* compare target with current list entry */
3084*5c51f124SMoriah Waterland 
3085*5c51f124SMoriah Waterland 		c = strcmp(list[n].fsi_mntPoint, a_mntPoint);
3086*5c51f124SMoriah Waterland 
3087*5c51f124SMoriah Waterland 		if (c == 0) {
3088*5c51f124SMoriah Waterland 			char	*me;
3089*5c51f124SMoriah Waterland 			long	len;
3090*5c51f124SMoriah Waterland 
3091*5c51f124SMoriah Waterland 			/* entry already in list -- merge entries */
3092*5c51f124SMoriah Waterland 
3093*5c51f124SMoriah Waterland 			len = strlen(list[n].fsi_mntOptions) +
3094*5c51f124SMoriah Waterland 				strlen(a_mntOptions) + 2;
3095*5c51f124SMoriah Waterland 			me = (char *)calloc(1, len);
3096*5c51f124SMoriah Waterland 
3097*5c51f124SMoriah Waterland 			/* merge two mount options lists into one */
3098*5c51f124SMoriah Waterland 
3099*5c51f124SMoriah Waterland 			(void) strlcat(me, list[n].fsi_mntOptions, len);
3100*5c51f124SMoriah Waterland 			(void) strlcat(me, ",", len);
3101*5c51f124SMoriah Waterland 			(void) strlcat(me, a_mntOptions, len);
3102*5c51f124SMoriah Waterland 
3103*5c51f124SMoriah Waterland 			/* free old list, replace with merged one */
3104*5c51f124SMoriah Waterland 
3105*5c51f124SMoriah Waterland 			free(list[n].fsi_mntOptions);
3106*5c51f124SMoriah Waterland 			list[n].fsi_mntOptions = me;
3107*5c51f124SMoriah Waterland 
3108*5c51f124SMoriah Waterland 			echoDebug(DBG_SORTEDINS_SKIPPED,
3109*5c51f124SMoriah Waterland 				n, list[n].fsi_mntPoint, a_fsType,
3110*5c51f124SMoriah Waterland 				list[n].fsi_fsType, a_mntOptions,
3111*5c51f124SMoriah Waterland 				list[n].fsi_mntOptions);
3112*5c51f124SMoriah Waterland 
3113*5c51f124SMoriah Waterland 			continue;
3114*5c51f124SMoriah Waterland 		} else if (c < 0) {
3115*5c51f124SMoriah Waterland 			/* entry before this one - skip */
3116*5c51f124SMoriah Waterland 			continue;
3117*5c51f124SMoriah Waterland 		}
3118*5c51f124SMoriah Waterland 
3119*5c51f124SMoriah Waterland 		/*
3120*5c51f124SMoriah Waterland 		 * entry after this one - insert new entry
3121*5c51f124SMoriah Waterland 		 */
3122*5c51f124SMoriah Waterland 
3123*5c51f124SMoriah Waterland 		/* allocate one more entry and make space for new entry */
3124*5c51f124SMoriah Waterland 		listSize++;
3125*5c51f124SMoriah Waterland 		list = (FSI_T *)realloc(list,
3126*5c51f124SMoriah Waterland 			sizeof (FSI_T)*(listSize+1));
3127*5c51f124SMoriah Waterland 		(void) memmove(&(list[n+1]), &(list[n]),
3128*5c51f124SMoriah Waterland 			sizeof (FSI_T)*(listSize-n));
3129*5c51f124SMoriah Waterland 
3130*5c51f124SMoriah Waterland 		/* insert this entry into list */
3131*5c51f124SMoriah Waterland 		list[n].fsi_mntPoint = strdup(a_mntPoint);
3132*5c51f124SMoriah Waterland 		list[n].fsi_fsType = strdup(a_fsType);
3133*5c51f124SMoriah Waterland 		list[n].fsi_mntOptions = strdup(a_mntOptions);
3134*5c51f124SMoriah Waterland 
3135*5c51f124SMoriah Waterland 		/* restore list and list size references to caller */
3136*5c51f124SMoriah Waterland 		*a_listSize = listSize;
3137*5c51f124SMoriah Waterland 		*r_list = list;
3138*5c51f124SMoriah Waterland 
3139*5c51f124SMoriah Waterland 		return;
3140*5c51f124SMoriah Waterland 	}
3141*5c51f124SMoriah Waterland 
3142*5c51f124SMoriah Waterland 	/*
3143*5c51f124SMoriah Waterland 	 * all entries are before this one - append to end of list
3144*5c51f124SMoriah Waterland 	 */
3145*5c51f124SMoriah Waterland 
3146*5c51f124SMoriah Waterland 	/* allocate new entry at end of list */
3147*5c51f124SMoriah Waterland 	listSize++;
3148*5c51f124SMoriah Waterland 	list = (FSI_T *)realloc(list, sizeof (FSI_T)*(listSize+1));
3149*5c51f124SMoriah Waterland 
3150*5c51f124SMoriah Waterland 	/* append this entry to the end of the list */
3151*5c51f124SMoriah Waterland 	list[listSize-1].fsi_mntPoint = strdup(a_mntPoint);
3152*5c51f124SMoriah Waterland 	list[listSize-1].fsi_fsType = strdup(a_fsType);
3153*5c51f124SMoriah Waterland 	list[listSize-1].fsi_mntOptions = strdup(a_mntOptions);
3154*5c51f124SMoriah Waterland 
3155*5c51f124SMoriah Waterland 	/* restore list and list size references to caller */
3156*5c51f124SMoriah Waterland 	*a_listSize = listSize;
3157*5c51f124SMoriah Waterland 	*r_list = list;
3158*5c51f124SMoriah Waterland }
3159*5c51f124SMoriah Waterland 
3160*5c51f124SMoriah Waterland /*
3161*5c51f124SMoriah Waterland  * Name:	calculateFileSystemConfig
3162*5c51f124SMoriah Waterland  * Description:	generate sorted list of all mounted file systems
3163*5c51f124SMoriah Waterland  * Arguments:	a_gdt - global data structure to place sorted entries into
3164*5c51f124SMoriah Waterland  * Output:	None
3165*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - successfully generated mounted file systems list
3166*5c51f124SMoriah Waterland  *		R_FAILURE - options is not present
3167*5c51f124SMoriah Waterland  *		R_ERROR - unable to determine if option is present or not
3168*5c51f124SMoriah Waterland  */
3169*5c51f124SMoriah Waterland 
3170*5c51f124SMoriah Waterland static int
3171*5c51f124SMoriah Waterland calculateFileSystemConfig(GLOBALDATA_T *a_gdt)
3172*5c51f124SMoriah Waterland {
3173*5c51f124SMoriah Waterland 	FILE		*fp;
3174*5c51f124SMoriah Waterland 	struct mnttab	mntbuf;
3175*5c51f124SMoriah Waterland 	FSI_T		*list;
3176*5c51f124SMoriah Waterland 	long		listSize;
3177*5c51f124SMoriah Waterland 	boolean_t	readOnlyMountFound = B_FALSE;
3178*5c51f124SMoriah Waterland 
3179*5c51f124SMoriah Waterland 	/* entry assetions */
3180*5c51f124SMoriah Waterland 
3181*5c51f124SMoriah Waterland 	assert(a_gdt != (GLOBALDATA_T *)NULL);
3182*5c51f124SMoriah Waterland 
3183*5c51f124SMoriah Waterland 	/* entry debugging info */
3184*5c51f124SMoriah Waterland 
3185*5c51f124SMoriah Waterland 	echoDebug(DBG_CALCSCFG_ENTRY);
3186*5c51f124SMoriah Waterland 
3187*5c51f124SMoriah Waterland 	/* allocate a list that has one termination entry */
3188*5c51f124SMoriah Waterland 
3189*5c51f124SMoriah Waterland 	list = (FSI_T *)calloc(1, sizeof (FSI_T));
3190*5c51f124SMoriah Waterland 	list[0].fsi_mntPoint = NULL;
3191*5c51f124SMoriah Waterland 	list[0].fsi_fsType = NULL;
3192*5c51f124SMoriah Waterland 	list[0].fsi_mntOptions = NULL;
3193*5c51f124SMoriah Waterland 	listSize = 0;
3194*5c51f124SMoriah Waterland 
3195*5c51f124SMoriah Waterland 	/* insert entries for all inherited file systems */
3196*5c51f124SMoriah Waterland 
3197*5c51f124SMoriah Waterland 	if (a_gdt->gd_inheritedFileSystems) {
3198*5c51f124SMoriah Waterland 		int n;
3199*5c51f124SMoriah Waterland 		char **ifs = a_gdt->gd_inheritedFileSystems;
3200*5c51f124SMoriah Waterland 
3201*5c51f124SMoriah Waterland 		/* debugging info */
3202*5c51f124SMoriah Waterland 
3203*5c51f124SMoriah Waterland 		echoDebug(DBG_CALCSCFG_INHERITED);
3204*5c51f124SMoriah Waterland 
3205*5c51f124SMoriah Waterland 		/* insert all inherited file systems */
3206*5c51f124SMoriah Waterland 
3207*5c51f124SMoriah Waterland 		for (n = 0; ifs[n]; n++) {
3208*5c51f124SMoriah Waterland 			sortedInsert(&list, &listSize, ifs[n],
3209*5c51f124SMoriah Waterland 				FSTYPE_INHERITED, MNTOPT_RO);
3210*5c51f124SMoriah Waterland 		}
3211*5c51f124SMoriah Waterland 	}
3212*5c51f124SMoriah Waterland 
3213*5c51f124SMoriah Waterland 	/* open the mount table for reading */
3214*5c51f124SMoriah Waterland 
3215*5c51f124SMoriah Waterland 	fp = fopen(MNTTAB, "r");
3216*5c51f124SMoriah Waterland 	if (fp == (FILE *)NULL) {
3217*5c51f124SMoriah Waterland 		return (R_ERROR);
3218*5c51f124SMoriah Waterland 	}
3219*5c51f124SMoriah Waterland 
3220*5c51f124SMoriah Waterland 	/* debugging info */
3221*5c51f124SMoriah Waterland 
3222*5c51f124SMoriah Waterland 	echoDebug(DBG_CALCSCFG_MOUNTED);
3223*5c51f124SMoriah Waterland 
3224*5c51f124SMoriah Waterland 	/* go through all the specials looking for the device */
3225*5c51f124SMoriah Waterland 
3226*5c51f124SMoriah Waterland 	while (getmntent(fp, &mntbuf) == 0) {
3227*5c51f124SMoriah Waterland 		if (mntbuf.mnt_mountp[0] == '/') {
3228*5c51f124SMoriah Waterland 			sortedInsert(&list, &listSize,
3229*5c51f124SMoriah Waterland 			strdup(mntbuf.mnt_mountp),
3230*5c51f124SMoriah Waterland 			strdup(mntbuf.mnt_fstype),
3231*5c51f124SMoriah Waterland 			strdup(mntbuf.mnt_mntopts ? mntbuf.mnt_mntopts : ""));
3232*5c51f124SMoriah Waterland 		}
3233*5c51f124SMoriah Waterland 
3234*5c51f124SMoriah Waterland 		/*
3235*5c51f124SMoriah Waterland 		 * Set flag if we are in a non-global zone and it is in
3236*5c51f124SMoriah Waterland 		 * the mounted state.
3237*5c51f124SMoriah Waterland 		 */
3238*5c51f124SMoriah Waterland 
3239*5c51f124SMoriah Waterland 		if (strcmp(mntbuf.mnt_mountp, "/a") == 0 &&
3240*5c51f124SMoriah Waterland 			strcmp(mntbuf.mnt_special, "/a") == 0 &&
3241*5c51f124SMoriah Waterland 			strcmp(mntbuf.mnt_fstype, "lofs") == 0) {
3242*5c51f124SMoriah Waterland 			a_gdt->inMountedState = B_TRUE;
3243*5c51f124SMoriah Waterland 		}
3244*5c51f124SMoriah Waterland 
3245*5c51f124SMoriah Waterland 		if (!readOnlyMountFound) {
3246*5c51f124SMoriah Waterland 			readOnlyMountFound = checkForReadOnlyMount(a_gdt,
3247*5c51f124SMoriah Waterland 			    mntbuf.mnt_mountp, mntbuf.mnt_fstype,
3248*5c51f124SMoriah Waterland 			    mntbuf.mnt_mntopts);
3249*5c51f124SMoriah Waterland 		}
3250*5c51f124SMoriah Waterland 	}
3251*5c51f124SMoriah Waterland 
3252*5c51f124SMoriah Waterland 	/* close mount table file */
3253*5c51f124SMoriah Waterland 
3254*5c51f124SMoriah Waterland 	(void) fclose(fp);
3255*5c51f124SMoriah Waterland 
3256*5c51f124SMoriah Waterland 	/* store list pointers in global data structure */
3257*5c51f124SMoriah Waterland 
3258*5c51f124SMoriah Waterland 	a_gdt->gd_fileSystemConfig = list;
3259*5c51f124SMoriah Waterland 	a_gdt->gd_fileSystemConfigLen = listSize;
3260*5c51f124SMoriah Waterland 
3261*5c51f124SMoriah Waterland 	return (R_SUCCESS);
3262*5c51f124SMoriah Waterland }
3263*5c51f124SMoriah Waterland 
3264*5c51f124SMoriah Waterland /*
3265*5c51f124SMoriah Waterland  * Name:	checkForReadOnlyMount
3266*5c51f124SMoriah Waterland  * Description:	given a mount point, type and options, determine if the
3267*5c51f124SMoriah Waterland  *              mounted file system is part of a "sparse root" configuration
3268*5c51f124SMoriah Waterland  *              by checking if the known Zone directories a ro LOFS mounted.
3269*5c51f124SMoriah Waterland  * Arguments:	a_gdt - global data structure to place sorted entries into
3270*5c51f124SMoriah Waterland  *		a_mntPoint - pointer to string representing mount point
3271*5c51f124SMoriah Waterland  *		a_fsType - pointer to string representing file system type
3272*5c51f124SMoriah Waterland  *		a_mntOptions - pointer to string representing the options
3273*5c51f124SMoriah Waterland  *			used to mount the file system
3274*5c51f124SMoriah Waterland  * Returns:	B_TRUE - if sparse root mount is found
3275*5c51f124SMoriah Waterland  * 		B_FLASE - if no sparse root mount's are found
3276*5c51f124SMoriah Waterland  * Side Effects: set:
3277*5c51f124SMoriah Waterland  *			a_gdt->gd_srFsMountedRO = B_TRUE
3278*5c51f124SMoriah Waterland  *		if the mounted file system is part of a 'sparse root' config
3279*5c51f124SMoriah Waterland  */
3280*5c51f124SMoriah Waterland 
3281*5c51f124SMoriah Waterland static boolean_t
3282*5c51f124SMoriah Waterland checkForReadOnlyMount(GLOBALDATA_T *a_gdt, char *a_mntPoint,
3283*5c51f124SMoriah Waterland 	char *a_fsType, char *a_mntOptions)
3284*5c51f124SMoriah Waterland {
3285*5c51f124SMoriah Waterland 	/* entry assertions */
3286*5c51f124SMoriah Waterland 	int	i;
3287*5c51f124SMoriah Waterland 	char mntPoint[MAXPATHLEN];
3288*5c51f124SMoriah Waterland 	char *zDirs[] = { "/usr", "/lib", "/platform", "/sbin", NULL };
3289*5c51f124SMoriah Waterland 	char *aZDirs[] = { "/a/usr", "/a/lib", "/a/platform", "/a/sbin", NULL };
3290*5c51f124SMoriah Waterland 
3291*5c51f124SMoriah Waterland 	assert(a_gdt != (GLOBALDATA_T *)NULL);
3292*5c51f124SMoriah Waterland 	assert(a_mntPoint != NULL);
3293*5c51f124SMoriah Waterland 	assert(a_fsType != NULL);
3294*5c51f124SMoriah Waterland 
3295*5c51f124SMoriah Waterland 	/* return if no read-only mount option */
3296*5c51f124SMoriah Waterland 
3297*5c51f124SMoriah Waterland 	if (mountOptionPresent(a_mntOptions, MNTOPT_RO) != R_SUCCESS) {
3298*5c51f124SMoriah Waterland 		return (B_FALSE);
3299*5c51f124SMoriah Waterland 	}
3300*5c51f124SMoriah Waterland 
3301*5c51f124SMoriah Waterland 	/* return if file system is not read-only mounted */
3302*5c51f124SMoriah Waterland 
3303*5c51f124SMoriah Waterland 	if (strcmp(a_fsType, MNTTYPE_LOFS) != 0) {
3304*5c51f124SMoriah Waterland 		return (B_FALSE);
3305*5c51f124SMoriah Waterland 	}
3306*5c51f124SMoriah Waterland 
3307*5c51f124SMoriah Waterland 	/* file system is a read-only lofs mounted.  */
3308*5c51f124SMoriah Waterland 
3309*5c51f124SMoriah Waterland 	/* Check read-only lofs mount's appended to the command line path */
3310*5c51f124SMoriah Waterland 
3311*5c51f124SMoriah Waterland 	if (a_gdt->gd_cmdline_path != NULL) {
3312*5c51f124SMoriah Waterland 		if (strncmp(a_mntPoint, a_gdt->gd_cmdline_path,
3313*5c51f124SMoriah Waterland 			strlen(a_gdt->gd_cmdline_path)) == 0) {
3314*5c51f124SMoriah Waterland 			for (i = 0; zDirs[i] != NULL; i++) {
3315*5c51f124SMoriah Waterland 				(void) snprintf(mntPoint, sizeof (mntPoint),
3316*5c51f124SMoriah Waterland 				    "%s%s", a_gdt->gd_cmdline_path,
3317*5c51f124SMoriah Waterland 				    zDirs[i]);
3318*5c51f124SMoriah Waterland 				if (strcmp(a_mntPoint, mntPoint) == 0) {
3319*5c51f124SMoriah Waterland 					echoDebug(DBG_CKSR_FSREADONLY,
3320*5c51f124SMoriah Waterland 					    a_mntPoint, a_fsType);
3321*5c51f124SMoriah Waterland 					a_gdt->gd_srFsMountedRO = B_TRUE;
3322*5c51f124SMoriah Waterland 					return (B_TRUE);
3323*5c51f124SMoriah Waterland 				}
3324*5c51f124SMoriah Waterland 			}
3325*5c51f124SMoriah Waterland 		}
3326*5c51f124SMoriah Waterland 
3327*5c51f124SMoriah Waterland 	/* Check read-only lofs mount's in the mounted state */
3328*5c51f124SMoriah Waterland 
3329*5c51f124SMoriah Waterland 	} else if (a_gdt->inMountedState) {
3330*5c51f124SMoriah Waterland 		for (i = 0; aZDirs[i] != NULL; i++) {
3331*5c51f124SMoriah Waterland 			if (strncmp(a_mntPoint, aZDirs[i],
3332*5c51f124SMoriah Waterland 			    sizeof (aZDirs[i])) == 0) {
3333*5c51f124SMoriah Waterland 				echoDebug(DBG_CKSR_FSREADONLY, a_mntPoint,
3334*5c51f124SMoriah Waterland 				    a_fsType);
3335*5c51f124SMoriah Waterland 				a_gdt->gd_srFsMountedRO = B_TRUE;
3336*5c51f124SMoriah Waterland 				return (B_TRUE);
3337*5c51f124SMoriah Waterland 			}
3338*5c51f124SMoriah Waterland 		}
3339*5c51f124SMoriah Waterland 
3340*5c51f124SMoriah Waterland 	/* Check read-only lofs mount's for live system */
3341*5c51f124SMoriah Waterland 
3342*5c51f124SMoriah Waterland 	} else {
3343*5c51f124SMoriah Waterland 		for (i = 0; zDirs[i] != NULL; i++) {
3344*5c51f124SMoriah Waterland 			if (strncmp(a_mntPoint, zDirs[i],
3345*5c51f124SMoriah Waterland 			    sizeof (zDirs[i])) == 0) {
3346*5c51f124SMoriah Waterland 				echoDebug(DBG_CKSR_FSREADONLY, a_mntPoint,
3347*5c51f124SMoriah Waterland 				    a_fsType);
3348*5c51f124SMoriah Waterland 				a_gdt->gd_srFsMountedRO = B_TRUE;
3349*5c51f124SMoriah Waterland 				return (B_TRUE);
3350*5c51f124SMoriah Waterland 			}
3351*5c51f124SMoriah Waterland 		}
3352*5c51f124SMoriah Waterland 	}
3353*5c51f124SMoriah Waterland 
3354*5c51f124SMoriah Waterland 	return (B_FALSE);
3355*5c51f124SMoriah Waterland }
3356*5c51f124SMoriah Waterland 
3357*5c51f124SMoriah Waterland /*
3358*5c51f124SMoriah Waterland  * Name: 	adjustResults
3359*5c51f124SMoriah Waterland  * Description:	adjust output result code before existing
3360*5c51f124SMoriah Waterland  * Arguments:	a_result - result code to adjust
3361*5c51f124SMoriah Waterland  * Returns:	int - adjusted result code
3362*5c51f124SMoriah Waterland  */
3363*5c51f124SMoriah Waterland 
3364*5c51f124SMoriah Waterland static int
3365*5c51f124SMoriah Waterland adjustResults(int a_result)
3366*5c51f124SMoriah Waterland {
3367*5c51f124SMoriah Waterland 	boolean_t	negate = getNegateResults();
3368*5c51f124SMoriah Waterland 	int		realResult;
3369*5c51f124SMoriah Waterland 
3370*5c51f124SMoriah Waterland 	/* adjust code as appropriate */
3371*5c51f124SMoriah Waterland 
3372*5c51f124SMoriah Waterland 	switch (a_result) {
3373*5c51f124SMoriah Waterland 	case R_SUCCESS:		/* condition satisfied */
3374*5c51f124SMoriah Waterland 		realResult = ((negate == B_TRUE) ? 1 : 0);
3375*5c51f124SMoriah Waterland 		break;
3376*5c51f124SMoriah Waterland 	case R_FAILURE:		/* condition not satisfied */
3377*5c51f124SMoriah Waterland 		realResult = ((negate == B_TRUE) ? 0 : 1);
3378*5c51f124SMoriah Waterland 		break;
3379*5c51f124SMoriah Waterland 	case R_USAGE:		/* usage errors */
3380*5c51f124SMoriah Waterland 		realResult = 2;
3381*5c51f124SMoriah Waterland 		break;
3382*5c51f124SMoriah Waterland 	case R_ERROR:		/* condition could not be determined */
3383*5c51f124SMoriah Waterland 	default:
3384*5c51f124SMoriah Waterland 		realResult = 3;
3385*5c51f124SMoriah Waterland 		break;
3386*5c51f124SMoriah Waterland 	}
3387*5c51f124SMoriah Waterland 
3388*5c51f124SMoriah Waterland 	/* debugging output */
3389*5c51f124SMoriah Waterland 
3390*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_ADJUST_RESULTS, a_result, negate,
3391*5c51f124SMoriah Waterland 		realResult);
3392*5c51f124SMoriah Waterland 
3393*5c51f124SMoriah Waterland 	/* return results */
3394*5c51f124SMoriah Waterland 
3395*5c51f124SMoriah Waterland 	return (realResult);
3396*5c51f124SMoriah Waterland }
3397*5c51f124SMoriah Waterland 
3398*5c51f124SMoriah Waterland /*
3399*5c51f124SMoriah Waterland  * Name:        setCmdLinePath
3400*5c51f124SMoriah Waterland  * Description:	set global command line path
3401*5c51f124SMoriah Waterland  * Arguments:   path - path to set from the command line
3402*5c51f124SMoriah Waterland  *              args - command line args
3403*5c51f124SMoriah Waterland  *              num_args - number of command line args
3404*5c51f124SMoriah Waterland  * Returns:     R_SUCCESS - root path successfully set
3405*5c51f124SMoriah Waterland  *              R_FAILURE - root path could not be set
3406*5c51f124SMoriah Waterland  *              R_ERROR - fatal error attempting to set root path
3407*5c51f124SMoriah Waterland  */
3408*5c51f124SMoriah Waterland 
3409*5c51f124SMoriah Waterland static void
3410*5c51f124SMoriah Waterland setCmdLinePath(char **path, char **args, int num_args)
3411*5c51f124SMoriah Waterland {
3412*5c51f124SMoriah Waterland 	char   rp[PATH_MAX] = { '\0' };
3413*5c51f124SMoriah Waterland 	struct stat statbuf;
3414*5c51f124SMoriah Waterland 
3415*5c51f124SMoriah Waterland 	if (*path != NULL) {
3416*5c51f124SMoriah Waterland 		return;
3417*5c51f124SMoriah Waterland 	}
3418*5c51f124SMoriah Waterland 
3419*5c51f124SMoriah Waterland 	/*
3420*5c51f124SMoriah Waterland 	 * If a path "pkgcond is_global_zone [path]" is provided on the
3421*5c51f124SMoriah Waterland 	 * command line it must be the last argument.
3422*5c51f124SMoriah Waterland 	 */
3423*5c51f124SMoriah Waterland 
3424*5c51f124SMoriah Waterland 	if (realpath(args[num_args - 1], rp) != NULL) {
3425*5c51f124SMoriah Waterland 		if (stat(rp, &statbuf) == 0) {
3426*5c51f124SMoriah Waterland 			/* make sure the target is a directory */
3427*5c51f124SMoriah Waterland 			if ((statbuf.st_mode & S_IFDIR)) {
3428*5c51f124SMoriah Waterland 				*path = strdup(rp);
3429*5c51f124SMoriah Waterland 			} else {
3430*5c51f124SMoriah Waterland 				*path = NULL;
3431*5c51f124SMoriah Waterland 			}
3432*5c51f124SMoriah Waterland 		}
3433*5c51f124SMoriah Waterland 	}
3434*5c51f124SMoriah Waterland }
3435*5c51f124SMoriah Waterland 
3436*5c51f124SMoriah Waterland /*
3437*5c51f124SMoriah Waterland  * Name:	setRootPath
3438*5c51f124SMoriah Waterland  * Description:	set global root path returned by getRootPath
3439*5c51f124SMoriah Waterland  * Arguments:	a_path - root path to set
3440*5c51f124SMoriah Waterland  *		a_mustExist - B_TRUE if path must exist (else error)
3441*5c51f124SMoriah Waterland  *			- B_FALSE if path may not exist
3442*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - root path successfully set
3443*5c51f124SMoriah Waterland  *		R_FAILURE - root path could not be set
3444*5c51f124SMoriah Waterland  *		R_ERROR - fatal error attempting to set root path
3445*5c51f124SMoriah Waterland  */
3446*5c51f124SMoriah Waterland 
3447*5c51f124SMoriah Waterland static int
3448*5c51f124SMoriah Waterland setRootPath(char *a_path, char *a_envVar, boolean_t a_mustExist)
3449*5c51f124SMoriah Waterland {
3450*5c51f124SMoriah Waterland 	char		rp[PATH_MAX] = { '\0' };
3451*5c51f124SMoriah Waterland 	struct stat	statbuf;
3452*5c51f124SMoriah Waterland 
3453*5c51f124SMoriah Waterland 	/* if no data then issue warning and return success */
3454*5c51f124SMoriah Waterland 
3455*5c51f124SMoriah Waterland 	if ((a_path == NULL) || (*a_path == '\0')) {
3456*5c51f124SMoriah Waterland 		echoDebug(DBG_NO_DEFAULT_ROOT_PATH_SET);
3457*5c51f124SMoriah Waterland 		return (R_SUCCESS);
3458*5c51f124SMoriah Waterland 	}
3459*5c51f124SMoriah Waterland 
3460*5c51f124SMoriah Waterland 	/* path present - resolve to absolute path */
3461*5c51f124SMoriah Waterland 
3462*5c51f124SMoriah Waterland 	if (realpath(a_path, rp) == NULL) {
3463*5c51f124SMoriah Waterland 		if (a_mustExist == B_TRUE) {
3464*5c51f124SMoriah Waterland 			/* must exist ... error */
3465*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_INVALID,
3466*5c51f124SMoriah Waterland 				a_path, strerror(errno));
3467*5c51f124SMoriah Waterland 			return (R_ERROR);
3468*5c51f124SMoriah Waterland 		} else {
3469*5c51f124SMoriah Waterland 			/* may not exist - use path as specified */
3470*5c51f124SMoriah Waterland 			(void) strcpy(rp, a_path);
3471*5c51f124SMoriah Waterland 		}
3472*5c51f124SMoriah Waterland 	}
3473*5c51f124SMoriah Waterland 
3474*5c51f124SMoriah Waterland 	/* debugging output */
3475*5c51f124SMoriah Waterland 
3476*5c51f124SMoriah Waterland 	echoDebug(DBG_DEFAULT_ROOT_PATH_SET, rp, a_envVar ? a_envVar : "");
3477*5c51f124SMoriah Waterland 
3478*5c51f124SMoriah Waterland 	/* validate path existence if it must exist */
3479*5c51f124SMoriah Waterland 
3480*5c51f124SMoriah Waterland 	if (a_mustExist == B_TRUE) {
3481*5c51f124SMoriah Waterland 
3482*5c51f124SMoriah Waterland 		/* get node status */
3483*5c51f124SMoriah Waterland 
3484*5c51f124SMoriah Waterland 		if (stat(rp, &statbuf) != 0) {
3485*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_INVALID,
3486*5c51f124SMoriah Waterland 				rp, strerror(errno));
3487*5c51f124SMoriah Waterland 			return (R_ERROR);
3488*5c51f124SMoriah Waterland 		}
3489*5c51f124SMoriah Waterland 
3490*5c51f124SMoriah Waterland 		/* make sure the target is a directory */
3491*5c51f124SMoriah Waterland 
3492*5c51f124SMoriah Waterland 		if (!(statbuf.st_mode & S_IFDIR)) {
3493*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_NOT_DIR, rp);
3494*5c51f124SMoriah Waterland 			return (R_ERROR);
3495*5c51f124SMoriah Waterland 		}
3496*5c51f124SMoriah Waterland 	}
3497*5c51f124SMoriah Waterland 
3498*5c51f124SMoriah Waterland 	/* target exists and is a directory - set */
3499*5c51f124SMoriah Waterland 
3500*5c51f124SMoriah Waterland 	echoDebug(DBG_SET_ROOT_PATH_TO, rp);
3501*5c51f124SMoriah Waterland 
3502*5c51f124SMoriah Waterland 	/* store copy of resolved root path */
3503*5c51f124SMoriah Waterland 
3504*5c51f124SMoriah Waterland 	_rootPath = strdup(rp);
3505*5c51f124SMoriah Waterland 
3506*5c51f124SMoriah Waterland 	/* success! */
3507*5c51f124SMoriah Waterland 
3508*5c51f124SMoriah Waterland 	return (R_SUCCESS);
3509*5c51f124SMoriah Waterland }
3510*5c51f124SMoriah Waterland 
3511*5c51f124SMoriah Waterland /*
3512*5c51f124SMoriah Waterland  * Name:	testPath
3513*5c51f124SMoriah Waterland  * Description:	determine if a path meets the specified conditions
3514*5c51f124SMoriah Waterland  * Arguments:	a_tt - conditions to test path against
3515*5c51f124SMoriah Waterland  * 		a_format - format to use to generate path
3516*5c51f124SMoriah Waterland  *		arguments following a_format - as needed for a_format
3517*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - the path meets all of the specified conditions
3518*5c51f124SMoriah Waterland  *		R_FAILURE - the path does not meet all of the conditions
3519*5c51f124SMoriah Waterland  *		R_ERROR - error attempting to test path
3520*5c51f124SMoriah Waterland  */
3521*5c51f124SMoriah Waterland 
3522*5c51f124SMoriah Waterland /*PRINTFLIKE2*/
3523*5c51f124SMoriah Waterland static int
3524*5c51f124SMoriah Waterland testPath(TEST_TYPES a_tt, char *a_format, ...)
3525*5c51f124SMoriah Waterland {
3526*5c51f124SMoriah Waterland 	char		*mbPath;	/* copy for the path to be returned */
3527*5c51f124SMoriah Waterland 	char		bfr[1];
3528*5c51f124SMoriah Waterland 	int		r;
3529*5c51f124SMoriah Waterland 	size_t		vres = 0;
3530*5c51f124SMoriah Waterland 	struct stat	statbuf;
3531*5c51f124SMoriah Waterland 	va_list		ap;
3532*5c51f124SMoriah Waterland 	int		fd;
3533*5c51f124SMoriah Waterland 
3534*5c51f124SMoriah Waterland 	/* entry assertions */
3535*5c51f124SMoriah Waterland 
3536*5c51f124SMoriah Waterland 	assert(a_format != NULL);
3537*5c51f124SMoriah Waterland 	assert(*a_format != '\0');
3538*5c51f124SMoriah Waterland 
3539*5c51f124SMoriah Waterland 	/* determine size of the message in bytes */
3540*5c51f124SMoriah Waterland 
3541*5c51f124SMoriah Waterland 	va_start(ap, a_format);
3542*5c51f124SMoriah Waterland 	vres = vsnprintf(bfr, 1, a_format, ap);
3543*5c51f124SMoriah Waterland 	va_end(ap);
3544*5c51f124SMoriah Waterland 
3545*5c51f124SMoriah Waterland 	assert(vres > 0);
3546*5c51f124SMoriah Waterland 
3547*5c51f124SMoriah Waterland 	/* allocate storage to hold the message */
3548*5c51f124SMoriah Waterland 
3549*5c51f124SMoriah Waterland 	mbPath = (char *)calloc(1, vres+2);
3550*5c51f124SMoriah Waterland 	assert(mbPath != NULL);
3551*5c51f124SMoriah Waterland 
3552*5c51f124SMoriah Waterland 	/* generate the results of the printf conversion */
3553*5c51f124SMoriah Waterland 
3554*5c51f124SMoriah Waterland 	va_start(ap, a_format);
3555*5c51f124SMoriah Waterland 	vres = vsnprintf(mbPath, vres+1, a_format, ap);
3556*5c51f124SMoriah Waterland 	va_end(ap);
3557*5c51f124SMoriah Waterland 
3558*5c51f124SMoriah Waterland 	assert(vres > 0);
3559*5c51f124SMoriah Waterland 
3560*5c51f124SMoriah Waterland 	echoDebug(DBG_TEST_PATH, mbPath, (unsigned long)a_tt);
3561*5c51f124SMoriah Waterland 
3562*5c51f124SMoriah Waterland 	/*
3563*5c51f124SMoriah Waterland 	 * When a path given to open(2) contains symbolic links, the
3564*5c51f124SMoriah Waterland 	 * open system call first resolves all symbolic links and then
3565*5c51f124SMoriah Waterland 	 * opens that final "resolved" path. As a result, it is not
3566*5c51f124SMoriah Waterland 	 * possible to check the result of an fstat(2) against the
3567*5c51f124SMoriah Waterland 	 * file descriptor returned by open(2) for S_IFLNK (a symbolic
3568*5c51f124SMoriah Waterland 	 * link) since all symbolic links are resolved before the
3569*5c51f124SMoriah Waterland 	 * target is opened.
3570*5c51f124SMoriah Waterland 	 *
3571*5c51f124SMoriah Waterland 	 * When testing the target as being (or not being) a symbolic
3572*5c51f124SMoriah Waterland 	 * link, first use lstat(2) against the target to determine
3573*5c51f124SMoriah Waterland 	 * whether or not the specified target itself is (or is not) a
3574*5c51f124SMoriah Waterland 	 * symbolic link.
3575*5c51f124SMoriah Waterland 	 */
3576*5c51f124SMoriah Waterland 
3577*5c51f124SMoriah Waterland 	if (a_tt & (TEST_IS_SYMBOLIC_LINK|TEST_NOT_SYMBOLIC_LINK)) {
3578*5c51f124SMoriah Waterland 		/*
3579*5c51f124SMoriah Waterland 		 * testing target is/is not a symbolic link; use lstat
3580*5c51f124SMoriah Waterland 		 * to determine the status of the target itself rather
3581*5c51f124SMoriah Waterland 		 * than what the target might finally address.
3582*5c51f124SMoriah Waterland 		 */
3583*5c51f124SMoriah Waterland 
3584*5c51f124SMoriah Waterland 		if (lstat(mbPath, &statbuf) != 0) {
3585*5c51f124SMoriah Waterland 			echoDebug(DBG_CANNOT_LSTAT_PATH, mbPath,
3586*5c51f124SMoriah Waterland 				strerror(errno));
3587*5c51f124SMoriah Waterland 			free(mbPath);
3588*5c51f124SMoriah Waterland 			return (R_FAILURE);
3589*5c51f124SMoriah Waterland 		}
3590*5c51f124SMoriah Waterland 
3591*5c51f124SMoriah Waterland 		/* Is the target required to be a symbolic link? */
3592*5c51f124SMoriah Waterland 
3593*5c51f124SMoriah Waterland 		if (a_tt & TEST_IS_SYMBOLIC_LINK) {
3594*5c51f124SMoriah Waterland 			/* target must be a symbolic link */
3595*5c51f124SMoriah Waterland 			if (!(statbuf.st_mode & S_IFLNK)) {
3596*5c51f124SMoriah Waterland 				/* failure: target is not a symbolic link */
3597*5c51f124SMoriah Waterland 				echoDebug(DBG_IS_NOT_A_SYMLINK, mbPath);
3598*5c51f124SMoriah Waterland 				free(mbPath);
3599*5c51f124SMoriah Waterland 				return (R_FAILURE);
3600*5c51f124SMoriah Waterland 			}
3601*5c51f124SMoriah Waterland 			/* success: target is a symbolic link */
3602*5c51f124SMoriah Waterland 			echoDebug(DBG_SYMLINK_IS, mbPath);
3603*5c51f124SMoriah Waterland 		}
3604*5c51f124SMoriah Waterland 
3605*5c51f124SMoriah Waterland 		/* Is the target required to not be a symbolic link? */
3606*5c51f124SMoriah Waterland 
3607*5c51f124SMoriah Waterland 		if (a_tt & TEST_NOT_SYMBOLIC_LINK) {
3608*5c51f124SMoriah Waterland 			/* target must not be a symbolic link */
3609*5c51f124SMoriah Waterland 			if (statbuf.st_mode & S_IFLNK) {
3610*5c51f124SMoriah Waterland 				/* failure: target is a symbolic link */
3611*5c51f124SMoriah Waterland 				echoDebug(DBG_IS_A_SYMLINK, mbPath);
3612*5c51f124SMoriah Waterland 				free(mbPath);
3613*5c51f124SMoriah Waterland 				return (R_FAILURE);
3614*5c51f124SMoriah Waterland 			}
3615*5c51f124SMoriah Waterland 			/* success: target is not a symbolic link */
3616*5c51f124SMoriah Waterland 			echoDebug(DBG_SYMLINK_NOT, mbPath);
3617*5c51f124SMoriah Waterland 		}
3618*5c51f124SMoriah Waterland 
3619*5c51f124SMoriah Waterland 		/*
3620*5c51f124SMoriah Waterland 		 * if only testing is/is not a symbolic link, then
3621*5c51f124SMoriah Waterland 		 * no need to open the target: return success.
3622*5c51f124SMoriah Waterland 		 */
3623*5c51f124SMoriah Waterland 
3624*5c51f124SMoriah Waterland 		if (!(a_tt &
3625*5c51f124SMoriah Waterland 		    (~(TEST_IS_SYMBOLIC_LINK|TEST_NOT_SYMBOLIC_LINK)))) {
3626*5c51f124SMoriah Waterland 			free(mbPath);
3627*5c51f124SMoriah Waterland 			return (R_SUCCESS);
3628*5c51f124SMoriah Waterland 		}
3629*5c51f124SMoriah Waterland 	}
3630*5c51f124SMoriah Waterland 
3631*5c51f124SMoriah Waterland 	/* resolve path and remove any whitespace */
3632*5c51f124SMoriah Waterland 
3633*5c51f124SMoriah Waterland 	r = resolvePath(&mbPath);
3634*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
3635*5c51f124SMoriah Waterland 		echoDebug(DBG_TEST_PATH_NO_RESOLVE, mbPath);
3636*5c51f124SMoriah Waterland 		free(mbPath);
3637*5c51f124SMoriah Waterland 		if (a_tt & TEST_NOT_EXISTS) {
3638*5c51f124SMoriah Waterland 			return (R_SUCCESS);
3639*5c51f124SMoriah Waterland 		}
3640*5c51f124SMoriah Waterland 		return (r);
3641*5c51f124SMoriah Waterland 	}
3642*5c51f124SMoriah Waterland 
3643*5c51f124SMoriah Waterland 	echoDebug(DBG_TEST_PATH_RESOLVE, mbPath);
3644*5c51f124SMoriah Waterland 
3645*5c51f124SMoriah Waterland 	/* open the file - this is the basic existence test */
3646*5c51f124SMoriah Waterland 
3647*5c51f124SMoriah Waterland 	fd = open(mbPath, O_RDONLY|O_LARGEFILE, 0);
3648*5c51f124SMoriah Waterland 
3649*5c51f124SMoriah Waterland 	/* existence test failed if file cannot be opened */
3650*5c51f124SMoriah Waterland 
3651*5c51f124SMoriah Waterland 	if (fd < 0) {
3652*5c51f124SMoriah Waterland 		/*
3653*5c51f124SMoriah Waterland 		 * target could not be opened - if testing for non-existence,
3654*5c51f124SMoriah Waterland 		 * return success, otherwise return failure
3655*5c51f124SMoriah Waterland 		 */
3656*5c51f124SMoriah Waterland 		if (a_tt & TEST_NOT_EXISTS) {
3657*5c51f124SMoriah Waterland 			echoDebug(DBG_CANNOT_ACCESS_PATH_OK, mbPath);
3658*5c51f124SMoriah Waterland 			free(mbPath);
3659*5c51f124SMoriah Waterland 			return (R_SUCCESS);
3660*5c51f124SMoriah Waterland 		}
3661*5c51f124SMoriah Waterland 
3662*5c51f124SMoriah Waterland 		echoDebug(DBG_CANNOT_ACCESS_PATH_BUT_SHOULD,
3663*5c51f124SMoriah Waterland 		    mbPath, strerror(errno));
3664*5c51f124SMoriah Waterland 		free(mbPath);
3665*5c51f124SMoriah Waterland 
3666*5c51f124SMoriah Waterland 		return (R_FAILURE);
3667*5c51f124SMoriah Waterland 	}
3668*5c51f124SMoriah Waterland 
3669*5c51f124SMoriah Waterland 	/*
3670*5c51f124SMoriah Waterland 	 * target successfully opened - if testing for non-existence,
3671*5c51f124SMoriah Waterland 	 * return failure, otherwise continue with specified tests
3672*5c51f124SMoriah Waterland 	 */
3673*5c51f124SMoriah Waterland 
3674*5c51f124SMoriah Waterland 	if (a_tt & TEST_NOT_EXISTS) {
3675*5c51f124SMoriah Waterland 		/* testing for non-existence: return failure */
3676*5c51f124SMoriah Waterland 		echoDebug(DBG_TEST_EXISTS_SHOULD_NOT, mbPath);
3677*5c51f124SMoriah Waterland 		free(mbPath);
3678*5c51f124SMoriah Waterland 		(void) close(fd);
3679*5c51f124SMoriah Waterland 		return (R_FAILURE);
3680*5c51f124SMoriah Waterland 	}
3681*5c51f124SMoriah Waterland 
3682*5c51f124SMoriah Waterland 	/* get the file status */
3683*5c51f124SMoriah Waterland 
3684*5c51f124SMoriah Waterland 	r = fstat(fd, &statbuf);
3685*5c51f124SMoriah Waterland 	if (r != 0) {
3686*5c51f124SMoriah Waterland 		echoDebug(DBG_PATH_DOES_NOT_EXIST, mbPath, strerror(errno));
3687*5c51f124SMoriah Waterland 		(void) close(fd);
3688*5c51f124SMoriah Waterland 		free(mbPath);
3689*5c51f124SMoriah Waterland 		return (R_FAILURE);
3690*5c51f124SMoriah Waterland 	}
3691*5c51f124SMoriah Waterland 
3692*5c51f124SMoriah Waterland 	/* required to be a directory? */
3693*5c51f124SMoriah Waterland 
3694*5c51f124SMoriah Waterland 	if (a_tt & TEST_IS_DIRECTORY) {
3695*5c51f124SMoriah Waterland 		if (!(statbuf.st_mode & S_IFDIR)) {
3696*5c51f124SMoriah Waterland 			/* is not a directory */
3697*5c51f124SMoriah Waterland 			echoDebug(DBG_IS_NOT_A_DIRECTORY, mbPath);
3698*5c51f124SMoriah Waterland 			free(mbPath);
3699*5c51f124SMoriah Waterland 			return (R_FAILURE);
3700*5c51f124SMoriah Waterland 		}
3701*5c51f124SMoriah Waterland 		/* a directory */
3702*5c51f124SMoriah Waterland 		echoDebug(DBG_DIRECTORY_IS, mbPath);
3703*5c51f124SMoriah Waterland 	}
3704*5c51f124SMoriah Waterland 
3705*5c51f124SMoriah Waterland 	/* required to not be a directory? */
3706*5c51f124SMoriah Waterland 
3707*5c51f124SMoriah Waterland 	if (a_tt & TEST_NOT_DIRECTORY) {
3708*5c51f124SMoriah Waterland 		if (statbuf.st_mode & S_IFDIR) {
3709*5c51f124SMoriah Waterland 			/* is a directory */
3710*5c51f124SMoriah Waterland 			echoDebug(DBG_IS_A_DIRECTORY, mbPath);
3711*5c51f124SMoriah Waterland 			free(mbPath);
3712*5c51f124SMoriah Waterland 			return (R_FAILURE);
3713*5c51f124SMoriah Waterland 		}
3714*5c51f124SMoriah Waterland 		/* not a directory */
3715*5c51f124SMoriah Waterland 		echoDebug(DBG_DIRECTORY_NOT, mbPath);
3716*5c51f124SMoriah Waterland 	}
3717*5c51f124SMoriah Waterland 
3718*5c51f124SMoriah Waterland 	/* required to be a file? */
3719*5c51f124SMoriah Waterland 
3720*5c51f124SMoriah Waterland 	if (a_tt & TEST_IS_FILE) {
3721*5c51f124SMoriah Waterland 		if (!(statbuf.st_mode & S_IFREG)) {
3722*5c51f124SMoriah Waterland 			/* is not a regular file */
3723*5c51f124SMoriah Waterland 			echoDebug(DBG_IS_NOT_A_FILE, mbPath);
3724*5c51f124SMoriah Waterland 			free(mbPath);
3725*5c51f124SMoriah Waterland 			return (R_FAILURE);
3726*5c51f124SMoriah Waterland 		}
3727*5c51f124SMoriah Waterland 		/* a regular file */
3728*5c51f124SMoriah Waterland 		echoDebug(DBG_FILE_IS, mbPath);
3729*5c51f124SMoriah Waterland 	}
3730*5c51f124SMoriah Waterland 
3731*5c51f124SMoriah Waterland 	/* required to not be a file? */
3732*5c51f124SMoriah Waterland 
3733*5c51f124SMoriah Waterland 	if (a_tt & TEST_NOT_FILE) {
3734*5c51f124SMoriah Waterland 		if (statbuf.st_mode & S_IFREG) {
3735*5c51f124SMoriah Waterland 			/* is a regular file */
3736*5c51f124SMoriah Waterland 			echoDebug(DBG_IS_A_FILE, mbPath);
3737*5c51f124SMoriah Waterland 			free(mbPath);
3738*5c51f124SMoriah Waterland 			return (R_FAILURE);
3739*5c51f124SMoriah Waterland 		}
3740*5c51f124SMoriah Waterland 		/* not a regular file */
3741*5c51f124SMoriah Waterland 		echoDebug(DBG_FILE_NOT, mbPath);
3742*5c51f124SMoriah Waterland 	}
3743*5c51f124SMoriah Waterland 
3744*5c51f124SMoriah Waterland 	/*
3745*5c51f124SMoriah Waterland 	 * Find token (global) in file pointed to by mbPath.
3746*5c51f124SMoriah Waterland 	 * token is only compared to first word in mbPath.
3747*5c51f124SMoriah Waterland 	 */
3748*5c51f124SMoriah Waterland 
3749*5c51f124SMoriah Waterland 	if (a_tt & TEST_GLOBAL_TOKEN_IN_FILE) {
3750*5c51f124SMoriah Waterland 		if (!(statbuf.st_mode & S_IFREG)) {
3751*5c51f124SMoriah Waterland 			/* is not a regular file */
3752*5c51f124SMoriah Waterland 			echoDebug(DBG_IS_NOT_A_FILE, mbPath);
3753*5c51f124SMoriah Waterland 			free(mbPath);
3754*5c51f124SMoriah Waterland 			return (R_FAILURE);
3755*5c51f124SMoriah Waterland 		}
3756*5c51f124SMoriah Waterland 		/* If global exists then we're not in a non-global zone */
3757*5c51f124SMoriah Waterland 		if (findToken(mbPath, GLOBAL_ZONENAME) == R_SUCCESS) {
3758*5c51f124SMoriah Waterland 			echoDebug(DBG_TOKEN__EXISTS, GLOBAL_ZONENAME, mbPath);
3759*5c51f124SMoriah Waterland 			free(mbPath);
3760*5c51f124SMoriah Waterland 			return (R_FAILURE);
3761*5c51f124SMoriah Waterland 		}
3762*5c51f124SMoriah Waterland 	}
3763*5c51f124SMoriah Waterland 
3764*5c51f124SMoriah Waterland 	(void) close(fd);
3765*5c51f124SMoriah Waterland 
3766*5c51f124SMoriah Waterland 	/* success! */
3767*5c51f124SMoriah Waterland 
3768*5c51f124SMoriah Waterland 	echoDebug(DBG_TESTPATH_OK, mbPath);
3769*5c51f124SMoriah Waterland 
3770*5c51f124SMoriah Waterland 	/* free up temp storage used to hold path to test */
3771*5c51f124SMoriah Waterland 
3772*5c51f124SMoriah Waterland 	free(mbPath);
3773*5c51f124SMoriah Waterland 
3774*5c51f124SMoriah Waterland 	return (R_SUCCESS);
3775*5c51f124SMoriah Waterland }
3776*5c51f124SMoriah Waterland 
3777*5c51f124SMoriah Waterland /*
3778*5c51f124SMoriah Waterland  * Name:        findToken
3779*5c51f124SMoriah Waterland  * Description:	Find first token in file.
3780*5c51f124SMoriah Waterland  * Arguments:
3781*5c51f124SMoriah Waterland  *              path - file to search for token
3782*5c51f124SMoriah Waterland  *              token - string to search for
3783*5c51f124SMoriah Waterland  * Returns:
3784*5c51f124SMoriah Waterland  *              R_SUCCESS - the token exists
3785*5c51f124SMoriah Waterland  *              R_FAILURE - the token does not exist
3786*5c51f124SMoriah Waterland  *              R_ERROR - fatal error attempting to find token
3787*5c51f124SMoriah Waterland  */
3788*5c51f124SMoriah Waterland 
3789*5c51f124SMoriah Waterland static int
3790*5c51f124SMoriah Waterland findToken(char *path, char *token)
3791*5c51f124SMoriah Waterland {
3792*5c51f124SMoriah Waterland 	FILE	*fp;
3793*5c51f124SMoriah Waterland 	char	*cp;
3794*5c51f124SMoriah Waterland 	char	line[MAXPATHLEN];
3795*5c51f124SMoriah Waterland 
3796*5c51f124SMoriah Waterland 	if (path == NULL || token == NULL) {
3797*5c51f124SMoriah Waterland 		return (R_ERROR);
3798*5c51f124SMoriah Waterland 	}
3799*5c51f124SMoriah Waterland 	if ((fp = fopen(path, "r")) == NULL) {
3800*5c51f124SMoriah Waterland 		return (R_ERROR);
3801*5c51f124SMoriah Waterland 	}
3802*5c51f124SMoriah Waterland 
3803*5c51f124SMoriah Waterland 	while (fgets(line, sizeof (line), fp) != NULL) {
3804*5c51f124SMoriah Waterland 		for (cp = line; *cp && isspace(*cp); cp++);
3805*5c51f124SMoriah Waterland 		/* skip comments */
3806*5c51f124SMoriah Waterland 		if (*cp == '#') {
3807*5c51f124SMoriah Waterland 			continue;
3808*5c51f124SMoriah Waterland 		}
3809*5c51f124SMoriah Waterland 		if (pkgstrContainsToken(cp, token, ":")) {
3810*5c51f124SMoriah Waterland 			(void) fclose(fp);
3811*5c51f124SMoriah Waterland 			return (R_SUCCESS);
3812*5c51f124SMoriah Waterland 		}
3813*5c51f124SMoriah Waterland 	}
3814*5c51f124SMoriah Waterland 	(void) fclose(fp);
3815*5c51f124SMoriah Waterland 	return (R_FAILURE);
3816*5c51f124SMoriah Waterland }
3817*5c51f124SMoriah Waterland 
3818*5c51f124SMoriah Waterland 
3819*5c51f124SMoriah Waterland /*
3820*5c51f124SMoriah Waterland  * Name:	resolvePath
3821*5c51f124SMoriah Waterland  * Description:	fully resolve a path to an absolute real path
3822*5c51f124SMoriah Waterland  * Arguments:	r_path - pointer to pointer to malloc()ed storage containing
3823*5c51f124SMoriah Waterland  *			the path to resolve - this path may be reallocated
3824*5c51f124SMoriah Waterland  *			as necessary to hold the fully resolved path
3825*5c51f124SMoriah Waterland  * Output:	r_path - is realloc()ed as necessary
3826*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - the path is fully resolved
3827*5c51f124SMoriah Waterland  *		R_FAILURE - the path could not be resolved
3828*5c51f124SMoriah Waterland  *		R_ERROR - fatal error attempting to resolve path
3829*5c51f124SMoriah Waterland  */
3830*5c51f124SMoriah Waterland 
3831*5c51f124SMoriah Waterland static int
3832*5c51f124SMoriah Waterland resolvePath(char **r_path)
3833*5c51f124SMoriah Waterland {
3834*5c51f124SMoriah Waterland 	int		i;
3835*5c51f124SMoriah Waterland 	char		resolvedPath[MAXPATHLEN+1] = {'\0'};
3836*5c51f124SMoriah Waterland 	size_t		mbPathlen;	/* length of multi-byte path */
3837*5c51f124SMoriah Waterland 	size_t		wcPathlen;	/* length of wide-character path */
3838*5c51f124SMoriah Waterland 	wchar_t		*wcPath;	/* wide-character version of the path */
3839*5c51f124SMoriah Waterland 	wchar_t		*wptr;		/* scratch pointer */
3840*5c51f124SMoriah Waterland 
3841*5c51f124SMoriah Waterland 	/* entry assertions */
3842*5c51f124SMoriah Waterland 
3843*5c51f124SMoriah Waterland 	assert(r_path != (char **)NULL);
3844*5c51f124SMoriah Waterland 
3845*5c51f124SMoriah Waterland 	/* return error if the path is completely empty */
3846*5c51f124SMoriah Waterland 
3847*5c51f124SMoriah Waterland 	if (*r_path == '\0') {
3848*5c51f124SMoriah Waterland 		return (R_FAILURE);
3849*5c51f124SMoriah Waterland 	}
3850*5c51f124SMoriah Waterland 
3851*5c51f124SMoriah Waterland 	/* remove all leading whitespace */
3852*5c51f124SMoriah Waterland 
3853*5c51f124SMoriah Waterland 	removeLeadingWhitespace(r_path);
3854*5c51f124SMoriah Waterland 
3855*5c51f124SMoriah Waterland 	/*
3856*5c51f124SMoriah Waterland 	 * convert to real path: an absolute pathname that names the same file,
3857*5c51f124SMoriah Waterland 	 * whose resolution does not involve ".", "..",  or  symbolic links.
3858*5c51f124SMoriah Waterland 	 */
3859*5c51f124SMoriah Waterland 
3860*5c51f124SMoriah Waterland 	if (realpath(*r_path, resolvedPath) != NULL) {
3861*5c51f124SMoriah Waterland 		free(*r_path);
3862*5c51f124SMoriah Waterland 		*r_path = strdup(resolvedPath);
3863*5c51f124SMoriah Waterland 	}
3864*5c51f124SMoriah Waterland 
3865*5c51f124SMoriah Waterland 	/*
3866*5c51f124SMoriah Waterland 	 *  convert the multi-byte version of the path to a
3867*5c51f124SMoriah Waterland 	 *  wide-character rendering, for doing our figuring.
3868*5c51f124SMoriah Waterland 	 */
3869*5c51f124SMoriah Waterland 
3870*5c51f124SMoriah Waterland 	mbPathlen = strlen(*r_path);
3871*5c51f124SMoriah Waterland 
3872*5c51f124SMoriah Waterland 	if ((wcPath = (wchar_t *)
3873*5c51f124SMoriah Waterland 		calloc(1, sizeof (wchar_t)*(mbPathlen+1))) == NULL) {
3874*5c51f124SMoriah Waterland 		return (R_FAILURE);
3875*5c51f124SMoriah Waterland 	}
3876*5c51f124SMoriah Waterland 
3877*5c51f124SMoriah Waterland 	/*LINTED*/
3878*5c51f124SMoriah Waterland 	if ((wcPathlen = mbstowcs(wcPath, *r_path, mbPathlen)) == -1) {
3879*5c51f124SMoriah Waterland 		free(wcPath);
3880*5c51f124SMoriah Waterland 		return (R_FAILURE);
3881*5c51f124SMoriah Waterland 	}
3882*5c51f124SMoriah Waterland 
3883*5c51f124SMoriah Waterland 	/*
3884*5c51f124SMoriah Waterland 	 *  remove duplicate slashes first ("//../" -> "/")
3885*5c51f124SMoriah Waterland 	 */
3886*5c51f124SMoriah Waterland 
3887*5c51f124SMoriah Waterland 	for (wptr = wcPath, i = 0; i < wcPathlen; i++) {
3888*5c51f124SMoriah Waterland 		*wptr++ = wcPath[i];
3889*5c51f124SMoriah Waterland 
3890*5c51f124SMoriah Waterland 		if (wcPath[i] == '/') {
3891*5c51f124SMoriah Waterland 			i++;
3892*5c51f124SMoriah Waterland 
3893*5c51f124SMoriah Waterland 			while (wcPath[i] == '/') {
3894*5c51f124SMoriah Waterland 				i++;
3895*5c51f124SMoriah Waterland 			}
3896*5c51f124SMoriah Waterland 
3897*5c51f124SMoriah Waterland 			i--;
3898*5c51f124SMoriah Waterland 		}
3899*5c51f124SMoriah Waterland 	}
3900*5c51f124SMoriah Waterland 
3901*5c51f124SMoriah Waterland 	*wptr = '\0';
3902*5c51f124SMoriah Waterland 
3903*5c51f124SMoriah Waterland 	/*
3904*5c51f124SMoriah Waterland 	 *  now convert back to the multi-byte format.
3905*5c51f124SMoriah Waterland 	 */
3906*5c51f124SMoriah Waterland 
3907*5c51f124SMoriah Waterland 	/*LINTED*/
3908*5c51f124SMoriah Waterland 	if (wcstombs(*r_path, wcPath, mbPathlen) == -1) {
3909*5c51f124SMoriah Waterland 		free(wcPath);
3910*5c51f124SMoriah Waterland 		return (R_FAILURE);
3911*5c51f124SMoriah Waterland 	}
3912*5c51f124SMoriah Waterland 
3913*5c51f124SMoriah Waterland 	/* at this point have a path */
3914*5c51f124SMoriah Waterland 
3915*5c51f124SMoriah Waterland 	/* free up temporary storage */
3916*5c51f124SMoriah Waterland 
3917*5c51f124SMoriah Waterland 	free(wcPath);
3918*5c51f124SMoriah Waterland 
3919*5c51f124SMoriah Waterland 	return (R_SUCCESS);
3920*5c51f124SMoriah Waterland }
3921*5c51f124SMoriah Waterland 
3922*5c51f124SMoriah Waterland /*
3923*5c51f124SMoriah Waterland  * Name:	removeLeadingWhitespace
3924*5c51f124SMoriah Waterland  * Synopsis:	Remove leading whitespace from string
3925*5c51f124SMoriah Waterland  * Description:	Remove all leading whitespace characters from a string
3926*5c51f124SMoriah Waterland  * Arguments:	a_str - [RO, *RW] - (char **)
3927*5c51f124SMoriah Waterland  *			Pointer to handle to string (in allocated storage) to
3928*5c51f124SMoriah Waterland  *			remove all leading whitespace from
3929*5c51f124SMoriah Waterland  * Returns:	void
3930*5c51f124SMoriah Waterland  *			The input string is modified as follows:
3931*5c51f124SMoriah Waterland  *			== NULL:
3932*5c51f124SMoriah Waterland  *				- input string was NULL
3933*5c51f124SMoriah Waterland  *				- input string is all whitespace
3934*5c51f124SMoriah Waterland  *			!= NULL:
3935*5c51f124SMoriah Waterland  *				- copy of input string with leading
3936*5c51f124SMoriah Waterland  *				  whitespace removed
3937*5c51f124SMoriah Waterland  * CAUTION:	The input string must be allocated space (via malloc() or
3938*5c51f124SMoriah Waterland  *		strdup()) - it must not be a static or inline character string
3939*5c51f124SMoriah Waterland  * NOTE:	The input string a_str will be freed with 'free'
3940*5c51f124SMoriah Waterland  *		if it is all whitespace, or if it contains any leading
3941*5c51f124SMoriah Waterland  *		whitespace characters
3942*5c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
3943*5c51f124SMoriah Waterland  *		calling method. The caller must use 'free' to dispose
3944*5c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
3945*5c51f124SMoriah Waterland  * Errors:	If the string cannot be created, the process exits
3946*5c51f124SMoriah Waterland  */
3947*5c51f124SMoriah Waterland 
3948*5c51f124SMoriah Waterland static void
3949*5c51f124SMoriah Waterland removeLeadingWhitespace(char **a_str)
3950*5c51f124SMoriah Waterland {
3951*5c51f124SMoriah Waterland 	char	*o_str;
3952*5c51f124SMoriah Waterland 
3953*5c51f124SMoriah Waterland 	/* entry assertions */
3954*5c51f124SMoriah Waterland 
3955*5c51f124SMoriah Waterland 	assert(a_str != (char **)NULL);
3956*5c51f124SMoriah Waterland 
3957*5c51f124SMoriah Waterland 	/* if string is null, just return */
3958*5c51f124SMoriah Waterland 
3959*5c51f124SMoriah Waterland 	if (*a_str == NULL) {
3960*5c51f124SMoriah Waterland 		return;
3961*5c51f124SMoriah Waterland 	}
3962*5c51f124SMoriah Waterland 	o_str = *a_str;
3963*5c51f124SMoriah Waterland 
3964*5c51f124SMoriah Waterland 	/* if string is empty, deallocate and return NULL */
3965*5c51f124SMoriah Waterland 
3966*5c51f124SMoriah Waterland 	if (*o_str == '\0') {
3967*5c51f124SMoriah Waterland 		/* free string */
3968*5c51f124SMoriah Waterland 		free(*a_str);
3969*5c51f124SMoriah Waterland 		*a_str = NULL;
3970*5c51f124SMoriah Waterland 		return;
3971*5c51f124SMoriah Waterland 	}
3972*5c51f124SMoriah Waterland 
3973*5c51f124SMoriah Waterland 	/* if first character is not a space, just return */
3974*5c51f124SMoriah Waterland 
3975*5c51f124SMoriah Waterland 	if (!isspace(*o_str)) {
3976*5c51f124SMoriah Waterland 		return;
3977*5c51f124SMoriah Waterland 	}
3978*5c51f124SMoriah Waterland 
3979*5c51f124SMoriah Waterland 	/* advance past all space characters */
3980*5c51f124SMoriah Waterland 
3981*5c51f124SMoriah Waterland 	while ((*o_str != '\0') && (isspace(*o_str))) {
3982*5c51f124SMoriah Waterland 		o_str++;
3983*5c51f124SMoriah Waterland 	}
3984*5c51f124SMoriah Waterland 
3985*5c51f124SMoriah Waterland 	/* if string was all space characters, deallocate and return NULL */
3986*5c51f124SMoriah Waterland 
3987*5c51f124SMoriah Waterland 	if (*o_str == '\0') {
3988*5c51f124SMoriah Waterland 		/* free string */
3989*5c51f124SMoriah Waterland 		free(*a_str);
3990*5c51f124SMoriah Waterland 		*a_str = NULL;
3991*5c51f124SMoriah Waterland 		return;
3992*5c51f124SMoriah Waterland 	}
3993*5c51f124SMoriah Waterland 
3994*5c51f124SMoriah Waterland 	/* have non-space/null byte, return dup, deallocate original */
3995*5c51f124SMoriah Waterland 
3996*5c51f124SMoriah Waterland 	o_str = strdup(o_str);
3997*5c51f124SMoriah Waterland 	free(*a_str);
3998*5c51f124SMoriah Waterland 	*a_str = o_str;
3999*5c51f124SMoriah Waterland }
4000*5c51f124SMoriah Waterland 
4001*5c51f124SMoriah Waterland /*
4002*5c51f124SMoriah Waterland  * Name:	getZoneName
4003*5c51f124SMoriah Waterland  * Description:	get the name of the zone this process is running in
4004*5c51f124SMoriah Waterland  * Arguments:	r_zoneName - pointer to pointer to receive zone name
4005*5c51f124SMoriah Waterland  * Output:	r_zoneName - a pointer to malloc()ed storage containing
4006*5c51f124SMoriah Waterland  *			the zone name this process is running in is stored
4007*5c51f124SMoriah Waterland  *			in the location pointed to by r_zoneName
4008*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - the zone name is successfully returned
4009*5c51f124SMoriah Waterland  *		R_FAILURE - the zone name is not successfully returned
4010*5c51f124SMoriah Waterland  *		R_ERROR - error attempting to get the zone name
4011*5c51f124SMoriah Waterland  */
4012*5c51f124SMoriah Waterland 
4013*5c51f124SMoriah Waterland static int
4014*5c51f124SMoriah Waterland getZoneName(char **r_zoneName)
4015*5c51f124SMoriah Waterland {
4016*5c51f124SMoriah Waterland static char zoneName[ZONENAME_MAX] = { '\0' };
4017*5c51f124SMoriah Waterland 
4018*5c51f124SMoriah Waterland 	/* if zone name not already present, retrieve and cache name */
4019*5c51f124SMoriah Waterland 
4020*5c51f124SMoriah Waterland 	if (zoneName[0] == '\0') {
4021*5c51f124SMoriah Waterland 		if (getzonenamebyid(getzoneid(), zoneName,
4022*5c51f124SMoriah Waterland 			sizeof (zoneName)) < 0) {
4023*5c51f124SMoriah Waterland 			log_msg(LOG_MSG_ERR, ERR_CANNOT_GET_ZONENAME);
4024*5c51f124SMoriah Waterland 			return (R_ERROR);
4025*5c51f124SMoriah Waterland 		}
4026*5c51f124SMoriah Waterland 	}
4027*5c51f124SMoriah Waterland 
4028*5c51f124SMoriah Waterland 	/* return cached zone name */
4029*5c51f124SMoriah Waterland 
4030*5c51f124SMoriah Waterland 	*r_zoneName = zoneName;
4031*5c51f124SMoriah Waterland 	return (R_SUCCESS);
4032*5c51f124SMoriah Waterland }
4033*5c51f124SMoriah Waterland 
4034*5c51f124SMoriah Waterland /*
4035*5c51f124SMoriah Waterland  * Name:	getRootPath
4036*5c51f124SMoriah Waterland  * Description:	get the root path being tested by this process
4037*5c51f124SMoriah Waterland  * Arguments:	r_rootPath - pointer to pointer to receive root path
4038*5c51f124SMoriah Waterland  * Output:	r_rootPath - a pointer to malloc()ed storage containing
4039*5c51f124SMoriah Waterland  *			the root path name this process is testing
4040*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - the root path is successfully returned
4041*5c51f124SMoriah Waterland  *		R_FAILURE - the root path is not successfully returned
4042*5c51f124SMoriah Waterland  *		R_ERROR - error attempting to get the root path
4043*5c51f124SMoriah Waterland  */
4044*5c51f124SMoriah Waterland 
4045*5c51f124SMoriah Waterland static int
4046*5c51f124SMoriah Waterland getRootPath(char **r_rootPath)
4047*5c51f124SMoriah Waterland {
4048*5c51f124SMoriah Waterland 	*r_rootPath = _rootPath;
4049*5c51f124SMoriah Waterland 	return (R_SUCCESS);
4050*5c51f124SMoriah Waterland }
4051*5c51f124SMoriah Waterland 
4052*5c51f124SMoriah Waterland /*
4053*5c51f124SMoriah Waterland  * Name:	setVerbose
4054*5c51f124SMoriah Waterland  * Description:	Turns on verbose output
4055*5c51f124SMoriah Waterland  * Scope:	public
4056*5c51f124SMoriah Waterland  * Arguments:	verbose = B_TRUE indicates verbose mode
4057*5c51f124SMoriah Waterland  * Returns:	none
4058*5c51f124SMoriah Waterland  */
4059*5c51f124SMoriah Waterland 
4060*5c51f124SMoriah Waterland static void
4061*5c51f124SMoriah Waterland setVerbose(boolean_t setting)
4062*5c51f124SMoriah Waterland {
4063*5c51f124SMoriah Waterland 	/* set log verbose messages */
4064*5c51f124SMoriah Waterland 
4065*5c51f124SMoriah Waterland 	log_set_verbose(setting);
4066*5c51f124SMoriah Waterland 
4067*5c51f124SMoriah Waterland 	/* set interactive messages */
4068*5c51f124SMoriah Waterland 
4069*5c51f124SMoriah Waterland 	echoSetFlag(setting);
4070*5c51f124SMoriah Waterland }
4071*5c51f124SMoriah Waterland 
4072*5c51f124SMoriah Waterland /*
4073*5c51f124SMoriah Waterland  * Name:	negate_results
4074*5c51f124SMoriah Waterland  * Description:	control negation of results
4075*5c51f124SMoriah Waterland  * Scope:	public
4076*5c51f124SMoriah Waterland  * Arguments:	setting
4077*5c51f124SMoriah Waterland  *		== B_TRUE indicates negated results mode
4078*5c51f124SMoriah Waterland  *		== B_FALSE indicates non-negated results mode
4079*5c51f124SMoriah Waterland  * Returns:	none
4080*5c51f124SMoriah Waterland  */
4081*5c51f124SMoriah Waterland 
4082*5c51f124SMoriah Waterland static void
4083*5c51f124SMoriah Waterland setNegateResults(boolean_t setting)
4084*5c51f124SMoriah Waterland {
4085*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_SET_NEGATE_RESULTS,
4086*5c51f124SMoriah Waterland 		_negateResults, setting);
4087*5c51f124SMoriah Waterland 
4088*5c51f124SMoriah Waterland 	_negateResults = setting;
4089*5c51f124SMoriah Waterland }
4090*5c51f124SMoriah Waterland 
4091*5c51f124SMoriah Waterland /*
4092*5c51f124SMoriah Waterland  * Name:	getNegateResults
4093*5c51f124SMoriah Waterland  * Description:	Returns whether or not to results are negated
4094*5c51f124SMoriah Waterland  * Scope:	public
4095*5c51f124SMoriah Waterland  * Arguments:	none
4096*5c51f124SMoriah Waterland  * Returns:	B_TRUE - results are negated
4097*5c51f124SMoriah Waterland  *		B_FALSE - results are not negated
4098*5c51f124SMoriah Waterland  */
4099*5c51f124SMoriah Waterland 
4100*5c51f124SMoriah Waterland static boolean_t
4101*5c51f124SMoriah Waterland getNegateResults(void)
4102*5c51f124SMoriah Waterland {
4103*5c51f124SMoriah Waterland 	return (_negateResults);
4104*5c51f124SMoriah Waterland }
4105*5c51f124SMoriah Waterland 
4106*5c51f124SMoriah Waterland /*
4107*5c51f124SMoriah Waterland  * Name:	usage
4108*5c51f124SMoriah Waterland  * Description:	output usage string
4109*5c51f124SMoriah Waterland  * Arguments:	a_format - format to use to generate message
4110*5c51f124SMoriah Waterland  *		arguments following a_format - as needed for a_format
4111*5c51f124SMoriah Waterland  * Output:	Outputs the usage string to stderr.
4112*5c51f124SMoriah Waterland  * Returns:	R_ERROR
4113*5c51f124SMoriah Waterland  */
4114*5c51f124SMoriah Waterland 
4115*5c51f124SMoriah Waterland static int
4116*5c51f124SMoriah Waterland usage(char *a_format, ...)
4117*5c51f124SMoriah Waterland {
4118*5c51f124SMoriah Waterland 	int		cur_cmd;
4119*5c51f124SMoriah Waterland 	char		cmdlst[LINE_MAX+1] = { '\0' };
4120*5c51f124SMoriah Waterland 	char		*message;
4121*5c51f124SMoriah Waterland 	char		bfr[1];
4122*5c51f124SMoriah Waterland 	char		*p = get_prog_name();
4123*5c51f124SMoriah Waterland 	size_t		vres = 0;
4124*5c51f124SMoriah Waterland 	va_list		ap;
4125*5c51f124SMoriah Waterland 
4126*5c51f124SMoriah Waterland 	/* entry assertions */
4127*5c51f124SMoriah Waterland 
4128*5c51f124SMoriah Waterland 	assert(a_format != NULL);
4129*5c51f124SMoriah Waterland 	assert(*a_format != '\0');
4130*5c51f124SMoriah Waterland 
4131*5c51f124SMoriah Waterland 	/* determine size of the message in bytes */
4132*5c51f124SMoriah Waterland 
4133*5c51f124SMoriah Waterland 	va_start(ap, a_format);
4134*5c51f124SMoriah Waterland 	/* LINTED warning: variable format specifier to vsnprintf(); */
4135*5c51f124SMoriah Waterland 	vres = vsnprintf(bfr, 1, a_format, ap);
4136*5c51f124SMoriah Waterland 	va_end(ap);
4137*5c51f124SMoriah Waterland 
4138*5c51f124SMoriah Waterland 	assert(vres > 0);
4139*5c51f124SMoriah Waterland 
4140*5c51f124SMoriah Waterland 	/* allocate storage to hold the message */
4141*5c51f124SMoriah Waterland 
4142*5c51f124SMoriah Waterland 	message = (char *)calloc(1, vres+2);
4143*5c51f124SMoriah Waterland 	assert(message != NULL);
4144*5c51f124SMoriah Waterland 
4145*5c51f124SMoriah Waterland 	/* generate the results of the printf conversion */
4146*5c51f124SMoriah Waterland 
4147*5c51f124SMoriah Waterland 	va_start(ap, a_format);
4148*5c51f124SMoriah Waterland 	/* LINTED warning: variable format specifier to vsnprintf(); */
4149*5c51f124SMoriah Waterland 	vres = vsnprintf(message, vres+1, a_format, ap);
4150*5c51f124SMoriah Waterland 	va_end(ap);
4151*5c51f124SMoriah Waterland 
4152*5c51f124SMoriah Waterland 	assert(vres > 0);
4153*5c51f124SMoriah Waterland 
4154*5c51f124SMoriah Waterland 	/* generate list of all defined conditions */
4155*5c51f124SMoriah Waterland 
4156*5c51f124SMoriah Waterland 	for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
4157*5c51f124SMoriah Waterland 		(void) strlcat(cmdlst, "\t", sizeof (cmdlst));
4158*5c51f124SMoriah Waterland 		(void) strlcat(cmdlst, cmds[cur_cmd].c_name, sizeof (cmdlst));
4159*5c51f124SMoriah Waterland 		if (cmds[cur_cmd].c_args != NULL) {
4160*5c51f124SMoriah Waterland 			(void) strlcat(cmdlst, cmds[cur_cmd].c_args,
4161*5c51f124SMoriah Waterland 						sizeof (cmdlst));
4162*5c51f124SMoriah Waterland 		}
4163*5c51f124SMoriah Waterland 		(void) strlcat(cmdlst, "\n", sizeof (cmdlst));
4164*5c51f124SMoriah Waterland 	}
4165*5c51f124SMoriah Waterland 
4166*5c51f124SMoriah Waterland 	/* output usage with conditions */
4167*5c51f124SMoriah Waterland 
4168*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_INFO, MSG_USAGE, message, p ? p : "pkgcond", cmdlst);
4169*5c51f124SMoriah Waterland 
4170*5c51f124SMoriah Waterland 	return (R_ERROR);
4171*5c51f124SMoriah Waterland }
4172*5c51f124SMoriah Waterland 
4173*5c51f124SMoriah Waterland /*
4174*5c51f124SMoriah Waterland  * Name:	parseGlobalData
4175*5c51f124SMoriah Waterland  * Description:	parse environment global data and store in global data structure
4176*5c51f124SMoriah Waterland  * Arguments:	a_envVar - pointer to string representing the name of the
4177*5c51f124SMoriah Waterland  *			environment variable to get and parse
4178*5c51f124SMoriah Waterland  *		r_gdt - pointer to pointer to global data structure to fill in
4179*5c51f124SMoriah Waterland  *			using the parsed data from a_envVar
4180*5c51f124SMoriah Waterland  * Output:	none
4181*5c51f124SMoriah Waterland  * Returns:	R_SUCCESS - the global data is successfully parsed
4182*5c51f124SMoriah Waterland  *		R_FAILURE - problem parsing global data
4183*5c51f124SMoriah Waterland  *		R_ERROR - fatal error attempting to parse global data
4184*5c51f124SMoriah Waterland  */
4185*5c51f124SMoriah Waterland 
4186*5c51f124SMoriah Waterland static int
4187*5c51f124SMoriah Waterland parseGlobalData(char *a_envVar, GLOBALDATA_T **r_gdt)
4188*5c51f124SMoriah Waterland {
4189*5c51f124SMoriah Waterland 	int		r;
4190*5c51f124SMoriah Waterland 	int		n;
4191*5c51f124SMoriah Waterland 	char		*a;
4192*5c51f124SMoriah Waterland 	SML_TAG		*tag;
4193*5c51f124SMoriah Waterland 	SML_TAG		*ntag;
4194*5c51f124SMoriah Waterland 
4195*5c51f124SMoriah Waterland 	assert(r_gdt != (GLOBALDATA_T **)NULL);
4196*5c51f124SMoriah Waterland 
4197*5c51f124SMoriah Waterland 	/*
4198*5c51f124SMoriah Waterland 	 * allocate space for global data structure if needed
4199*5c51f124SMoriah Waterland 	 */
4200*5c51f124SMoriah Waterland 
4201*5c51f124SMoriah Waterland 	if (*r_gdt == (GLOBALDATA_T *)NULL) {
4202*5c51f124SMoriah Waterland 		*r_gdt = (GLOBALDATA_T *)calloc(1, sizeof (GLOBALDATA_T));
4203*5c51f124SMoriah Waterland 	}
4204*5c51f124SMoriah Waterland 
4205*5c51f124SMoriah Waterland 	/*
4206*5c51f124SMoriah Waterland 	 * get initial installation indication:
4207*5c51f124SMoriah Waterland 	 * If the initial install variable is set to "true", then an initial
4208*5c51f124SMoriah Waterland 	 * installation of Solaris is underway. When this condition is true:
4209*5c51f124SMoriah Waterland 	 * - if the path being checked is the package install root, then
4210*5c51f124SMoriah Waterland 	 *   the path is considered to be an 'alternative root' which is
4211*5c51f124SMoriah Waterland 	 *   currently being installed.
4212*5c51f124SMoriah Waterland 	 * - if the path being checked is not the package install root, then
4213*5c51f124SMoriah Waterland 	 *   the path needs to be further analyzed to determine what it may
4214*5c51f124SMoriah Waterland 	 *   be referring to.
4215*5c51f124SMoriah Waterland 	 */
4216*5c51f124SMoriah Waterland 
4217*5c51f124SMoriah Waterland 	a = getenv(ENV_VAR_INITIAL_INSTALL);
4218*5c51f124SMoriah Waterland 	if ((a != NULL) && (strcasecmp(a, "true") == 0)) {
4219*5c51f124SMoriah Waterland 		(*r_gdt)->gd_initialInstall = B_TRUE;
4220*5c51f124SMoriah Waterland 	}
4221*5c51f124SMoriah Waterland 
4222*5c51f124SMoriah Waterland 	/* get current zone name */
4223*5c51f124SMoriah Waterland 
4224*5c51f124SMoriah Waterland 	r = getZoneName(&(*r_gdt)->gd_zoneName);
4225*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
4226*5c51f124SMoriah Waterland 		(*r_gdt)->gd_zoneName = "";
4227*5c51f124SMoriah Waterland 	}
4228*5c51f124SMoriah Waterland 
4229*5c51f124SMoriah Waterland 	/*
4230*5c51f124SMoriah Waterland 	 * get zone installation status:
4231*5c51f124SMoriah Waterland 	 * - If the package install zone name is not set, then an installation
4232*5c51f124SMoriah Waterland 	 *   of a global zone, or of a non-global zone, is not underway.
4233*5c51f124SMoriah Waterland 	 * - If the package install zone name is set to "global", then an
4234*5c51f124SMoriah Waterland 	 *   installation of a global zone is underway. In this case, no path
4235*5c51f124SMoriah Waterland 	 *   can be a netinstall image, diskless client, mounted miniroot,
4236*5c51f124SMoriah Waterland 	 *   non-global zone, the current running system, alternative root,
4237*5c51f124SMoriah Waterland 	 *   or alternative boot environment.
4238*5c51f124SMoriah Waterland 	 * - If the package install zone name is set to a value other than
4239*5c51f124SMoriah Waterland 	 *   "global", then an installation of a non-global zone with that name
4240*5c51f124SMoriah Waterland 	 *   is underway.  In this case, no path can be a netinstall image,
4241*5c51f124SMoriah Waterland 	 *   diskless client, mounted miniroot, global zone, the current
4242*5c51f124SMoriah Waterland 	 *   running system, alternative root, or alternative boot environment.
4243*5c51f124SMoriah Waterland 	 */
4244*5c51f124SMoriah Waterland 
4245*5c51f124SMoriah Waterland 	a = getenv(ENV_VAR_PKGZONENAME);
4246*5c51f124SMoriah Waterland 	if ((a == NULL) || (*a == '\0')) {
4247*5c51f124SMoriah Waterland 		/* not installing a zone */
4248*5c51f124SMoriah Waterland 		(*r_gdt)->gd_globalZoneInstall = B_FALSE;
4249*5c51f124SMoriah Waterland 		(*r_gdt)->gd_nonglobalZoneInstall = B_FALSE;
4250*5c51f124SMoriah Waterland 	} else if (strcmp(a, GLOBAL_ZONENAME) == 0) {
4251*5c51f124SMoriah Waterland 		/* installing a global zone */
4252*5c51f124SMoriah Waterland 		(*r_gdt)->gd_globalZoneInstall = B_TRUE;
4253*5c51f124SMoriah Waterland 		(*r_gdt)->gd_nonglobalZoneInstall = B_FALSE;
4254*5c51f124SMoriah Waterland 		(*r_gdt)->gd_zoneName = a;
4255*5c51f124SMoriah Waterland 	} else {
4256*5c51f124SMoriah Waterland 		/* installing a non-global zone by that name */
4257*5c51f124SMoriah Waterland 		(*r_gdt)->gd_globalZoneInstall = B_FALSE;
4258*5c51f124SMoriah Waterland 		(*r_gdt)->gd_nonglobalZoneInstall = B_TRUE;
4259*5c51f124SMoriah Waterland 		(*r_gdt)->gd_zoneName = a;
4260*5c51f124SMoriah Waterland 	}
4261*5c51f124SMoriah Waterland 
4262*5c51f124SMoriah Waterland 	/*
4263*5c51f124SMoriah Waterland 	 * get package install root. If it doesn't exist check for
4264*5c51f124SMoriah Waterland 	 * patch install root (ROOTDIR)
4265*5c51f124SMoriah Waterland 	 */
4266*5c51f124SMoriah Waterland 
4267*5c51f124SMoriah Waterland 	a = getenv(ENV_VAR_PKGROOT);
4268*5c51f124SMoriah Waterland 	if ((a != NULL) && (*a != '\0')) {
4269*5c51f124SMoriah Waterland 		(*r_gdt)->gd_installRoot = a;
4270*5c51f124SMoriah Waterland 	} else {
4271*5c51f124SMoriah Waterland 		a = getenv(ENV_VAR_PATCHROOT);
4272*5c51f124SMoriah Waterland 		if ((a != NULL) && (*a != '\0')) {
4273*5c51f124SMoriah Waterland 			(*r_gdt)->gd_installRoot = a;
4274*5c51f124SMoriah Waterland 		} else {
4275*5c51f124SMoriah Waterland 			(*r_gdt)->gd_installRoot = "/";
4276*5c51f124SMoriah Waterland 		}
4277*5c51f124SMoriah Waterland 	}
4278*5c51f124SMoriah Waterland 
4279*5c51f124SMoriah Waterland 	/*
4280*5c51f124SMoriah Waterland 	 * get patch client version: always set if $ROOTDIR != / and
4281*5c51f124SMoriah Waterland 	 * the $ROOTDIR/var/sadm/softinfo/INST_RELEASE file exists.
4282*5c51f124SMoriah Waterland 	 */
4283*5c51f124SMoriah Waterland 
4284*5c51f124SMoriah Waterland 	a = getenv(ENV_VAR_PATCH_CLIENTVER);
4285*5c51f124SMoriah Waterland 	(*r_gdt)->gd_patchClientVersion = (a ? a : "");
4286*5c51f124SMoriah Waterland 
4287*5c51f124SMoriah Waterland 	/* get the global data environment variable */
4288*5c51f124SMoriah Waterland 
4289*5c51f124SMoriah Waterland 	a = getenv(a_envVar);
4290*5c51f124SMoriah Waterland 
4291*5c51f124SMoriah Waterland 	/* if no data then issue warning and return success */
4292*5c51f124SMoriah Waterland 
4293*5c51f124SMoriah Waterland 	if ((a == NULL) || (*a_envVar == '\0')) {
4294*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_DEBUG, DBG_NO_GLOBAL_DATA_AVAILABLE, a_envVar);
4295*5c51f124SMoriah Waterland 		return (R_SUCCESS);
4296*5c51f124SMoriah Waterland 	}
4297*5c51f124SMoriah Waterland 
4298*5c51f124SMoriah Waterland 	/* data present - parse into SML structure */
4299*5c51f124SMoriah Waterland 
4300*5c51f124SMoriah Waterland 	log_msg(LOG_MSG_DEBUG, DBG_PARSE_GLOBAL, a);
4301*5c51f124SMoriah Waterland 
4302*5c51f124SMoriah Waterland 	r = smlConvertStringToTag(&tag, a);
4303*5c51f124SMoriah Waterland 	if (r != R_SUCCESS) {
4304*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_ERR, ERR_CANNOT_PARSE_GLOBAL_DATA, a);
4305*5c51f124SMoriah Waterland 		return (R_FAILURE);
4306*5c51f124SMoriah Waterland 	}
4307*5c51f124SMoriah Waterland 
4308*5c51f124SMoriah Waterland 	smlDbgPrintTag(tag, DBG_PARSED_ENVIRONMENT, a_envVar);
4309*5c51f124SMoriah Waterland 
4310*5c51f124SMoriah Waterland 	/* fill in global data structure */
4311*5c51f124SMoriah Waterland 
4312*5c51f124SMoriah Waterland 	/* find the environment condition information structure */
4313*5c51f124SMoriah Waterland 
4314*5c51f124SMoriah Waterland 	ntag = smlGetTagByName(tag, 0, TAG_COND_TOPLEVEL);
4315*5c51f124SMoriah Waterland 	if (ntag == SML_TAG__NULL) {
4316*5c51f124SMoriah Waterland 		log_msg(LOG_MSG_WRN, WRN_PARSED_DATA_MISSING,
4317*5c51f124SMoriah Waterland 			TAG_COND_TOPLEVEL);
4318*5c51f124SMoriah Waterland 		return (R_FAILURE);
4319*5c51f124SMoriah Waterland 	}
4320*5c51f124SMoriah Waterland 
4321*5c51f124SMoriah Waterland 	/*
4322*5c51f124SMoriah Waterland 	 * data found - extract what we know about
4323*5c51f124SMoriah Waterland 	 */
4324*5c51f124SMoriah Waterland 
4325*5c51f124SMoriah Waterland 	/* parent zone name */
4326*5c51f124SMoriah Waterland 
4327*5c51f124SMoriah Waterland 	a = smlGetParamByTag(ntag, 0, TAG_COND_PARENT_ZONE, TAG_COND_ZONE_NAME);
4328*5c51f124SMoriah Waterland 	(*r_gdt)->gd_parentZoneName = a;
4329*5c51f124SMoriah Waterland 
4330*5c51f124SMoriah Waterland 	/* parent zone type */
4331*5c51f124SMoriah Waterland 
4332*5c51f124SMoriah Waterland 	a = smlGetParamByTag(ntag, 0, TAG_COND_PARENT_ZONE, TAG_COND_ZONE_TYPE);
4333*5c51f124SMoriah Waterland 	(*r_gdt)->gd_parentZoneType = a;
4334*5c51f124SMoriah Waterland 
4335*5c51f124SMoriah Waterland 	/* current zone name */
4336*5c51f124SMoriah Waterland 
4337*5c51f124SMoriah Waterland 	a = smlGetParamByTag(ntag, 0, TAG_COND_CURRENT_ZONE,
4338*5c51f124SMoriah Waterland 		TAG_COND_ZONE_NAME);
4339*5c51f124SMoriah Waterland 	(*r_gdt)->gd_currentZoneName = a;
4340*5c51f124SMoriah Waterland 
4341*5c51f124SMoriah Waterland 	/* current zone type */
4342*5c51f124SMoriah Waterland 
4343*5c51f124SMoriah Waterland 	a = smlGetParamByTag(ntag, 0, TAG_COND_CURRENT_ZONE,
4344*5c51f124SMoriah Waterland 		TAG_COND_ZONE_TYPE);
4345*5c51f124SMoriah Waterland 	(*r_gdt)->gd_currentZoneType = a;
4346*5c51f124SMoriah Waterland 
4347*5c51f124SMoriah Waterland 	/* extract any inherited file systems */
4348*5c51f124SMoriah Waterland 
4349*5c51f124SMoriah Waterland 	for (n = 0; ; n++) {
4350*5c51f124SMoriah Waterland 		char	**ifs;
4351*5c51f124SMoriah Waterland 
4352*5c51f124SMoriah Waterland 		a = smlGetParamByTag(ntag, n, TAG_COND_INHERITED_FS,
4353*5c51f124SMoriah Waterland 			TAG_COND_FS_NAME);
4354*5c51f124SMoriah Waterland 
4355*5c51f124SMoriah Waterland 		if (a == NULL) {
4356*5c51f124SMoriah Waterland 			if (n > 0) {
4357*5c51f124SMoriah Waterland 				/* LINTED warning: variable may be used */
4358*5c51f124SMoriah Waterland 				(*r_gdt)->gd_inheritedFileSystems = ifs;
4359*5c51f124SMoriah Waterland 			}
4360*5c51f124SMoriah Waterland 			break;
4361*5c51f124SMoriah Waterland 		}
4362*5c51f124SMoriah Waterland 
4363*5c51f124SMoriah Waterland 		if (n == 0) {
4364*5c51f124SMoriah Waterland 			ifs = (char **)calloc(1, sizeof (char **)*(n+2));
4365*5c51f124SMoriah Waterland 			ifs[n] = a;
4366*5c51f124SMoriah Waterland 			ifs[n+1] = NULL;
4367*5c51f124SMoriah Waterland 		} else {
4368*5c51f124SMoriah Waterland 			ifs = (char **)realloc(ifs, sizeof (char **)*(n+2));
4369*5c51f124SMoriah Waterland 			ifs[n] = a;
4370*5c51f124SMoriah Waterland 			ifs[n+1] = NULL;
4371*5c51f124SMoriah Waterland 		}
4372*5c51f124SMoriah Waterland 	}
4373*5c51f124SMoriah Waterland 
4374*5c51f124SMoriah Waterland 	return (R_SUCCESS);
4375*5c51f124SMoriah Waterland }
4376*5c51f124SMoriah Waterland 
4377*5c51f124SMoriah Waterland /*
4378*5c51f124SMoriah Waterland  * Name:	dumpGlobalData
4379*5c51f124SMoriah Waterland  * Description:	dump global data structure using echoDebug
4380*5c51f124SMoriah Waterland  * Arguments:	a_gdt - pointer to global data structure to dump
4381*5c51f124SMoriah Waterland  * Outputs:	echoDebug is called to output global data strucutre information
4382*5c51f124SMoriah Waterland  * Returns:	void
4383*5c51f124SMoriah Waterland  */
4384*5c51f124SMoriah Waterland 
4385*5c51f124SMoriah Waterland static void
4386*5c51f124SMoriah Waterland dumpGlobalData(GLOBALDATA_T *a_gdt)
4387*5c51f124SMoriah Waterland {
4388*5c51f124SMoriah Waterland 	/* entry assertions */
4389*5c51f124SMoriah Waterland 
4390*5c51f124SMoriah Waterland 	assert(a_gdt != (GLOBALDATA_T *)NULL);
4391*5c51f124SMoriah Waterland 
4392*5c51f124SMoriah Waterland 	/* debugging enabled, dump the global data structure */
4393*5c51f124SMoriah Waterland 
4394*5c51f124SMoriah Waterland 	echoDebug(DBG_DUMP_GLOBAL_ENTRY);
4395*5c51f124SMoriah Waterland 	echoDebug(DBG_DUMP_GLOBAL_PARENT_ZONE,
4396*5c51f124SMoriah Waterland 		a_gdt->gd_parentZoneName ? a_gdt->gd_parentZoneName : "",
4397*5c51f124SMoriah Waterland 		a_gdt->gd_parentZoneType ? a_gdt->gd_parentZoneType : "");
4398*5c51f124SMoriah Waterland 	echoDebug(DBG_DUMP_GLOBAL_CURRENT_ZONE,
4399*5c51f124SMoriah Waterland 		a_gdt->gd_currentZoneName ? a_gdt->gd_currentZoneName : "",
4400*5c51f124SMoriah Waterland 		a_gdt->gd_currentZoneType ? a_gdt->gd_currentZoneType : "");
4401*5c51f124SMoriah Waterland 
4402*5c51f124SMoriah Waterland 	if (a_gdt->gd_inheritedFileSystems) {
4403*5c51f124SMoriah Waterland 		int n;
4404*5c51f124SMoriah Waterland 		char **ifs = a_gdt->gd_inheritedFileSystems;
4405*5c51f124SMoriah Waterland 		for (n = 0; ifs[n]; n++) {
4406*5c51f124SMoriah Waterland 			echoDebug(DBG_DUMP_GLOBAL_LINE, n, ifs[n]);
4407*5c51f124SMoriah Waterland 		}
4408*5c51f124SMoriah Waterland 	}
4409*5c51f124SMoriah Waterland }
4410*5c51f124SMoriah Waterland 
4411*5c51f124SMoriah Waterland /*
4412*5c51f124SMoriah Waterland  * Name:	recursionCheck
4413*5c51f124SMoriah Waterland  * Description:	prevent recursive calling of functions
4414*5c51f124SMoriah Waterland  * Arguments:	r_recursion - pointer to int recursion counter
4415*5c51f124SMoriah Waterland  *		a_function - pointer to name of function
4416*5c51f124SMoriah Waterland  * Returns:	B_TRUE - function is recursively called
4417*5c51f124SMoriah Waterland  *		B_FALSE - function not recursively called
4418*5c51f124SMoriah Waterland  */
4419*5c51f124SMoriah Waterland 
4420*5c51f124SMoriah Waterland static boolean_t
4421*5c51f124SMoriah Waterland recursionCheck(int *r_recursion, char *a_function)
4422*5c51f124SMoriah Waterland {
4423*5c51f124SMoriah Waterland 	/* prevent recursion */
4424*5c51f124SMoriah Waterland 
4425*5c51f124SMoriah Waterland 	(*r_recursion)++;
4426*5c51f124SMoriah Waterland 	if (*r_recursion > 1) {
4427*5c51f124SMoriah Waterland 		echoDebug(DBG_RECURSION, a_function, *r_recursion);
4428*5c51f124SMoriah Waterland 		(*r_recursion)--;
4429*5c51f124SMoriah Waterland 		return (B_TRUE);
4430*5c51f124SMoriah Waterland 	}
4431*5c51f124SMoriah Waterland 
4432*5c51f124SMoriah Waterland 	echoDebug(DBG_NO_RECURSION, a_function);
4433*5c51f124SMoriah Waterland 	return (B_FALSE);
4434*5c51f124SMoriah Waterland }
4435*5c51f124SMoriah Waterland 
4436*5c51f124SMoriah Waterland /*
4437*5c51f124SMoriah Waterland  * Name:	quit
4438*5c51f124SMoriah Waterland  * Description:	cleanup and exit
4439*5c51f124SMoriah Waterland  * Arguments:	a_retcode - the code to use to determine final exit status;
4440*5c51f124SMoriah Waterland  *			if this is NOT "99" and if a "ckreturnFunc" is
4441*5c51f124SMoriah Waterland  *			set, then that function is called with a_retcode
4442*5c51f124SMoriah Waterland  *			to set the final exit status.
4443*5c51f124SMoriah Waterland  *		Valid values are:
4444*5c51f124SMoriah Waterland  *		0 - success
4445*5c51f124SMoriah Waterland  *		1 - package operation failed (fatal error)
4446*5c51f124SMoriah Waterland  *		2 - non-fatal error (warning)
4447*5c51f124SMoriah Waterland  *		3 - user selected quit (operation interrupted)
4448*5c51f124SMoriah Waterland  *		4 - admin settings prevented operation
4449*5c51f124SMoriah Waterland  *		5 - interaction required and -n (non-interactive) specified
4450*5c51f124SMoriah Waterland  *		"10" is added to indicate "immediate reboot required"
4451*5c51f124SMoriah Waterland  *		"20" is be added to indicate "reboot after install required"
4452*5c51f124SMoriah Waterland  *		99 - do not interpret the code - just exit "99"
4453*5c51f124SMoriah Waterland  * Returns:	<<this function does not return - calls exit()>>
4454*5c51f124SMoriah Waterland  * NOTE:	This is needed because libinst functions can call "quit(99)"
4455*5c51f124SMoriah Waterland  *		to force an error exit.
4456*5c51f124SMoriah Waterland  */
4457*5c51f124SMoriah Waterland 
4458*5c51f124SMoriah Waterland void
4459*5c51f124SMoriah Waterland quit(int a_retcode)
4460*5c51f124SMoriah Waterland {
4461*5c51f124SMoriah Waterland 	/* process return code if not quit(99) */
4462*5c51f124SMoriah Waterland 
4463*5c51f124SMoriah Waterland 	if (a_retcode == 99) {
4464*5c51f124SMoriah Waterland 		exit(0x7f);	/* processing error (127) */
4465*5c51f124SMoriah Waterland 	}
4466*5c51f124SMoriah Waterland 
4467*5c51f124SMoriah Waterland 	exit(R_FAILURE);
4468*5c51f124SMoriah Waterland }
4469