xref: /titanic_51/usr/src/cmd/fm/fmtopo/common/fmtopo.c (revision aab83bb83be7342f6cfccaed8d5fe0b2f404855d)
17aec1d6eScindi /*
27aec1d6eScindi  * CDDL HEADER START
37aec1d6eScindi  *
47aec1d6eScindi  * The contents of this file are subject to the terms of the
57aec1d6eScindi  * Common Development and Distribution License (the "License").
67aec1d6eScindi  * You may not use this file except in compliance with the License.
77aec1d6eScindi  *
87aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi  * See the License for the specific language governing permissions
117aec1d6eScindi  * and limitations under the License.
127aec1d6eScindi  *
137aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi  *
197aec1d6eScindi  * CDDL HEADER END
207aec1d6eScindi  */
217aec1d6eScindi 
227aec1d6eScindi /*
23f6e214c7SGavin Maltby  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24*1410cb93SJoshua M. Clulow  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
257aec1d6eScindi  */
267aec1d6eScindi 
277aec1d6eScindi 
287aec1d6eScindi #include <sys/fm/protocol.h>
297aec1d6eScindi #include <fm/libtopo.h>
300eb822a1Scindi #include <ctype.h>
31c40d7343Scindi #include <fnmatch.h>
327aec1d6eScindi #include <limits.h>
337aec1d6eScindi #include <strings.h>
347aec1d6eScindi #include <stdio.h>
357aec1d6eScindi #include <errno.h>
36c40d7343Scindi #include <umem.h>
37f6e214c7SGavin Maltby #include <zone.h>
380eb822a1Scindi #include <sys/param.h>
397aec1d6eScindi 
407aec1d6eScindi #define	FMTOPO_EXIT_SUCCESS	0
417aec1d6eScindi #define	FMTOPO_EXIT_ERROR	1
427aec1d6eScindi #define	FMTOPO_EXIT_USAGE	2
437aec1d6eScindi 
440eb822a1Scindi #define	STDERR	"stderr"
450eb822a1Scindi #define	DOTS	"..."
460eb822a1Scindi #define	ALL	"all"
470eb822a1Scindi 
487aec1d6eScindi static const char *g_pname;
49c40d7343Scindi static const char *g_fmri = NULL;
507aec1d6eScindi 
517aec1d6eScindi static const char *opt_R = "/";
527aec1d6eScindi static const char *opt_s = FM_FMRI_SCHEME_HC;
53b6955755SRobert Johnston static const char optstr[] = "bCdem:P:pR:s:StVx";
54b6955755SRobert Johnston static const char *opt_m;
557aec1d6eScindi 
5678432d5eScy152378 static int opt_b = 0;
570eb822a1Scindi static int opt_d = 0;
5878432d5eScy152378 static int opt_e = 0;
590eb822a1Scindi static int opt_p = 0;
60c40d7343Scindi static int opt_S = 0;
61c40d7343Scindi static int opt_t = 0;
6278432d5eScy152378 static int opt_V = 0;
630eb822a1Scindi static int opt_x = 0;
64c40d7343Scindi static int opt_all = 0;
65c40d7343Scindi 
66c40d7343Scindi struct prop_args {
67c40d7343Scindi 	const char *group;
68c40d7343Scindi 	const char *prop;
69c40d7343Scindi 	const char *type;
70c40d7343Scindi 	const char *value;
71c40d7343Scindi };
72c40d7343Scindi 
73c40d7343Scindi static struct prop_args **pargs = NULL;
74c40d7343Scindi static int pcnt = 0;
757aec1d6eScindi 
767aec1d6eScindi static int
777aec1d6eScindi usage(FILE *fp)
787aec1d6eScindi {
797aec1d6eScindi 	(void) fprintf(fp,
80a38fc4eaSRobert Johnston 	    "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] "
81b6955755SRobert Johnston 	    "[-R root] [-m method] [-s scheme] [fmri]\n", g_pname);
827aec1d6eScindi 
837aec1d6eScindi 	(void) fprintf(fp,
8478432d5eScy152378 	    "\t-b  walk in sibling-first order (default is child-first)\n"
857aec1d6eScindi 	    "\t-C  dump core after completing execution\n"
860eb822a1Scindi 	    "\t-d  set debug mode for libtopo modules\n"
870eb822a1Scindi 	    "\t-e  display FMRIs as paths using esc/eft notation\n"
88b6955755SRobert Johnston 	    "\t-m  execute given method\n"
89c40d7343Scindi 	    "\t-P  get/set specified properties\n"
900eb822a1Scindi 	    "\t-p  display of FMRI protocol properties\n"
917aec1d6eScindi 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
927aec1d6eScindi 	    "\t-s  display topology for the specified FMRI scheme\n"
93c40d7343Scindi 	    "\t-S  display FMRI status (present/usable)\n"
940eb822a1Scindi 	    "\t-V  set verbose mode\n"
950eb822a1Scindi 	    "\t-x  display a xml formatted topology\n");
967aec1d6eScindi 
977aec1d6eScindi 	return (FMTOPO_EXIT_USAGE);
987aec1d6eScindi }
997aec1d6eScindi 
100c40d7343Scindi static topo_type_t
101c40d7343Scindi str2type(const char *tstr)
1027aec1d6eScindi {
103c40d7343Scindi 	topo_type_t type;
1047aec1d6eScindi 
105c40d7343Scindi 	if (tstr == NULL)
106c40d7343Scindi 		return (TOPO_TYPE_INVALID);
107c40d7343Scindi 
108c40d7343Scindi 	if (strcmp(tstr, "int32") == 0)
109c40d7343Scindi 		type = TOPO_TYPE_INT32;
110c40d7343Scindi 	else if (strcmp(tstr, "uint32") == 0)
111c40d7343Scindi 		type = TOPO_TYPE_UINT32;
112c40d7343Scindi 	else if (strcmp(tstr, "int64") == 0)
113c40d7343Scindi 		type = TOPO_TYPE_INT64;
114c40d7343Scindi 	else if (strcmp(tstr, "uint64") == 0)
115c40d7343Scindi 		type = TOPO_TYPE_UINT64;
116c40d7343Scindi 	else if (strcmp(tstr, "string") == 0)
117c40d7343Scindi 		type = TOPO_TYPE_STRING;
118c40d7343Scindi 	else if (strcmp(tstr, "fmri") == 0)
119c40d7343Scindi 		type = TOPO_TYPE_FMRI;
120c40d7343Scindi 	else {
121c40d7343Scindi 		type = TOPO_TYPE_INVALID;
1227aec1d6eScindi 	}
1237aec1d6eScindi 
124c40d7343Scindi 	return (type);
1257aec1d6eScindi }
1267aec1d6eScindi 
127c40d7343Scindi static void
128c40d7343Scindi print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri)
129c40d7343Scindi {
130c40d7343Scindi 	int err, ret;
1317aec1d6eScindi 
132c40d7343Scindi 	(void) printf("%s\n", (char *)fmri);
133c40d7343Scindi 
134c40d7343Scindi 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
1357aec1d6eScindi 		char *aname = NULL, *fname = NULL, *lname = NULL;
1367aec1d6eScindi 		nvlist_t *asru = NULL;
1377aec1d6eScindi 		nvlist_t *fru = NULL;
1387aec1d6eScindi 
1397aec1d6eScindi 		if (topo_node_asru(node, &asru, NULL, &err) == 0)
1407aec1d6eScindi 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
1417aec1d6eScindi 		if (topo_node_fru(node, &fru, NULL, &err) == 0)
1427aec1d6eScindi 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
1437aec1d6eScindi 		(void) topo_node_label(node, &lname, &err);
1447aec1d6eScindi 		if (aname != NULL) {
1457aec1d6eScindi 			nvlist_free(asru);
1467aec1d6eScindi 			(void) printf("\tASRU: %s\n", aname);
1477aec1d6eScindi 			topo_hdl_strfree(thp, aname);
1487aec1d6eScindi 		} else {
1497aec1d6eScindi 			(void) printf("\tASRU: -\n");
1507aec1d6eScindi 		}
1517aec1d6eScindi 		if (fname != NULL) {
1527aec1d6eScindi 			nvlist_free(fru);
1537aec1d6eScindi 			(void) printf("\tFRU: %s\n", fname);
1547aec1d6eScindi 			topo_hdl_strfree(thp, fname);
1557aec1d6eScindi 		} else {
1567aec1d6eScindi 			(void) printf("\tFRU: -\n");
1577aec1d6eScindi 		}
1587aec1d6eScindi 		if (lname != NULL) {
1597aec1d6eScindi 			(void) printf("\tLabel: %s\n", lname);
1607aec1d6eScindi 			topo_hdl_strfree(thp, lname);
1617aec1d6eScindi 		} else {
1627aec1d6eScindi 			(void) printf("\tLabel: -\n");
1637aec1d6eScindi 		}
1647aec1d6eScindi 	}
1657aec1d6eScindi 
166c40d7343Scindi 	if (opt_S) {
167c40d7343Scindi 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
168c40d7343Scindi 			(void) printf("\tPresent: -\n");
169c40d7343Scindi 		else
170c40d7343Scindi 			(void) printf("\tPresent: %s\n",
171c40d7343Scindi 			    ret ? "true" : "false");
172c40d7343Scindi 
173c40d7343Scindi 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
174c40d7343Scindi 			(void) printf("\tUnusable: -\n");
175c40d7343Scindi 		else
176c40d7343Scindi 			(void) printf("\tUnusable: %s\n",
177c40d7343Scindi 			    ret ? "true" : "false");
178c40d7343Scindi 	}
1797aec1d6eScindi }
1807aec1d6eScindi 
1817aec1d6eScindi static void
1827aec1d6eScindi print_everstyle(tnode_t *node)
1837aec1d6eScindi {
1847aec1d6eScindi 	char buf[PATH_MAX], numbuf[64];
1857aec1d6eScindi 	nvlist_t *fmri, **hcl;
1867aec1d6eScindi 	int i, err;
1877aec1d6eScindi 	uint_t n;
1887aec1d6eScindi 
1897aec1d6eScindi 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
1907aec1d6eScindi 	    TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
1917aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
1927aec1d6eScindi 		    g_pname, topo_node_name(node),
1937aec1d6eScindi 		    topo_node_instance(node), topo_strerror(err));
1947aec1d6eScindi 		return;
1957aec1d6eScindi 	}
1967aec1d6eScindi 
1977aec1d6eScindi 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
1987aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
1997aec1d6eScindi 		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
2007aec1d6eScindi 		    topo_node_instance(node));
201825ba0f2Srobj 		nvlist_free(fmri);
2027aec1d6eScindi 		return;
2037aec1d6eScindi 	}
2047aec1d6eScindi 
2057aec1d6eScindi 	buf[0] = '\0';
2067aec1d6eScindi 
2077aec1d6eScindi 	for (i = 0; i < n; i++) {
2087aec1d6eScindi 		char *name, *inst, *estr;
2097aec1d6eScindi 		ulong_t ul;
2107aec1d6eScindi 
2117aec1d6eScindi 		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
2127aec1d6eScindi 		    nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
2137aec1d6eScindi 			(void) fprintf(stderr, "%s: failed to get "
2147aec1d6eScindi 			    "name-instance for %s=%d\n", g_pname,
2157aec1d6eScindi 			    topo_node_name(node), topo_node_instance(node));
216825ba0f2Srobj 			nvlist_free(fmri);
2177aec1d6eScindi 			return;
2187aec1d6eScindi 		}
2197aec1d6eScindi 
2207aec1d6eScindi 		errno = 0;
2217aec1d6eScindi 		ul = strtoul(inst, &estr, 10);
2227aec1d6eScindi 
2237aec1d6eScindi 		if (errno != 0 || estr == inst) {
2247aec1d6eScindi 			(void) fprintf(stderr, "%s: instance %s does not "
2257aec1d6eScindi 			    "convert to an unsigned integer\n", g_pname, inst);
2267aec1d6eScindi 		}
2277aec1d6eScindi 
2287aec1d6eScindi 		(void) strlcat(buf, "/", sizeof (buf));
2297aec1d6eScindi 		(void) strlcat(buf, name, sizeof (buf));
2307aec1d6eScindi 		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
2317aec1d6eScindi 		(void) strlcat(buf, numbuf, sizeof (buf));
2327aec1d6eScindi 	}
233825ba0f2Srobj 	nvlist_free(fmri);
2347aec1d6eScindi 
2357aec1d6eScindi 	(void) printf("%s\n", buf);
2367aec1d6eScindi }
2377aec1d6eScindi 
2380eb822a1Scindi static void
239825ba0f2Srobj print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl)
2400eb822a1Scindi {
2410eb822a1Scindi 	int err;
2420eb822a1Scindi 	topo_type_t type;
243825ba0f2Srobj 	char *tstr, *propn, buf[48], *factype;
2440eb822a1Scindi 	nvpair_t *pv_nvp;
2459dd0f810Scindi 	int i;
2469dd0f810Scindi 	uint_t nelem;
2470eb822a1Scindi 
2480eb822a1Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL)
2490eb822a1Scindi 		return;
2500eb822a1Scindi 
2510eb822a1Scindi 	/* Print property name */
2520eb822a1Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL ||
2530eb822a1Scindi 	    nvpair_name(pv_nvp) == NULL ||
2540eb822a1Scindi 	    strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) {
2550eb822a1Scindi 		(void) fprintf(stderr, "%s: malformed property name\n",
2560eb822a1Scindi 		    g_pname);
2570eb822a1Scindi 		return;
2580eb822a1Scindi 	} else {
2590eb822a1Scindi 		(void) nvpair_value_string(pv_nvp, &propn);
2600eb822a1Scindi 	}
2610eb822a1Scindi 
2620eb822a1Scindi 	if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL ||
2630eb822a1Scindi 	    nvpair_name(pv_nvp) == NULL ||
2640eb822a1Scindi 	    strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 ||
265c40d7343Scindi 	    nvpair_type(pv_nvp) != DATA_TYPE_UINT32)  {
2660eb822a1Scindi 		(void) fprintf(stderr, "%s: malformed property type for %s\n",
2670eb822a1Scindi 		    g_pname, propn);
2680eb822a1Scindi 		return;
2690eb822a1Scindi 	} else {
270c40d7343Scindi 		(void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type);
2710eb822a1Scindi 	}
2720eb822a1Scindi 
2730eb822a1Scindi 	switch (type) {
2740eb822a1Scindi 		case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break;
2750eb822a1Scindi 		case TOPO_TYPE_INT32: tstr = "int32"; break;
2760eb822a1Scindi 		case TOPO_TYPE_UINT32: tstr = "uint32"; break;
2770eb822a1Scindi 		case TOPO_TYPE_INT64: tstr = "int64"; break;
2780eb822a1Scindi 		case TOPO_TYPE_UINT64: tstr = "uint64"; break;
279825ba0f2Srobj 		case TOPO_TYPE_DOUBLE: tstr = "double"; break;
2800eb822a1Scindi 		case TOPO_TYPE_STRING: tstr = "string"; break;
2810eb822a1Scindi 		case TOPO_TYPE_FMRI: tstr = "fmri"; break;
2820eb822a1Scindi 		case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
2830eb822a1Scindi 		case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break;
2840eb822a1Scindi 		case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break;
2850eb822a1Scindi 		case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break;
2860eb822a1Scindi 		case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break;
2870eb822a1Scindi 		case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break;
2880eb822a1Scindi 		default: tstr = "unknown type";
2890eb822a1Scindi 	}
2900eb822a1Scindi 
291888e0559SRobert Johnston 	(void) printf("    %-17s %-8s ", propn, tstr);
2920eb822a1Scindi 
2930eb822a1Scindi 	/*
2940eb822a1Scindi 	 * Get property value
2950eb822a1Scindi 	 */
2960eb822a1Scindi 	if (nvpair_name(pv_nvp) == NULL ||
2970eb822a1Scindi 	    (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) {
2980eb822a1Scindi 		(void) fprintf(stderr, "%s: malformed property value\n",
2990eb822a1Scindi 		    g_pname);
3000eb822a1Scindi 		return;
3010eb822a1Scindi 	}
3020eb822a1Scindi 
3030eb822a1Scindi 	switch (nvpair_type(pv_nvp)) {
3040eb822a1Scindi 		case DATA_TYPE_INT32: {
3050eb822a1Scindi 			int32_t val;
3060eb822a1Scindi 			(void) nvpair_value_int32(pv_nvp, &val);
3070eb822a1Scindi 			(void) printf(" %d", val);
3080eb822a1Scindi 			break;
3090eb822a1Scindi 		}
3100eb822a1Scindi 		case DATA_TYPE_UINT32: {
311825ba0f2Srobj 			uint32_t val, type;
312825ba0f2Srobj 			char val_str[49];
313825ba0f2Srobj 			nvlist_t *fac, *rsrc = NULL;
314825ba0f2Srobj 
3150eb822a1Scindi 			(void) nvpair_value_uint32(pv_nvp, &val);
316825ba0f2Srobj 			if (node == NULL || topo_node_flags(node) !=
317825ba0f2Srobj 			    TOPO_NODE_FACILITY)
318825ba0f2Srobj 				goto uint32_def;
319825ba0f2Srobj 
320825ba0f2Srobj 			if (topo_node_resource(node, &rsrc, &err) != 0)
321825ba0f2Srobj 				goto uint32_def;
322825ba0f2Srobj 
323825ba0f2Srobj 			if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0)
324825ba0f2Srobj 				goto uint32_def;
325825ba0f2Srobj 
326825ba0f2Srobj 			if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
327825ba0f2Srobj 			    &factype) != 0)
328825ba0f2Srobj 				goto uint32_def;
329825ba0f2Srobj 
330825ba0f2Srobj 			nvlist_free(rsrc);
331825ba0f2Srobj 			rsrc = NULL;
332825ba0f2Srobj 
333825ba0f2Srobj 			/*
334825ba0f2Srobj 			 * Special case code to do friendlier printing of
335825ba0f2Srobj 			 * facility node properties
336825ba0f2Srobj 			 */
337825ba0f2Srobj 			if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
338825ba0f2Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
339825ba0f2Srobj 				topo_sensor_type_name(val, val_str, 48);
340825ba0f2Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
341825ba0f2Srobj 				break;
342825ba0f2Srobj 			} else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
343825ba0f2Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) {
344825ba0f2Srobj 				topo_led_type_name(val, val_str, 48);
345825ba0f2Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
346825ba0f2Srobj 				break;
347825ba0f2Srobj 			} else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) {
348825ba0f2Srobj 				topo_sensor_units_name(val, val_str, 48);
349825ba0f2Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
350825ba0f2Srobj 				break;
351825ba0f2Srobj 			} else if (strcmp(propn, TOPO_LED_MODE) == 0) {
352825ba0f2Srobj 				topo_led_state_name(val, val_str, 48);
353825ba0f2Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
354825ba0f2Srobj 				break;
355825ba0f2Srobj 			} else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) &&
356825ba0f2Srobj 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
357825ba0f2Srobj 				if (topo_prop_get_uint32(node,
358825ba0f2Srobj 				    TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
359825ba0f2Srobj 				    &type, &err) != 0) {
360825ba0f2Srobj 					goto uint32_def;
361825ba0f2Srobj 				}
362825ba0f2Srobj 				topo_sensor_state_name(type, val, val_str, 48);
363825ba0f2Srobj 				(void) printf(" 0x%x (%s)", val, val_str);
364825ba0f2Srobj 				break;
365825ba0f2Srobj 			}
366825ba0f2Srobj uint32_def:
3670eb822a1Scindi 			(void) printf(" 0x%x", val);
368825ba0f2Srobj 			nvlist_free(rsrc);
3690eb822a1Scindi 			break;
3700eb822a1Scindi 		}
3710eb822a1Scindi 		case DATA_TYPE_INT64: {
3720eb822a1Scindi 			int64_t val;
3730eb822a1Scindi 			(void) nvpair_value_int64(pv_nvp, &val);
3740eb822a1Scindi 			(void) printf(" %lld", (longlong_t)val);
3750eb822a1Scindi 			break;
3760eb822a1Scindi 		}
3770eb822a1Scindi 		case DATA_TYPE_UINT64: {
3780eb822a1Scindi 			uint64_t val;
3790eb822a1Scindi 			(void) nvpair_value_uint64(pv_nvp, &val);
3800eb822a1Scindi 			(void) printf(" 0x%llx", (u_longlong_t)val);
3810eb822a1Scindi 			break;
3820eb822a1Scindi 		}
383825ba0f2Srobj 		case DATA_TYPE_DOUBLE: {
384825ba0f2Srobj 			double val;
385825ba0f2Srobj 			(void) nvpair_value_double(pv_nvp, &val);
386825ba0f2Srobj 			(void) printf(" %lf", (double)val);
387825ba0f2Srobj 			break;
388825ba0f2Srobj 		}
3890eb822a1Scindi 		case DATA_TYPE_STRING: {
3900eb822a1Scindi 			char *val;
3910eb822a1Scindi 			(void) nvpair_value_string(pv_nvp, &val);
3920eb822a1Scindi 			if (!opt_V && strlen(val) > 48) {
3930eb822a1Scindi 				(void) snprintf(buf, 48, "%s...", val);
3940eb822a1Scindi 				(void) printf(" %s", buf);
3950eb822a1Scindi 			} else {
3960eb822a1Scindi 				(void) printf(" %s", val);
3970eb822a1Scindi 			}
3980eb822a1Scindi 			break;
3990eb822a1Scindi 		}
4000eb822a1Scindi 		case DATA_TYPE_NVLIST: {
4010eb822a1Scindi 			nvlist_t *val;
4020eb822a1Scindi 			char *fmri;
4030eb822a1Scindi 			(void) nvpair_value_nvlist(pv_nvp, &val);
4040eb822a1Scindi 			if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) {
4050eb822a1Scindi 				if (opt_V)
4060eb822a1Scindi 					nvlist_print(stdout, nvl);
4070eb822a1Scindi 				break;
4080eb822a1Scindi 			}
4090eb822a1Scindi 
4100eb822a1Scindi 			if (!opt_V && strlen(fmri) > 48) {
4110eb822a1Scindi 				(void) snprintf(buf, 48, "%s", fmri);
4120eb822a1Scindi 				(void) snprintf(&buf[45], 4, "%s", DOTS);
4130eb822a1Scindi 				(void) printf(" %s", buf);
4140eb822a1Scindi 			} else {
4150eb822a1Scindi 				(void) printf(" %s", fmri);
4160eb822a1Scindi 			}
4170eb822a1Scindi 
4180eb822a1Scindi 			topo_hdl_strfree(thp, fmri);
4190eb822a1Scindi 			break;
4200eb822a1Scindi 		}
42188045cffSRobert Johnston 		case DATA_TYPE_INT32_ARRAY: {
42288045cffSRobert Johnston 			int32_t *val;
42388045cffSRobert Johnston 
42488045cffSRobert Johnston 			(void) nvpair_value_int32_array(pv_nvp, &val, &nelem);
42588045cffSRobert Johnston 			(void) printf(" [ ");
42688045cffSRobert Johnston 			for (i = 0; i < nelem; i++)
42788045cffSRobert Johnston 				(void) printf("%d ", val[i]);
42888045cffSRobert Johnston 			(void) printf("]");
42988045cffSRobert Johnston 			break;
43088045cffSRobert Johnston 		}
4319dd0f810Scindi 		case DATA_TYPE_UINT32_ARRAY: {
4329dd0f810Scindi 			uint32_t *val;
4339dd0f810Scindi 
4349dd0f810Scindi 			(void) nvpair_value_uint32_array(pv_nvp, &val, &nelem);
4359dd0f810Scindi 			(void) printf(" [ ");
4369dd0f810Scindi 			for (i = 0; i < nelem; i++)
4379dd0f810Scindi 				(void) printf("%u ", val[i]);
4389dd0f810Scindi 			(void) printf("]");
4399dd0f810Scindi 			break;
4409dd0f810Scindi 		}
441825ba0f2Srobj 		case DATA_TYPE_INT64_ARRAY: {
442825ba0f2Srobj 			int64_t *val;
443825ba0f2Srobj 
444825ba0f2Srobj 			(void) nvpair_value_int64_array(pv_nvp, &val, &nelem);
445825ba0f2Srobj 			(void) printf(" [ ");
446825ba0f2Srobj 			for (i = 0; i < nelem; i++)
447825ba0f2Srobj 				(void) printf("%lld ", val[i]);
448825ba0f2Srobj 			(void) printf("]");
449825ba0f2Srobj 			break;
450825ba0f2Srobj 		}
45188045cffSRobert Johnston 		case DATA_TYPE_UINT64_ARRAY: {
45288045cffSRobert Johnston 			uint64_t *val;
45388045cffSRobert Johnston 
45488045cffSRobert Johnston 			(void) nvpair_value_uint64_array(pv_nvp, &val, &nelem);
45588045cffSRobert Johnston 			(void) printf(" [ ");
45688045cffSRobert Johnston 			for (i = 0; i < nelem; i++)
45788045cffSRobert Johnston 				(void) printf("%llu ", val[i]);
45888045cffSRobert Johnston 			(void) printf("]");
45988045cffSRobert Johnston 			break;
46088045cffSRobert Johnston 		}
461602ca9eaScth 		case DATA_TYPE_STRING_ARRAY: {
462602ca9eaScth 			char **val;
463602ca9eaScth 
464602ca9eaScth 			(void) nvpair_value_string_array(pv_nvp, &val, &nelem);
465602ca9eaScth 			(void) printf(" [ ");
466602ca9eaScth 			for (i = 0; i < nelem; i++)
46788045cffSRobert Johnston 				(void) printf("\"%s\" ", val[i]);
468602ca9eaScth 			(void) printf("]");
469602ca9eaScth 			break;
470602ca9eaScth 		}
4710eb822a1Scindi 		default:
4720eb822a1Scindi 			(void) fprintf(stderr, " unknown data type (%d)",
4730eb822a1Scindi 			    nvpair_type(pv_nvp));
4740eb822a1Scindi 			break;
4750eb822a1Scindi 		}
4760eb822a1Scindi 		(void) printf("\n");
4770eb822a1Scindi }
4780eb822a1Scindi 
4790eb822a1Scindi static void
480c40d7343Scindi print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab,
481c40d7343Scindi     char *nstab, int32_t version)
4820eb822a1Scindi {
483c40d7343Scindi 	int err;
4840eb822a1Scindi 	char buf[30];
485c40d7343Scindi 	topo_pgroup_info_t *pgi = NULL;
4860eb822a1Scindi 
487c40d7343Scindi 	if (pgn == NULL)
4880eb822a1Scindi 		return;
4890eb822a1Scindi 
490c40d7343Scindi 	if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) {
491c40d7343Scindi 		if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) {
492c40d7343Scindi 			dstab = (char *)topo_stability2name(pgi->tpi_datastab);
493c40d7343Scindi 			nstab = (char *)topo_stability2name(pgi->tpi_namestab);
494c40d7343Scindi 			version = pgi->tpi_version;
495c40d7343Scindi 		}
496c40d7343Scindi 	}
497c40d7343Scindi 
498c40d7343Scindi 	if (dstab == NULL || nstab == NULL || version == -1) {
499888e0559SRobert Johnston 		(void) printf("  group: %-30s version: - stability: -/-\n",
500888e0559SRobert Johnston 		    pgn);
501c40d7343Scindi 	} else if (!opt_V && strlen(pgn) > 30) {
5020eb822a1Scindi 		(void) snprintf(buf, 26, "%s", pgn);
5030eb822a1Scindi 		(void) snprintf(&buf[27], 4, "%s", DOTS);
504888e0559SRobert Johnston 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
5050eb822a1Scindi 		    buf, version, nstab, dstab);
5060eb822a1Scindi 	} else {
507888e0559SRobert Johnston 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
5080eb822a1Scindi 		    pgn, version, nstab, dstab);
5090eb822a1Scindi 	}
510c40d7343Scindi 
511c40d7343Scindi 	if (pgi != NULL) {
512c40d7343Scindi 		topo_hdl_strfree(thp, (char *)pgi->tpi_name);
513c40d7343Scindi 		topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t));
5140eb822a1Scindi 	}
5150eb822a1Scindi }
5160eb822a1Scindi 
5170eb822a1Scindi static void
518c40d7343Scindi print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv,
519c40d7343Scindi     const char *group)
5200eb822a1Scindi {
5210eb822a1Scindi 	char *pgn = NULL, *dstab = NULL, *nstab = NULL;
522c40d7343Scindi 	int32_t version;
5230eb822a1Scindi 	nvlist_t *pg_nv, *pv_nv;
5240eb822a1Scindi 	nvpair_t *nvp, *pg_nvp;
525c40d7343Scindi 	int pg_done, match, all = strcmp(group, ALL) == 0;
5260eb822a1Scindi 
5270eb822a1Scindi 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
5280eb822a1Scindi 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
5290eb822a1Scindi 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
5300eb822a1Scindi 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
5310eb822a1Scindi 			continue;
5320eb822a1Scindi 
533c40d7343Scindi 		nstab = NULL;
534c40d7343Scindi 		dstab = NULL;
535c40d7343Scindi 		version = -1;
536c40d7343Scindi 		pg_done = match = 0;
5370eb822a1Scindi 		(void) nvpair_value_nvlist(nvp, &pg_nv);
5380eb822a1Scindi 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
5390eb822a1Scindi 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
5400eb822a1Scindi 			/*
5410eb822a1Scindi 			 * Print property group name and stability levels
5420eb822a1Scindi 			 */
5430eb822a1Scindi 			if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp))
5440eb822a1Scindi 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5450eb822a1Scindi 				(void) nvpair_value_string(pg_nvp, &pgn);
546c40d7343Scindi 				match = strcmp(group, pgn) == 0;
547c40d7343Scindi 				continue;
548c40d7343Scindi 			}
5490eb822a1Scindi 
550c40d7343Scindi 			if (strcmp(TOPO_PROP_GROUP_NSTAB,
5510eb822a1Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5520eb822a1Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5530eb822a1Scindi 				(void) nvpair_value_string(pg_nvp, &nstab);
554c40d7343Scindi 				continue;
555c40d7343Scindi 			}
556c40d7343Scindi 
557c40d7343Scindi 			if (strcmp(TOPO_PROP_GROUP_DSTAB,
5580eb822a1Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5590eb822a1Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5600eb822a1Scindi 				(void) nvpair_value_string(pg_nvp, &dstab);
561c40d7343Scindi 				continue;
562c40d7343Scindi 			}
563c40d7343Scindi 
564c40d7343Scindi 			if (strcmp(TOPO_PROP_GROUP_VERSION,
5650eb822a1Scindi 			    nvpair_name(pg_nvp)) == 0 &&
5660eb822a1Scindi 			    nvpair_type(pg_nvp) == DATA_TYPE_INT32) {
5670eb822a1Scindi 				(void) nvpair_value_int32(pg_nvp, &version);
5680eb822a1Scindi 				continue;
5690eb822a1Scindi 			}
570c40d7343Scindi 
571c40d7343Scindi 			if ((match || all) && !pg_done) {
572c40d7343Scindi 				print_pgroup(thp, node, pgn, dstab, nstab,
573c40d7343Scindi 				    version);
574c40d7343Scindi 				pg_done++;
575c40d7343Scindi 			}
576c40d7343Scindi 
5770eb822a1Scindi 			/*
578c40d7343Scindi 			 * Print property group and property name-value pair
5790eb822a1Scindi 			 */
580c40d7343Scindi 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp))
5810eb822a1Scindi 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
5820eb822a1Scindi 				(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
583c40d7343Scindi 				if ((match || all) && pg_done) {
584825ba0f2Srobj 					print_prop_nameval(thp, node, pv_nv);
585c40d7343Scindi 				}
5860eb822a1Scindi 
5870eb822a1Scindi 			}
588c40d7343Scindi 
5890eb822a1Scindi 		}
590c40d7343Scindi 		if (match && !all)
591c40d7343Scindi 			return;
592c40d7343Scindi 	}
593c40d7343Scindi }
594c40d7343Scindi 
595c40d7343Scindi static void
596c40d7343Scindi set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp)
597c40d7343Scindi {
598c40d7343Scindi 	int ret, err = 0;
599c40d7343Scindi 	topo_type_t type;
600*1410cb93SJoshua M. Clulow 	nvlist_t *nvl = NULL;
601c40d7343Scindi 	char *end;
602c40d7343Scindi 
603c40d7343Scindi 	if (pp->prop == NULL || pp->type == NULL || pp->value == NULL)
604*1410cb93SJoshua M. Clulow 		goto out;
605c40d7343Scindi 
606c40d7343Scindi 	if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) {
607c40d7343Scindi 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
608c40d7343Scindi 		    g_pname, pp->type, pp->prop);
609*1410cb93SJoshua M. Clulow 		goto out;
610c40d7343Scindi 	}
611c40d7343Scindi 
612c40d7343Scindi 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
613c40d7343Scindi 		(void) fprintf(stderr, "%s: nvlist allocation failed for "
614c40d7343Scindi 		    "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value);
615*1410cb93SJoshua M. Clulow 		goto out;
616c40d7343Scindi 	}
617c40d7343Scindi 	ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop);
618c40d7343Scindi 	ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
619c40d7343Scindi 	if (ret != 0) {
620c40d7343Scindi 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
621c40d7343Scindi 		    g_pname, pp->type, pp->prop);
622*1410cb93SJoshua M. Clulow 		goto out;
623c40d7343Scindi 	}
624c40d7343Scindi 
625c40d7343Scindi 	errno = 0;
626c40d7343Scindi 	switch (type) {
627c40d7343Scindi 		case TOPO_TYPE_INT32:
628c40d7343Scindi 		{
629c40d7343Scindi 			int32_t val;
630c40d7343Scindi 
631c40d7343Scindi 			val = strtol(pp->value, &end, 0);
632c40d7343Scindi 			if (errno == ERANGE) {
633c40d7343Scindi 				ret = -1;
634c40d7343Scindi 				break;
635c40d7343Scindi 			}
636c40d7343Scindi 			ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
637c40d7343Scindi 			break;
638c40d7343Scindi 		}
639c40d7343Scindi 		case TOPO_TYPE_UINT32:
640c40d7343Scindi 		{
641c40d7343Scindi 			uint32_t val;
642c40d7343Scindi 
643c40d7343Scindi 			val = strtoul(pp->value, &end, 0);
644c40d7343Scindi 			if (errno == ERANGE) {
645c40d7343Scindi 				ret = -1;
646c40d7343Scindi 				break;
647c40d7343Scindi 			}
648c40d7343Scindi 			ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
649c40d7343Scindi 			break;
650c40d7343Scindi 		}
651c40d7343Scindi 		case TOPO_TYPE_INT64:
652c40d7343Scindi 		{
653c40d7343Scindi 			int64_t val;
654c40d7343Scindi 
655c40d7343Scindi 			val = strtoll(pp->value, &end, 0);
656c40d7343Scindi 			if (errno == ERANGE) {
657c40d7343Scindi 				ret = -1;
658c40d7343Scindi 				break;
659c40d7343Scindi 			}
660c40d7343Scindi 			ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
661c40d7343Scindi 			break;
662c40d7343Scindi 		}
663c40d7343Scindi 		case TOPO_TYPE_UINT64:
664c40d7343Scindi 		{
665c40d7343Scindi 			uint64_t val;
666c40d7343Scindi 
667c40d7343Scindi 			val = strtoull(pp->value, &end, 0);
668c40d7343Scindi 			if (errno == ERANGE) {
669c40d7343Scindi 				ret = -1;
670c40d7343Scindi 				break;
671c40d7343Scindi 			}
672c40d7343Scindi 			ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
673c40d7343Scindi 			break;
674c40d7343Scindi 		}
675c40d7343Scindi 		case TOPO_TYPE_STRING:
676c40d7343Scindi 		{
677c40d7343Scindi 			ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
678c40d7343Scindi 			    pp->value);
679c40d7343Scindi 			break;
680c40d7343Scindi 		}
681c40d7343Scindi 		case TOPO_TYPE_FMRI:
682c40d7343Scindi 		{
683*1410cb93SJoshua M. Clulow 			nvlist_t *val = NULL;
684*1410cb93SJoshua M. Clulow 
685*1410cb93SJoshua M. Clulow 			if ((ret = topo_fmri_str2nvl(thp, pp->value, &val,
686*1410cb93SJoshua M. Clulow 			    &err)) < 0)
687c40d7343Scindi 				break;
688c40d7343Scindi 
689c40d7343Scindi 			if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
690*1410cb93SJoshua M. Clulow 			    val)) != 0)
691c40d7343Scindi 				err = ETOPO_PROP_NVL;
692*1410cb93SJoshua M. Clulow 
693*1410cb93SJoshua M. Clulow 			nvlist_free(val);
694c40d7343Scindi 			break;
695c40d7343Scindi 		}
696c40d7343Scindi 		default:
697c40d7343Scindi 			ret = -1;
698c40d7343Scindi 	}
699c40d7343Scindi 
700c40d7343Scindi 	if (ret != 0) {
701c40d7343Scindi 		(void) fprintf(stderr, "%s: unable to set property value for "
702c40d7343Scindi 		    "%s: %s\n", g_pname, pp->prop,  topo_strerror(err));
703*1410cb93SJoshua M. Clulow 		goto out;
704c40d7343Scindi 	}
705c40d7343Scindi 
706c40d7343Scindi 	if (node != NULL) {
707*1410cb93SJoshua M. Clulow 		if ((ret = topo_prop_setprop(node, pp->group, nvl,
708*1410cb93SJoshua M. Clulow 		    TOPO_PROP_MUTABLE, nvl, &err)) < 0) {
709c40d7343Scindi 			(void) fprintf(stderr, "%s: unable to set property "
710c40d7343Scindi 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
711*1410cb93SJoshua M. Clulow 			    pp->type, pp->value, topo_strerror(err));
712*1410cb93SJoshua M. Clulow 			goto out;
713c40d7343Scindi 		}
714c40d7343Scindi 	} else {
715*1410cb93SJoshua M. Clulow 		if ((ret = topo_fmri_setprop(thp, fmri,  pp->group, nvl,
716*1410cb93SJoshua M. Clulow 		    TOPO_PROP_MUTABLE, nvl, &err)) < 0) {
717c40d7343Scindi 			(void) fprintf(stderr, "%s: unable to set property "
718c40d7343Scindi 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
719*1410cb93SJoshua M. Clulow 			    pp->type, pp->value, topo_strerror(err));
720*1410cb93SJoshua M. Clulow 			goto out;
721c40d7343Scindi 		}
722c40d7343Scindi 	}
723c40d7343Scindi 
724c40d7343Scindi 	nvlist_free(nvl);
725*1410cb93SJoshua M. Clulow 	nvl = NULL;
726c40d7343Scindi 
727c40d7343Scindi 	/*
728c40d7343Scindi 	 * Now, get the property back for printing
729c40d7343Scindi 	 */
730c40d7343Scindi 	if (node != NULL) {
731*1410cb93SJoshua M. Clulow 		if ((ret = topo_prop_getprop(node, pp->group, pp->prop, NULL,
732*1410cb93SJoshua M. Clulow 		    &nvl, &err)) < 0) {
733c40d7343Scindi 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
734c40d7343Scindi 			    g_pname, pp->group, pp->prop, topo_strerror(err));
735*1410cb93SJoshua M. Clulow 			goto out;
736c40d7343Scindi 		}
737c40d7343Scindi 	} else {
738*1410cb93SJoshua M. Clulow 		if ((ret = topo_fmri_getprop(thp, fmri, pp->group, pp->prop,
739*1410cb93SJoshua M. Clulow 		    NULL, &nvl, &err)) < 0) {
740c40d7343Scindi 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
741c40d7343Scindi 			    g_pname, pp->group, pp->prop, topo_strerror(err));
742*1410cb93SJoshua M. Clulow 			goto out;
743c40d7343Scindi 		}
744c40d7343Scindi 	}
745c40d7343Scindi 
746c40d7343Scindi 	print_pgroup(thp, node, pp->group, NULL, NULL, 0);
747825ba0f2Srobj 	print_prop_nameval(thp, node, nvl);
748c40d7343Scindi 
749*1410cb93SJoshua M. Clulow out:
750*1410cb93SJoshua M. Clulow 	nvlist_free(nvl);
751c40d7343Scindi }
752c40d7343Scindi 
753c40d7343Scindi static void
754c40d7343Scindi print_props(topo_hdl_t *thp, tnode_t *node)
755c40d7343Scindi {
756c40d7343Scindi 	int i, err;
757c40d7343Scindi 	nvlist_t *nvl;
758c40d7343Scindi 	struct prop_args *pp;
759c40d7343Scindi 
760c40d7343Scindi 	if (pcnt == 0)
761c40d7343Scindi 		return;
762c40d7343Scindi 
763c40d7343Scindi 	for (i = 0; i < pcnt; ++i) {
764c40d7343Scindi 		pp = pargs[i];
765c40d7343Scindi 
766c40d7343Scindi 		if (pp->group == NULL)
767c40d7343Scindi 			continue;
768c40d7343Scindi 
769c40d7343Scindi 		/*
770c40d7343Scindi 		 * If we have a valid value, this is a request to
771c40d7343Scindi 		 * set a property.  Otherwise, just print the property
772c40d7343Scindi 		 * group and any specified properties.
773c40d7343Scindi 		 */
774c40d7343Scindi 		if (pp->value == NULL) {
775c40d7343Scindi 			if (pp->prop == NULL) {
776c40d7343Scindi 
777c40d7343Scindi 				/*
778c40d7343Scindi 				 * Print all properties in this group
779c40d7343Scindi 				 */
780c40d7343Scindi 				if ((nvl = topo_prop_getprops(node, &err))
781c40d7343Scindi 				    == NULL) {
782c40d7343Scindi 					(void) fprintf(stderr, "%s: failed to "
783c40d7343Scindi 					    "get %s: %s\n", g_pname,
784c40d7343Scindi 					    pp->group,
785c40d7343Scindi 					    topo_strerror(err));
786c40d7343Scindi 					continue;
787c40d7343Scindi 				} else {
788c40d7343Scindi 					print_all_props(thp, node, nvl,
789c40d7343Scindi 					    pp->group);
790c40d7343Scindi 					nvlist_free(nvl);
791c40d7343Scindi 					continue;
792c40d7343Scindi 				}
793c40d7343Scindi 			}
794c40d7343Scindi 			if (topo_prop_getprop(node, pp->group, pp->prop,
795c40d7343Scindi 			    NULL, &nvl, &err) < 0) {
796c40d7343Scindi 				(void) fprintf(stderr, "%s: failed to get "
797c40d7343Scindi 				    "%s.%s: %s\n", g_pname,
798c40d7343Scindi 				    pp->group, pp->prop,
799c40d7343Scindi 				    topo_strerror(err));
800c40d7343Scindi 				continue;
801c40d7343Scindi 			} else {
802c40d7343Scindi 				print_pgroup(thp, node, pp->group, NULL,
803c40d7343Scindi 				    NULL, 0);
804825ba0f2Srobj 				print_prop_nameval(thp, node, nvl);
805c40d7343Scindi 				nvlist_free(nvl);
806c40d7343Scindi 			}
807c40d7343Scindi 		} else {
808c40d7343Scindi 			set_prop(thp, node, NULL, pp);
809c40d7343Scindi 		}
8100eb822a1Scindi 	}
8110eb822a1Scindi }
8120eb822a1Scindi 
8137aec1d6eScindi /*ARGSUSED*/
8147aec1d6eScindi static int
815c40d7343Scindi walk_node(topo_hdl_t *thp, tnode_t *node, void *arg)
8167aec1d6eScindi {
8170eb822a1Scindi 	int err;
8180eb822a1Scindi 	nvlist_t *nvl;
819b6955755SRobert Johnston 	nvlist_t *rsrc, *out;
820c40d7343Scindi 	char *s;
8210eb822a1Scindi 
8220eb822a1Scindi 	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
8237aec1d6eScindi 		print_everstyle(node);
8240eb822a1Scindi 		return (TOPO_WALK_NEXT);
8250eb822a1Scindi 	}
8260eb822a1Scindi 
827c40d7343Scindi 	if (topo_node_resource(node, &rsrc, &err) < 0) {
828c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to get resource: "
829c40d7343Scindi 		    "%s", g_pname, topo_strerror(err));
830c40d7343Scindi 		return (TOPO_WALK_NEXT);
831c40d7343Scindi 	}
832c40d7343Scindi 	if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) {
833c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to convert "
834c40d7343Scindi 		    "resource to FMRI string: %s", g_pname,
835c40d7343Scindi 		    topo_strerror(err));
836c40d7343Scindi 		nvlist_free(rsrc);
837c40d7343Scindi 		return (TOPO_WALK_NEXT);
838c40d7343Scindi 	}
8397aec1d6eScindi 
840c40d7343Scindi 	if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) {
841c40d7343Scindi 		nvlist_free(rsrc);
842c40d7343Scindi 		topo_hdl_strfree(thp, s);
843c40d7343Scindi 		return (TOPO_WALK_NEXT);
844c40d7343Scindi 	}
845c40d7343Scindi 
846c40d7343Scindi 	print_node(thp, node, rsrc, s);
847c40d7343Scindi 	topo_hdl_strfree(thp, s);
848c40d7343Scindi 	nvlist_free(rsrc);
849c40d7343Scindi 
850b6955755SRobert Johnston 	if (opt_m != NULL) {
851b6955755SRobert Johnston 		if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) {
852b6955755SRobert Johnston 			nvlist_print(stdout, out);
853b6955755SRobert Johnston 			nvlist_free(out);
854b6955755SRobert Johnston 		} else if (err != ETOPO_METHOD_NOTSUP)
855b6955755SRobert Johnston 			(void) fprintf(stderr, "%s: method failed unexpectedly "
856b6955755SRobert Johnston 			    "on %s=%d (%s)\n", g_pname, topo_node_name(node),
857b6955755SRobert Johnston 			    topo_node_instance(node), topo_strerror(err));
858b6955755SRobert Johnston 	}
859b6955755SRobert Johnston 
860c40d7343Scindi 	if (opt_V || opt_all) {
8610eb822a1Scindi 		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
8620eb822a1Scindi 			(void) fprintf(stderr, "%s: failed to get "
8630eb822a1Scindi 			    "properties for %s=%d: %s\n", g_pname,
8640eb822a1Scindi 			    topo_node_name(node), topo_node_instance(node),
8650eb822a1Scindi 			    topo_strerror(err));
8667aec1d6eScindi 		} else {
867c40d7343Scindi 			print_all_props(thp, node, nvl, ALL);
8687aec1d6eScindi 			nvlist_free(nvl);
8697aec1d6eScindi 		}
870825ba0f2Srobj 	} else if (pcnt > 0)
871c40d7343Scindi 		print_props(thp, node);
8727aec1d6eScindi 
873888e0559SRobert Johnston 	(void) printf("\n");
8740eb822a1Scindi 
8757aec1d6eScindi 	return (TOPO_WALK_NEXT);
8767aec1d6eScindi }
8777aec1d6eScindi 
878c40d7343Scindi static void
879c40d7343Scindi get_pargs(int argc, char *argv[])
8807aec1d6eScindi {
881c40d7343Scindi 	struct prop_args *pp;
882c40d7343Scindi 	char c, *s, *p;
883c40d7343Scindi 	int i = 0;
884c40d7343Scindi 
885c40d7343Scindi 	if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) {
886c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to allocate property "
887c40d7343Scindi 		    "arguments\n", g_pname);
888c40d7343Scindi 		return;
889c40d7343Scindi 	}
890c40d7343Scindi 
891c40d7343Scindi 	for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) {
892c40d7343Scindi 		if (c == 'P') {
893c40d7343Scindi 
894c40d7343Scindi 			if (strcmp(optarg, ALL) == 0) {
895c40d7343Scindi 				opt_all++;
896c40d7343Scindi 				break;
897c40d7343Scindi 			}
898c40d7343Scindi 
899c40d7343Scindi 			if ((pp = pargs[i] = malloc(sizeof (struct prop_args)))
900c40d7343Scindi 			    == NULL) {
901c40d7343Scindi 				(void) fprintf(stderr, "%s: failed to "
902c40d7343Scindi 				    "allocate propertyarguments\n", g_pname);
903c40d7343Scindi 				return;
904c40d7343Scindi 			}
905c40d7343Scindi 			++i;
906c40d7343Scindi 			pp->group = NULL;
907c40d7343Scindi 			pp->prop = NULL;
908c40d7343Scindi 			pp->type = NULL;
909c40d7343Scindi 			pp->value = NULL;
910c40d7343Scindi 
911c40d7343Scindi 			p = optarg;
912c40d7343Scindi 			if ((s = strchr(p, '.')) != NULL) {
913c40d7343Scindi 				*s++ = '\0'; /* strike out delimiter */
914c40d7343Scindi 				pp->group = p;
915c40d7343Scindi 				p = s;
916c40d7343Scindi 				if ((s = strchr(p, '=')) != NULL) {
917c40d7343Scindi 					*s++ = '\0'; /* strike out delimiter */
918c40d7343Scindi 					pp->prop = p;
919c40d7343Scindi 					p = s;
920c40d7343Scindi 					if ((s = strchr(p, ':')) != NULL) {
921c40d7343Scindi 						*s++ = '\0';
922c40d7343Scindi 						pp->type = p;
923c40d7343Scindi 						pp->value = s;
924c40d7343Scindi 					} else {
925c40d7343Scindi 						(void) fprintf(stderr, "%s: "
926c40d7343Scindi 						    "property type not "
927c40d7343Scindi 						    "specified for assignment "
928c40d7343Scindi 						    " of %s.%s\n", g_pname,
929c40d7343Scindi 						    pp->group, pp->prop);
930c40d7343Scindi 						break;
931c40d7343Scindi 					}
932c40d7343Scindi 				} else {
933c40d7343Scindi 					pp->prop = p;
934c40d7343Scindi 				}
935c40d7343Scindi 			} else {
936c40d7343Scindi 				pp->group = p;
937c40d7343Scindi 			}
938c40d7343Scindi 			if (i >= pcnt)
939c40d7343Scindi 				break;
940c40d7343Scindi 		}
941c40d7343Scindi 	}
942c40d7343Scindi 
943c40d7343Scindi 	if (opt_all > 0) {
944c40d7343Scindi 		int j;
945c40d7343Scindi 
946c40d7343Scindi 		for (j = 0; j < i; ++j)
947c40d7343Scindi 			free(pargs[i]);
948c40d7343Scindi 		free(pargs);
949c40d7343Scindi 		pargs = NULL;
950c40d7343Scindi 	}
951c40d7343Scindi }
952c40d7343Scindi 
953c40d7343Scindi static int
954c40d7343Scindi walk_topo(topo_hdl_t *thp, char *uuid)
955c40d7343Scindi {
956c40d7343Scindi 	int err;
9577aec1d6eScindi 	topo_walk_t *twp;
95878432d5eScy152378 	int flag;
9597aec1d6eScindi 
960f6e214c7SGavin Maltby 	if (getzoneid() != GLOBAL_ZONEID &&
961f6e214c7SGavin Maltby 	    strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
962f6e214c7SGavin Maltby 		return (0);
963f6e214c7SGavin Maltby 	}
964f6e214c7SGavin Maltby 
965c40d7343Scindi 	if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err))
9667aec1d6eScindi 	    == NULL) {
9677aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to walk %s topology:"
9687aec1d6eScindi 		    " %s\n", g_pname, opt_s, topo_strerror(err));
9697aec1d6eScindi 
970c40d7343Scindi 		return (-1);
9717aec1d6eScindi 	}
9727aec1d6eScindi 
9730eb822a1Scindi 	/*
9740eb822a1Scindi 	 * Print standard header
9750eb822a1Scindi 	 */
9760eb822a1Scindi 	if (!opt_e) {
9770eb822a1Scindi 		char buf[32];
9780eb822a1Scindi 		time_t tod = time(NULL);
9790eb822a1Scindi 
980888e0559SRobert Johnston 		(void) printf("TIME                 UUID\n");
9810eb822a1Scindi 		(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
9820eb822a1Scindi 		(void) printf("%-15s %-32s\n", buf, uuid);
9830eb822a1Scindi 		(void) printf("\n");
9840eb822a1Scindi 	}
9857aec1d6eScindi 
98678432d5eScy152378 	flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD;
98778432d5eScy152378 
98878432d5eScy152378 	if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) {
9897aec1d6eScindi 		(void) fprintf(stderr, "%s: failed to walk topology\n",
9907aec1d6eScindi 		    g_pname);
991724365f7Ssethg 		topo_walk_fini(twp);
992c40d7343Scindi 		return (-1);
9937aec1d6eScindi 	}
9947aec1d6eScindi 
9957aec1d6eScindi 	topo_walk_fini(twp);
996c40d7343Scindi 
997c40d7343Scindi 	return (0);
998c40d7343Scindi }
999c40d7343Scindi 
1000c40d7343Scindi static void
1001c40d7343Scindi print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl)
1002c40d7343Scindi {
1003c40d7343Scindi 	char *dstab = NULL, *nstab = NULL;
1004c40d7343Scindi 	int32_t version = -1;
1005c40d7343Scindi 	nvlist_t *pnvl;
1006c40d7343Scindi 	nvpair_t *pnvp;
1007c40d7343Scindi 
1008c40d7343Scindi 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab);
1009c40d7343Scindi 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab);
1010c40d7343Scindi 	(void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version);
1011c40d7343Scindi 
1012c40d7343Scindi 	print_pgroup(thp, NULL, pgn, dstab, nstab, version);
1013c40d7343Scindi 
1014c40d7343Scindi 	for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL;
1015c40d7343Scindi 	    pnvp = nvlist_next_nvpair(nvl, pnvp)) {
1016c40d7343Scindi 
1017c40d7343Scindi 		/*
1018c40d7343Scindi 		 * Print property group and property name-value pair
1019c40d7343Scindi 		 */
1020c40d7343Scindi 		if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
1021c40d7343Scindi 		    == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
1022c40d7343Scindi 			(void) nvpair_value_nvlist(pnvp, &pnvl);
1023825ba0f2Srobj 				print_prop_nameval(thp, NULL, pnvl);
1024c40d7343Scindi 
1025c40d7343Scindi 		}
1026c40d7343Scindi 
1027c40d7343Scindi 	}
1028c40d7343Scindi }
1029c40d7343Scindi 
1030c40d7343Scindi static void
1031c40d7343Scindi print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl)
1032c40d7343Scindi {
1033c40d7343Scindi 	int i, err;
1034c40d7343Scindi 	struct prop_args *pp;
1035c40d7343Scindi 	nvlist_t *pnvl;
1036c40d7343Scindi 
1037c40d7343Scindi 	for (i = 0; i < pcnt; ++i) {
1038c40d7343Scindi 		pp = pargs[i];
1039c40d7343Scindi 
1040c40d7343Scindi 		if (pp->group == NULL)
1041c40d7343Scindi 			continue;
1042c40d7343Scindi 
1043c40d7343Scindi 		pnvl = NULL;
1044c40d7343Scindi 
1045c40d7343Scindi 		/*
1046c40d7343Scindi 		 * If we have a valid value, this is a request to
1047c40d7343Scindi 		 * set a property.  Otherwise, just print the property
1048c40d7343Scindi 		 * group and any specified properties.
1049c40d7343Scindi 		 */
1050c40d7343Scindi 		if (pp->value == NULL) {
1051c40d7343Scindi 			if (pp->prop == NULL) {
1052c40d7343Scindi 
1053c40d7343Scindi 				/*
1054c40d7343Scindi 				 * Print all properties in this group
1055c40d7343Scindi 				 */
1056c40d7343Scindi 				if (topo_fmri_getpgrp(thp, nvl, pp->group,
1057c40d7343Scindi 				    &pnvl, &err) < 0) {
1058c40d7343Scindi 					(void) fprintf(stderr, "%s: failed to "
1059c40d7343Scindi 					    "get group %s: %s\n", g_pname,
1060c40d7343Scindi 					    pp->group, topo_strerror(err));
1061c40d7343Scindi 					continue;
1062c40d7343Scindi 				} else {
1063825ba0f2Srobj 					print_fmri_pgroup(thp, pp->group,
1064825ba0f2Srobj 					    pnvl);
1065c40d7343Scindi 					nvlist_free(pnvl);
1066c40d7343Scindi 					continue;
1067c40d7343Scindi 				}
1068c40d7343Scindi 			}
1069c40d7343Scindi 			if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop,
1070c40d7343Scindi 			    NULL, &pnvl, &err) < 0) {
1071c40d7343Scindi 				(void) fprintf(stderr, "%s: failed to get "
1072c40d7343Scindi 				    "%s.%s: %s\n", g_pname,
1073c40d7343Scindi 				    pp->group, pp->prop,
1074c40d7343Scindi 				    topo_strerror(err));
1075c40d7343Scindi 				continue;
1076c40d7343Scindi 			} else {
1077c40d7343Scindi 				print_fmri_pgroup(thp, pp->group, pnvl);
1078825ba0f2Srobj 				print_prop_nameval(thp, NULL, pnvl);
1079c40d7343Scindi 				nvlist_free(nvl);
1080c40d7343Scindi 			}
1081c40d7343Scindi 		} else {
1082c40d7343Scindi 			set_prop(thp, NULL, nvl, pp);
1083c40d7343Scindi 		}
1084c40d7343Scindi 	}
1085c40d7343Scindi }
1086c40d7343Scindi 
1087c40d7343Scindi void
1088c40d7343Scindi print_fmri(topo_hdl_t *thp, char *uuid)
1089c40d7343Scindi {
1090c40d7343Scindi 	int ret, err;
1091c40d7343Scindi 	nvlist_t *nvl;
1092c40d7343Scindi 	char buf[32];
1093c40d7343Scindi 	time_t tod = time(NULL);
1094c40d7343Scindi 
1095c40d7343Scindi 	if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
1096c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to convert %s to nvlist: "
1097c40d7343Scindi 		    "%s\n", g_pname, g_fmri, topo_strerror(err));
1098c40d7343Scindi 		return;
1099c40d7343Scindi 	}
1100c40d7343Scindi 
1101888e0559SRobert Johnston 	(void) printf("TIME                 UUID\n");
1102c40d7343Scindi 	(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
1103c40d7343Scindi 	(void) printf("%-15s %-32s\n", buf, uuid);
1104c40d7343Scindi 	(void) printf("\n");
1105c40d7343Scindi 
1106c40d7343Scindi 	(void) printf("%s\n", (char *)g_fmri);
1107c40d7343Scindi 
1108c40d7343Scindi 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
1109c40d7343Scindi 		char *aname = NULL, *fname = NULL, *lname = NULL;
1110c40d7343Scindi 		nvlist_t *asru = NULL;
1111c40d7343Scindi 		nvlist_t *fru = NULL;
1112c40d7343Scindi 
1113c40d7343Scindi 		if (topo_fmri_asru(thp, nvl, &asru, &err) == 0)
1114c40d7343Scindi 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
1115c40d7343Scindi 		if (topo_fmri_fru(thp, nvl, &fru, &err) == 0)
1116c40d7343Scindi 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
1117c40d7343Scindi 		(void) topo_fmri_label(thp, nvl, &lname, &err);
1118c40d7343Scindi 
1119c40d7343Scindi 		nvlist_free(fru);
1120c40d7343Scindi 		nvlist_free(asru);
1121c40d7343Scindi 
1122c40d7343Scindi 		if (aname != NULL) {
1123c40d7343Scindi 			(void) printf("\tASRU: %s\n", aname);
1124c40d7343Scindi 			topo_hdl_strfree(thp, aname);
1125c40d7343Scindi 		} else {
1126c40d7343Scindi 			(void) printf("\tASRU: -\n");
1127c40d7343Scindi 		}
1128c40d7343Scindi 		if (fname != NULL) {
1129c40d7343Scindi 			(void) printf("\tFRU: %s\n", fname);
1130c40d7343Scindi 			topo_hdl_strfree(thp, fname);
1131c40d7343Scindi 		} else {
1132c40d7343Scindi 			(void) printf("\tFRU: -\n");
1133c40d7343Scindi 		}
1134c40d7343Scindi 		if (lname != NULL) {
1135c40d7343Scindi 			(void) printf("\tLabel: %s\n", lname);
1136c40d7343Scindi 			topo_hdl_strfree(thp, lname);
1137c40d7343Scindi 		} else {
1138c40d7343Scindi 			(void) printf("\tLabel: -\n");
1139c40d7343Scindi 		}
1140c40d7343Scindi 	}
1141c40d7343Scindi 
1142c40d7343Scindi 	if (opt_S) {
1143c40d7343Scindi 		if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
1144c40d7343Scindi 			(void) printf("\tPresent: -\n");
1145c40d7343Scindi 			(void) printf("\tUnusable: -\n");
1146c40d7343Scindi 			return;
1147c40d7343Scindi 		}
1148c40d7343Scindi 
1149c40d7343Scindi 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
1150c40d7343Scindi 			(void) printf("\tPresent: -\n");
1151c40d7343Scindi 		else
1152c40d7343Scindi 			(void) printf("\tPresent: %s\n",
1153c40d7343Scindi 			    ret ? "true" : "false");
1154c40d7343Scindi 
1155c40d7343Scindi 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
1156c40d7343Scindi 			(void) printf("\tUnusable: -\n");
1157c40d7343Scindi 		else
1158c40d7343Scindi 			(void) printf("\tUnusable: %s\n",
1159c40d7343Scindi 			    ret ? "true" : "false");
1160c40d7343Scindi 
1161c40d7343Scindi 		nvlist_free(nvl);
1162c40d7343Scindi 	}
1163c40d7343Scindi 
11644557a2a1Srobj 	if (pargs && pcnt > 0)
1165c40d7343Scindi 		print_fmri_props(thp, nvl);
1166c40d7343Scindi }
1167c40d7343Scindi 
1168c40d7343Scindi int
1169c40d7343Scindi fmtopo_exit(topo_hdl_t *thp, char *uuid, int err)
1170c40d7343Scindi {
1171c40d7343Scindi 	if (uuid != NULL)
1172c40d7343Scindi 		topo_hdl_strfree(thp, uuid);
1173c40d7343Scindi 
1174c40d7343Scindi 	if (thp != NULL) {
11757aec1d6eScindi 		topo_snap_release(thp);
11767aec1d6eScindi 		topo_close(thp);
1177c40d7343Scindi 	}
1178c40d7343Scindi 
1179c40d7343Scindi 	if (pargs) {
1180c40d7343Scindi 		int i;
1181c40d7343Scindi 		for (i = 0; i < pcnt; ++i)
1182c40d7343Scindi 			free(pargs[i]);
1183c40d7343Scindi 		free(pargs);
1184c40d7343Scindi 	}
1185c40d7343Scindi 
1186c40d7343Scindi 	return (err);
1187c40d7343Scindi }
1188c40d7343Scindi 
1189c40d7343Scindi int
1190c40d7343Scindi main(int argc, char *argv[])
1191c40d7343Scindi {
1192c40d7343Scindi 	topo_hdl_t *thp = NULL;
1193c40d7343Scindi 	char *uuid = NULL;
1194c40d7343Scindi 	int c, err = 0;
1195c40d7343Scindi 
1196c40d7343Scindi 	g_pname = argv[0];
1197c40d7343Scindi 
1198c40d7343Scindi 	while (optind < argc) {
1199c40d7343Scindi 		while ((c = getopt(argc, argv, optstr)) != -1) {
1200c40d7343Scindi 			switch (c) {
120178432d5eScy152378 			case 'b':
120278432d5eScy152378 				opt_b++;
120378432d5eScy152378 				break;
1204c40d7343Scindi 			case 'C':
1205888e0559SRobert Johnston 				(void) atexit(abort);
1206c40d7343Scindi 				break;
1207c40d7343Scindi 			case 'd':
1208c40d7343Scindi 				opt_d++;
1209c40d7343Scindi 				break;
1210c40d7343Scindi 			case 'e':
1211c40d7343Scindi 				opt_e++;
1212c40d7343Scindi 				break;
1213b6955755SRobert Johnston 			case 'm':
1214b6955755SRobert Johnston 				opt_m = optarg;
1215b6955755SRobert Johnston 				break;
1216c40d7343Scindi 			case 'P':
1217c40d7343Scindi 				pcnt++;
1218c40d7343Scindi 				break;
1219c40d7343Scindi 			case 'p':
1220c40d7343Scindi 				opt_p++;
1221c40d7343Scindi 				break;
1222c40d7343Scindi 			case 'V':
1223c40d7343Scindi 				opt_V++;
1224c40d7343Scindi 				break;
1225c40d7343Scindi 			case 'R':
1226c40d7343Scindi 				opt_R = optarg;
1227c40d7343Scindi 				break;
1228c40d7343Scindi 			case 's':
1229c40d7343Scindi 				opt_s = optarg;
1230c40d7343Scindi 				break;
1231c40d7343Scindi 			case 'S':
1232c40d7343Scindi 				opt_S++;
1233c40d7343Scindi 				break;
1234c40d7343Scindi 			case 't':
1235c40d7343Scindi 				opt_t++;
1236c40d7343Scindi 				break;
1237c40d7343Scindi 			case 'x':
1238c40d7343Scindi 				opt_x++;
1239c40d7343Scindi 				break;
1240c40d7343Scindi 			default:
1241c40d7343Scindi 				return (usage(stderr));
1242c40d7343Scindi 			}
1243c40d7343Scindi 		}
1244c40d7343Scindi 
1245c40d7343Scindi 		if (optind < argc) {
1246c40d7343Scindi 			if (g_fmri != NULL) {
1247c40d7343Scindi 				(void) fprintf(stderr, "%s: illegal argument "
1248c40d7343Scindi 				    "-- %s\n", g_pname, argv[optind]);
1249c40d7343Scindi 				return (FMTOPO_EXIT_USAGE);
1250c40d7343Scindi 			} else {
1251c40d7343Scindi 				g_fmri = argv[optind++];
1252c40d7343Scindi 			}
1253c40d7343Scindi 		}
1254c40d7343Scindi 	}
1255c40d7343Scindi 
1256c40d7343Scindi 	if (pcnt > 0)
1257c40d7343Scindi 		get_pargs(argc, argv);
1258c40d7343Scindi 
1259c40d7343Scindi 	if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
1260c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
1261c40d7343Scindi 		    g_pname, topo_strerror(err));
1262c40d7343Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
1263c40d7343Scindi 	}
1264c40d7343Scindi 
1265c40d7343Scindi 	if (opt_d)
1266c40d7343Scindi 		topo_debug_set(thp, "module", "stderr");
1267c40d7343Scindi 
1268c40d7343Scindi 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
1269c40d7343Scindi 		(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
1270c40d7343Scindi 		    g_pname, topo_strerror(err));
1271c40d7343Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
1272c40d7343Scindi 	} else if (err != 0) {
1273f6e214c7SGavin Maltby 		(void) fprintf(stderr, "%s: topology snapshot incomplete%s\n",
1274f6e214c7SGavin Maltby 		    g_pname, getzoneid() != GLOBAL_ZONEID &&
1275f6e214c7SGavin Maltby 		    strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0 ?
1276f6e214c7SGavin Maltby 		    " (" FM_FMRI_SCHEME_HC " scheme does not enumerate "
1277f6e214c7SGavin Maltby 		    "in a non-global zone)": "");
1278c40d7343Scindi 	}
1279c40d7343Scindi 
1280c40d7343Scindi 	if (opt_x) {
128178432d5eScy152378 		if (opt_b) {
128278432d5eScy152378 			(void) fprintf(stderr,
128378432d5eScy152378 			    "%s: -b and -x cannot be specified together\n",
128478432d5eScy152378 			    g_pname);
128578432d5eScy152378 			return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE));
128678432d5eScy152378 		}
128778432d5eScy152378 
1288c40d7343Scindi 		err = 0;
1289c40d7343Scindi 		if (topo_xml_print(thp, stdout, opt_s, &err) < 0)
1290c40d7343Scindi 			(void) fprintf(stderr, "%s: failed to print xml "
1291c40d7343Scindi 			    "formatted topology:%s",  g_pname,
1292c40d7343Scindi 			    topo_strerror(err));
1293c40d7343Scindi 
1294c40d7343Scindi 		return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR :
1295c40d7343Scindi 		    FMTOPO_EXIT_SUCCESS));
1296c40d7343Scindi 	}
1297c40d7343Scindi 
1298c40d7343Scindi 	if (opt_t || walk_topo(thp, uuid) < 0) {
1299c40d7343Scindi 		if (g_fmri != NULL)
1300c40d7343Scindi 			/*
1301c40d7343Scindi 			 * Try getting some useful information
1302c40d7343Scindi 			 */
1303c40d7343Scindi 			print_fmri(thp, uuid);
1304c40d7343Scindi 
1305c40d7343Scindi 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
1306c40d7343Scindi 	}
1307c40d7343Scindi 
130812cc75c8Scindi 	return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS));
13097aec1d6eScindi }
1310