Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 
     28 #include <sys/fm/protocol.h>
     29 #include <fm/libtopo.h>
     30 #include <ctype.h>
     31 #include <fnmatch.h>
     32 #include <limits.h>
     33 #include <strings.h>
     34 #include <stdio.h>
     35 #include <errno.h>
     36 #include <umem.h>
     37 #include <sys/param.h>
     38 
     39 #define	FMTOPO_EXIT_SUCCESS	0
     40 #define	FMTOPO_EXIT_ERROR	1
     41 #define	FMTOPO_EXIT_USAGE	2
     42 
     43 #define	STDERR	"stderr"
     44 #define	DOTS	"..."
     45 #define	ALL	"all"
     46 
     47 static const char *g_pname;
     48 static const char *g_fmri = NULL;
     49 
     50 static const char *opt_R = "/";
     51 static const char *opt_s = FM_FMRI_SCHEME_HC;
     52 static const char optstr[] = "bCdem:P:pR:s:StVx";
     53 static const char *opt_m;
     54 
     55 static int opt_b = 0;
     56 static int opt_d = 0;
     57 static int opt_e = 0;
     58 static int opt_p = 0;
     59 static int opt_S = 0;
     60 static int opt_t = 0;
     61 static int opt_V = 0;
     62 static int opt_x = 0;
     63 static int opt_all = 0;
     64 
     65 struct prop_args {
     66 	const char *group;
     67 	const char *prop;
     68 	const char *type;
     69 	const char *value;
     70 };
     71 
     72 static struct prop_args **pargs = NULL;
     73 static int pcnt = 0;
     74 
     75 static int
     76 usage(FILE *fp)
     77 {
     78 	(void) fprintf(fp,
     79 	    "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] "
     80 	    "[-R root] [-m method] [-s scheme] [fmri]\n", g_pname);
     81 
     82 	(void) fprintf(fp,
     83 	    "\t-b  walk in sibling-first order (default is child-first)\n"
     84 	    "\t-C  dump core after completing execution\n"
     85 	    "\t-d  set debug mode for libtopo modules\n"
     86 	    "\t-e  display FMRIs as paths using esc/eft notation\n"
     87 	    "\t-m  execute given method\n"
     88 	    "\t-P  get/set specified properties\n"
     89 	    "\t-p  display of FMRI protocol properties\n"
     90 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
     91 	    "\t-s  display topology for the specified FMRI scheme\n"
     92 	    "\t-S  display FMRI status (present/usable)\n"
     93 	    "\t-V  set verbose mode\n"
     94 	    "\t-x  display a xml formatted topology\n");
     95 
     96 	return (FMTOPO_EXIT_USAGE);
     97 }
     98 
     99 static topo_type_t
    100 str2type(const char *tstr)
    101 {
    102 	topo_type_t type;
    103 
    104 	if (tstr == NULL)
    105 		return (TOPO_TYPE_INVALID);
    106 
    107 	if (strcmp(tstr, "int32") == 0)
    108 		type = TOPO_TYPE_INT32;
    109 	else if (strcmp(tstr, "uint32") == 0)
    110 		type = TOPO_TYPE_UINT32;
    111 	else if (strcmp(tstr, "int64") == 0)
    112 		type = TOPO_TYPE_INT64;
    113 	else if (strcmp(tstr, "uint64") == 0)
    114 		type = TOPO_TYPE_UINT64;
    115 	else if (strcmp(tstr, "string") == 0)
    116 		type = TOPO_TYPE_STRING;
    117 	else if (strcmp(tstr, "fmri") == 0)
    118 		type = TOPO_TYPE_FMRI;
    119 	else {
    120 		type = TOPO_TYPE_INVALID;
    121 	}
    122 
    123 	return (type);
    124 }
    125 
    126 static void
    127 print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri)
    128 {
    129 	int err, ret;
    130 
    131 	(void) printf("%s\n", (char *)fmri);
    132 
    133 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
    134 		char *aname = NULL, *fname = NULL, *lname = NULL;
    135 		nvlist_t *asru = NULL;
    136 		nvlist_t *fru = NULL;
    137 
    138 		if (topo_node_asru(node, &asru, NULL, &err) == 0)
    139 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
    140 		if (topo_node_fru(node, &fru, NULL, &err) == 0)
    141 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
    142 		(void) topo_node_label(node, &lname, &err);
    143 		if (aname != NULL) {
    144 			nvlist_free(asru);
    145 			(void) printf("\tASRU: %s\n", aname);
    146 			topo_hdl_strfree(thp, aname);
    147 		} else {
    148 			(void) printf("\tASRU: -\n");
    149 		}
    150 		if (fname != NULL) {
    151 			nvlist_free(fru);
    152 			(void) printf("\tFRU: %s\n", fname);
    153 			topo_hdl_strfree(thp, fname);
    154 		} else {
    155 			(void) printf("\tFRU: -\n");
    156 		}
    157 		if (lname != NULL) {
    158 			(void) printf("\tLabel: %s\n", lname);
    159 			topo_hdl_strfree(thp, lname);
    160 		} else {
    161 			(void) printf("\tLabel: -\n");
    162 		}
    163 	}
    164 
    165 	if (opt_S) {
    166 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
    167 			(void) printf("\tPresent: -\n");
    168 		else
    169 			(void) printf("\tPresent: %s\n",
    170 			    ret ? "true" : "false");
    171 
    172 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
    173 			(void) printf("\tUnusable: -\n");
    174 		else
    175 			(void) printf("\tUnusable: %s\n",
    176 			    ret ? "true" : "false");
    177 	}
    178 }
    179 
    180 static void
    181 print_everstyle(tnode_t *node)
    182 {
    183 	char buf[PATH_MAX], numbuf[64];
    184 	nvlist_t *fmri, **hcl;
    185 	int i, err;
    186 	uint_t n;
    187 
    188 	if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
    189 	    TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
    190 		(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
    191 		    g_pname, topo_node_name(node),
    192 		    topo_node_instance(node), topo_strerror(err));
    193 		return;
    194 	}
    195 
    196 	if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
    197 		(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
    198 		    g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
    199 		    topo_node_instance(node));
    200 		nvlist_free(fmri);
    201 		return;
    202 	}
    203 
    204 	buf[0] = '\0';
    205 
    206 	for (i = 0; i < n; i++) {
    207 		char *name, *inst, *estr;
    208 		ulong_t ul;
    209 
    210 		if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
    211 		    nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
    212 			(void) fprintf(stderr, "%s: failed to get "
    213 			    "name-instance for %s=%d\n", g_pname,
    214 			    topo_node_name(node), topo_node_instance(node));
    215 			nvlist_free(fmri);
    216 			return;
    217 		}
    218 
    219 		errno = 0;
    220 		ul = strtoul(inst, &estr, 10);
    221 
    222 		if (errno != 0 || estr == inst) {
    223 			(void) fprintf(stderr, "%s: instance %s does not "
    224 			    "convert to an unsigned integer\n", g_pname, inst);
    225 		}
    226 
    227 		(void) strlcat(buf, "/", sizeof (buf));
    228 		(void) strlcat(buf, name, sizeof (buf));
    229 		(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
    230 		(void) strlcat(buf, numbuf, sizeof (buf));
    231 	}
    232 	nvlist_free(fmri);
    233 
    234 	(void) printf("%s\n", buf);
    235 }
    236 
    237 static void
    238 print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl)
    239 {
    240 	int err;
    241 	topo_type_t type;
    242 	char *tstr, *propn, buf[48], *factype;
    243 	nvpair_t *pv_nvp;
    244 	int i;
    245 	uint_t nelem;
    246 
    247 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL)
    248 		return;
    249 
    250 	/* Print property name */
    251 	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL ||
    252 	    nvpair_name(pv_nvp) == NULL ||
    253 	    strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) {
    254 		(void) fprintf(stderr, "%s: malformed property name\n",
    255 		    g_pname);
    256 		return;
    257 	} else {
    258 		(void) nvpair_value_string(pv_nvp, &propn);
    259 	}
    260 
    261 	if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL ||
    262 	    nvpair_name(pv_nvp) == NULL ||
    263 	    strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 ||
    264 	    nvpair_type(pv_nvp) != DATA_TYPE_UINT32)  {
    265 		(void) fprintf(stderr, "%s: malformed property type for %s\n",
    266 		    g_pname, propn);
    267 		return;
    268 	} else {
    269 		(void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type);
    270 	}
    271 
    272 	switch (type) {
    273 		case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break;
    274 		case TOPO_TYPE_INT32: tstr = "int32"; break;
    275 		case TOPO_TYPE_UINT32: tstr = "uint32"; break;
    276 		case TOPO_TYPE_INT64: tstr = "int64"; break;
    277 		case TOPO_TYPE_UINT64: tstr = "uint64"; break;
    278 		case TOPO_TYPE_DOUBLE: tstr = "double"; break;
    279 		case TOPO_TYPE_STRING: tstr = "string"; break;
    280 		case TOPO_TYPE_FMRI: tstr = "fmri"; break;
    281 		case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
    282 		case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break;
    283 		case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break;
    284 		case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break;
    285 		case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break;
    286 		case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break;
    287 		default: tstr = "unknown type";
    288 	}
    289 
    290 	(void) printf("    %-17s %-8s ", propn, tstr);
    291 
    292 	/*
    293 	 * Get property value
    294 	 */
    295 	if (nvpair_name(pv_nvp) == NULL ||
    296 	    (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) {
    297 		(void) fprintf(stderr, "%s: malformed property value\n",
    298 		    g_pname);
    299 		return;
    300 	}
    301 
    302 	switch (nvpair_type(pv_nvp)) {
    303 		case DATA_TYPE_INT32: {
    304 			int32_t val;
    305 			(void) nvpair_value_int32(pv_nvp, &val);
    306 			(void) printf(" %d", val);
    307 			break;
    308 		}
    309 		case DATA_TYPE_UINT32: {
    310 			uint32_t val, type;
    311 			char val_str[49];
    312 			nvlist_t *fac, *rsrc = NULL;
    313 
    314 			(void) nvpair_value_uint32(pv_nvp, &val);
    315 			if (node == NULL || topo_node_flags(node) !=
    316 			    TOPO_NODE_FACILITY)
    317 				goto uint32_def;
    318 
    319 			if (topo_node_resource(node, &rsrc, &err) != 0)
    320 				goto uint32_def;
    321 
    322 			if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0)
    323 				goto uint32_def;
    324 
    325 			if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
    326 			    &factype) != 0)
    327 				goto uint32_def;
    328 
    329 			nvlist_free(rsrc);
    330 			rsrc = NULL;
    331 
    332 			/*
    333 			 * Special case code to do friendlier printing of
    334 			 * facility node properties
    335 			 */
    336 			if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
    337 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
    338 				topo_sensor_type_name(val, val_str, 48);
    339 				(void) printf(" 0x%x (%s)", val, val_str);
    340 				break;
    341 			} else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
    342 			    (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) {
    343 				topo_led_type_name(val, val_str, 48);
    344 				(void) printf(" 0x%x (%s)", val, val_str);
    345 				break;
    346 			} else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) {
    347 				topo_sensor_units_name(val, val_str, 48);
    348 				(void) printf(" 0x%x (%s)", val, val_str);
    349 				break;
    350 			} else if (strcmp(propn, TOPO_LED_MODE) == 0) {
    351 				topo_led_state_name(val, val_str, 48);
    352 				(void) printf(" 0x%x (%s)", val, val_str);
    353 				break;
    354 			} else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) &&
    355 			    (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
    356 				if (topo_prop_get_uint32(node,
    357 				    TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
    358 				    &type, &err) != 0) {
    359 					goto uint32_def;
    360 				}
    361 				topo_sensor_state_name(type, val, val_str, 48);
    362 				(void) printf(" 0x%x (%s)", val, val_str);
    363 				break;
    364 			}
    365 uint32_def:
    366 			(void) printf(" 0x%x", val);
    367 			if (rsrc != NULL)
    368 				nvlist_free(rsrc);
    369 			break;
    370 		}
    371 		case DATA_TYPE_INT64: {
    372 			int64_t val;
    373 			(void) nvpair_value_int64(pv_nvp, &val);
    374 			(void) printf(" %lld", (longlong_t)val);
    375 			break;
    376 		}
    377 		case DATA_TYPE_UINT64: {
    378 			uint64_t val;
    379 			(void) nvpair_value_uint64(pv_nvp, &val);
    380 			(void) printf(" 0x%llx", (u_longlong_t)val);
    381 			break;
    382 		}
    383 		case DATA_TYPE_DOUBLE: {
    384 			double val;
    385 			(void) nvpair_value_double(pv_nvp, &val);
    386 			(void) printf(" %lf", (double)val);
    387 			break;
    388 		}
    389 		case DATA_TYPE_STRING: {
    390 			char *val;
    391 			(void) nvpair_value_string(pv_nvp, &val);
    392 			if (!opt_V && strlen(val) > 48) {
    393 				(void) snprintf(buf, 48, "%s...", val);
    394 				(void) printf(" %s", buf);
    395 			} else {
    396 				(void) printf(" %s", val);
    397 			}
    398 			break;
    399 		}
    400 		case DATA_TYPE_NVLIST: {
    401 			nvlist_t *val;
    402 			char *fmri;
    403 			(void) nvpair_value_nvlist(pv_nvp, &val);
    404 			if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) {
    405 				if (opt_V)
    406 					nvlist_print(stdout, nvl);
    407 				break;
    408 			}
    409 
    410 			if (!opt_V && strlen(fmri) > 48) {
    411 				(void) snprintf(buf, 48, "%s", fmri);
    412 				(void) snprintf(&buf[45], 4, "%s", DOTS);
    413 				(void) printf(" %s", buf);
    414 			} else {
    415 				(void) printf(" %s", fmri);
    416 			}
    417 
    418 			topo_hdl_strfree(thp, fmri);
    419 			break;
    420 		}
    421 		case DATA_TYPE_INT32_ARRAY: {
    422 			int32_t *val;
    423 
    424 			(void) nvpair_value_int32_array(pv_nvp, &val, &nelem);
    425 			(void) printf(" [ ");
    426 			for (i = 0; i < nelem; i++)
    427 				(void) printf("%d ", val[i]);
    428 			(void) printf("]");
    429 			break;
    430 		}
    431 		case DATA_TYPE_UINT32_ARRAY: {
    432 			uint32_t *val;
    433 
    434 			(void) nvpair_value_uint32_array(pv_nvp, &val, &nelem);
    435 			(void) printf(" [ ");
    436 			for (i = 0; i < nelem; i++)
    437 				(void) printf("%u ", val[i]);
    438 			(void) printf("]");
    439 			break;
    440 		}
    441 		case DATA_TYPE_INT64_ARRAY: {
    442 			int64_t *val;
    443 
    444 			(void) nvpair_value_int64_array(pv_nvp, &val, &nelem);
    445 			(void) printf(" [ ");
    446 			for (i = 0; i < nelem; i++)
    447 				(void) printf("%lld ", val[i]);
    448 			(void) printf("]");
    449 			break;
    450 		}
    451 		case DATA_TYPE_UINT64_ARRAY: {
    452 			uint64_t *val;
    453 
    454 			(void) nvpair_value_uint64_array(pv_nvp, &val, &nelem);
    455 			(void) printf(" [ ");
    456 			for (i = 0; i < nelem; i++)
    457 				(void) printf("%llu ", val[i]);
    458 			(void) printf("]");
    459 			break;
    460 		}
    461 		case DATA_TYPE_STRING_ARRAY: {
    462 			char **val;
    463 
    464 			(void) nvpair_value_string_array(pv_nvp, &val, &nelem);
    465 			(void) printf(" [ ");
    466 			for (i = 0; i < nelem; i++)
    467 				(void) printf("\"%s\" ", val[i]);
    468 			(void) printf("]");
    469 			break;
    470 		}
    471 		default:
    472 			(void) fprintf(stderr, " unknown data type (%d)",
    473 			    nvpair_type(pv_nvp));
    474 			break;
    475 		}
    476 		(void) printf("\n");
    477 }
    478 
    479 static void
    480 print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab,
    481     char *nstab, int32_t version)
    482 {
    483 	int err;
    484 	char buf[30];
    485 	topo_pgroup_info_t *pgi = NULL;
    486 
    487 	if (pgn == NULL)
    488 		return;
    489 
    490 	if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) {
    491 		if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) {
    492 			dstab = (char *)topo_stability2name(pgi->tpi_datastab);
    493 			nstab = (char *)topo_stability2name(pgi->tpi_namestab);
    494 			version = pgi->tpi_version;
    495 		}
    496 	}
    497 
    498 	if (dstab == NULL || nstab == NULL || version == -1) {
    499 		(void) printf("  group: %-30s version: - stability: -/-\n",
    500 		    pgn);
    501 	} else if (!opt_V && strlen(pgn) > 30) {
    502 		(void) snprintf(buf, 26, "%s", pgn);
    503 		(void) snprintf(&buf[27], 4, "%s", DOTS);
    504 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
    505 		    buf, version, nstab, dstab);
    506 	} else {
    507 		(void) printf("  group: %-30s version: %-3d stability: %s/%s\n",
    508 		    pgn, version, nstab, dstab);
    509 	}
    510 
    511 	if (pgi != NULL) {
    512 		topo_hdl_strfree(thp, (char *)pgi->tpi_name);
    513 		topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t));
    514 	}
    515 }
    516 
    517 static void
    518 print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv,
    519     const char *group)
    520 {
    521 	char *pgn = NULL, *dstab = NULL, *nstab = NULL;
    522 	int32_t version;
    523 	nvlist_t *pg_nv, *pv_nv;
    524 	nvpair_t *nvp, *pg_nvp;
    525 	int pg_done, match, all = strcmp(group, ALL) == 0;
    526 
    527 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
    528 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
    529 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
    530 		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
    531 			continue;
    532 
    533 		nstab = NULL;
    534 		dstab = NULL;
    535 		version = -1;
    536 		pg_done = match = 0;
    537 		(void) nvpair_value_nvlist(nvp, &pg_nv);
    538 		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
    539 		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
    540 			/*
    541 			 * Print property group name and stability levels
    542 			 */
    543 			if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp))
    544 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
    545 				(void) nvpair_value_string(pg_nvp, &pgn);
    546 				match = strcmp(group, pgn) == 0;
    547 				continue;
    548 			}
    549 
    550 			if (strcmp(TOPO_PROP_GROUP_NSTAB,
    551 			    nvpair_name(pg_nvp)) == 0 &&
    552 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
    553 				(void) nvpair_value_string(pg_nvp, &nstab);
    554 				continue;
    555 			}
    556 
    557 			if (strcmp(TOPO_PROP_GROUP_DSTAB,
    558 			    nvpair_name(pg_nvp)) == 0 &&
    559 			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
    560 				(void) nvpair_value_string(pg_nvp, &dstab);
    561 				continue;
    562 			}
    563 
    564 			if (strcmp(TOPO_PROP_GROUP_VERSION,
    565 			    nvpair_name(pg_nvp)) == 0 &&
    566 			    nvpair_type(pg_nvp) == DATA_TYPE_INT32) {
    567 				(void) nvpair_value_int32(pg_nvp, &version);
    568 				continue;
    569 			}
    570 
    571 			if ((match || all) && !pg_done) {
    572 				print_pgroup(thp, node, pgn, dstab, nstab,
    573 				    version);
    574 				pg_done++;
    575 			}
    576 
    577 			/*
    578 			 * Print property group and property name-value pair
    579 			 */
    580 			if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp))
    581 			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
    582 				(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
    583 				if ((match || all) && pg_done) {
    584 					print_prop_nameval(thp, node, pv_nv);
    585 				}
    586 
    587 			}
    588 
    589 		}
    590 		if (match && !all)
    591 			return;
    592 	}
    593 }
    594 
    595 static void
    596 set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp)
    597 {
    598 	int ret, err = 0;
    599 	topo_type_t type;
    600 	nvlist_t *nvl, *f = NULL;
    601 	char *end;
    602 
    603 	if (pp->prop == NULL || pp->type == NULL || pp->value == NULL)
    604 		return;
    605 
    606 	if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) {
    607 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
    608 		    g_pname, pp->type, pp->prop);
    609 		return;
    610 	}
    611 
    612 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
    613 		(void) fprintf(stderr, "%s: nvlist allocation failed for "
    614 		    "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value);
    615 		return;
    616 	}
    617 	ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop);
    618 	ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
    619 	if (ret != 0) {
    620 		(void) fprintf(stderr, "%s: invalid property type %s for %s\n",
    621 		    g_pname, pp->type, pp->prop);
    622 		nvlist_free(nvl);
    623 		return;
    624 	}
    625 
    626 	errno = 0;
    627 	switch (type) {
    628 		case TOPO_TYPE_INT32:
    629 		{
    630 			int32_t val;
    631 
    632 			val = strtol(pp->value, &end, 0);
    633 			if (errno == ERANGE) {
    634 				ret = -1;
    635 				break;
    636 			}
    637 			ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
    638 			break;
    639 		}
    640 		case TOPO_TYPE_UINT32:
    641 		{
    642 			uint32_t val;
    643 
    644 			val = strtoul(pp->value, &end, 0);
    645 			if (errno == ERANGE) {
    646 				ret = -1;
    647 				break;
    648 			}
    649 			ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
    650 			break;
    651 		}
    652 		case TOPO_TYPE_INT64:
    653 		{
    654 			int64_t val;
    655 
    656 			val = strtoll(pp->value, &end, 0);
    657 			if (errno == ERANGE) {
    658 				ret = -1;
    659 				break;
    660 			}
    661 			ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
    662 			break;
    663 		}
    664 		case TOPO_TYPE_UINT64:
    665 		{
    666 			uint64_t val;
    667 
    668 			val = strtoull(pp->value, &end, 0);
    669 			if (errno == ERANGE) {
    670 				ret = -1;
    671 				break;
    672 			}
    673 			ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
    674 			break;
    675 		}
    676 		case TOPO_TYPE_STRING:
    677 		{
    678 			ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
    679 			    pp->value);
    680 			break;
    681 		}
    682 		case TOPO_TYPE_FMRI:
    683 		{
    684 			if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err))
    685 			    < 0)
    686 				break;
    687 
    688 			if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
    689 			    f)) != 0)
    690 				err = ETOPO_PROP_NVL;
    691 			break;
    692 		}
    693 		default:
    694 			ret = -1;
    695 	}
    696 
    697 	if (ret != 0) {
    698 		(void) fprintf(stderr, "%s: unable to set property value for "
    699 		    "%s: %s\n", g_pname, pp->prop,  topo_strerror(err));
    700 		nvlist_free(nvl);
    701 		return;
    702 	}
    703 
    704 	if (node != NULL) {
    705 		if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE,
    706 		    f, &ret) < 0) {
    707 			(void) fprintf(stderr, "%s: unable to set property "
    708 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
    709 			    pp->type, pp->value, topo_strerror(ret));
    710 			nvlist_free(nvl);
    711 			nvlist_free(f);
    712 			return;
    713 		}
    714 	} else {
    715 		if (topo_fmri_setprop(thp, fmri,  pp->group, nvl,
    716 		    TOPO_PROP_MUTABLE, f, &ret) < 0) {
    717 			(void) fprintf(stderr, "%s: unable to set property "
    718 			    "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
    719 			    pp->type, pp->value, topo_strerror(ret));
    720 			nvlist_free(nvl);
    721 			nvlist_free(f);
    722 			return;
    723 		}
    724 	}
    725 
    726 	nvlist_free(nvl);
    727 
    728 	/*
    729 	 * Now, get the property back for printing
    730 	 */
    731 	if (node != NULL) {
    732 		if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl,
    733 		    &err) < 0) {
    734 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
    735 			    g_pname, pp->group, pp->prop, topo_strerror(err));
    736 			nvlist_free(f);
    737 			return;
    738 		}
    739 	} else {
    740 		if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop,
    741 		    f, &nvl, &err) < 0) {
    742 			(void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
    743 			    g_pname, pp->group, pp->prop, topo_strerror(err));
    744 			nvlist_free(f);
    745 			return;
    746 		}
    747 	}
    748 
    749 	print_pgroup(thp, node, pp->group, NULL, NULL, 0);
    750 	print_prop_nameval(thp, node, nvl);
    751 	nvlist_free(nvl);
    752 
    753 	nvlist_free(f);
    754 }
    755 
    756 static void
    757 print_props(topo_hdl_t *thp, tnode_t *node)
    758 {
    759 	int i, err;
    760 	nvlist_t *nvl;
    761 	struct prop_args *pp;
    762 
    763 	if (pcnt == 0)
    764 		return;
    765 
    766 	for (i = 0; i < pcnt; ++i) {
    767 		pp = pargs[i];
    768 
    769 		if (pp->group == NULL)
    770 			continue;
    771 
    772 		/*
    773 		 * If we have a valid value, this is a request to
    774 		 * set a property.  Otherwise, just print the property
    775 		 * group and any specified properties.
    776 		 */
    777 		if (pp->value == NULL) {
    778 			if (pp->prop == NULL) {
    779 
    780 				/*
    781 				 * Print all properties in this group
    782 				 */
    783 				if ((nvl = topo_prop_getprops(node, &err))
    784 				    == NULL) {
    785 					(void) fprintf(stderr, "%s: failed to "
    786 					    "get %s: %s\n", g_pname,
    787 					    pp->group,
    788 					    topo_strerror(err));
    789 					continue;
    790 				} else {
    791 					print_all_props(thp, node, nvl,
    792 					    pp->group);
    793 					nvlist_free(nvl);
    794 					continue;
    795 				}
    796 			}
    797 			if (topo_prop_getprop(node, pp->group, pp->prop,
    798 			    NULL, &nvl, &err) < 0) {
    799 				(void) fprintf(stderr, "%s: failed to get "
    800 				    "%s.%s: %s\n", g_pname,
    801 				    pp->group, pp->prop,
    802 				    topo_strerror(err));
    803 				continue;
    804 			} else {
    805 				print_pgroup(thp, node, pp->group, NULL,
    806 				    NULL, 0);
    807 				print_prop_nameval(thp, node, nvl);
    808 				nvlist_free(nvl);
    809 			}
    810 		} else {
    811 			set_prop(thp, node, NULL, pp);
    812 		}
    813 	}
    814 }
    815 
    816 /*ARGSUSED*/
    817 static int
    818 walk_node(topo_hdl_t *thp, tnode_t *node, void *arg)
    819 {
    820 	int err;
    821 	nvlist_t *nvl;
    822 	nvlist_t *rsrc, *out;
    823 	char *s;
    824 
    825 	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
    826 		print_everstyle(node);
    827 		return (TOPO_WALK_NEXT);
    828 	}
    829 
    830 	if (topo_node_resource(node, &rsrc, &err) < 0) {
    831 		(void) fprintf(stderr, "%s: failed to get resource: "
    832 		    "%s", g_pname, topo_strerror(err));
    833 		return (TOPO_WALK_NEXT);
    834 	}
    835 	if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) {
    836 		(void) fprintf(stderr, "%s: failed to convert "
    837 		    "resource to FMRI string: %s", g_pname,
    838 		    topo_strerror(err));
    839 		nvlist_free(rsrc);
    840 		return (TOPO_WALK_NEXT);
    841 	}
    842 
    843 	if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) {
    844 		nvlist_free(rsrc);
    845 		topo_hdl_strfree(thp, s);
    846 		return (TOPO_WALK_NEXT);
    847 	}
    848 
    849 	print_node(thp, node, rsrc, s);
    850 	topo_hdl_strfree(thp, s);
    851 	nvlist_free(rsrc);
    852 
    853 	if (opt_m != NULL) {
    854 		if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) {
    855 			nvlist_print(stdout, out);
    856 			nvlist_free(out);
    857 		} else if (err != ETOPO_METHOD_NOTSUP)
    858 			(void) fprintf(stderr, "%s: method failed unexpectedly "
    859 			    "on %s=%d (%s)\n", g_pname, topo_node_name(node),
    860 			    topo_node_instance(node), topo_strerror(err));
    861 	}
    862 
    863 	if (opt_V || opt_all) {
    864 		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
    865 			(void) fprintf(stderr, "%s: failed to get "
    866 			    "properties for %s=%d: %s\n", g_pname,
    867 			    topo_node_name(node), topo_node_instance(node),
    868 			    topo_strerror(err));
    869 		} else {
    870 			print_all_props(thp, node, nvl, ALL);
    871 			nvlist_free(nvl);
    872 		}
    873 	} else if (pcnt > 0)
    874 		print_props(thp, node);
    875 
    876 	(void) printf("\n");
    877 
    878 	return (TOPO_WALK_NEXT);
    879 }
    880 
    881 static void
    882 get_pargs(int argc, char *argv[])
    883 {
    884 	struct prop_args *pp;
    885 	char c, *s, *p;
    886 	int i = 0;
    887 
    888 	if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) {
    889 		(void) fprintf(stderr, "%s: failed to allocate property "
    890 		    "arguments\n", g_pname);
    891 		return;
    892 	}
    893 
    894 	for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) {
    895 		if (c == 'P') {
    896 
    897 			if (strcmp(optarg, ALL) == 0) {
    898 				opt_all++;
    899 				break;
    900 			}
    901 
    902 			if ((pp = pargs[i] = malloc(sizeof (struct prop_args)))
    903 			    == NULL) {
    904 				(void) fprintf(stderr, "%s: failed to "
    905 				    "allocate propertyarguments\n", g_pname);
    906 				return;
    907 			}
    908 			++i;
    909 			pp->group = NULL;
    910 			pp->prop = NULL;
    911 			pp->type = NULL;
    912 			pp->value = NULL;
    913 
    914 			p = optarg;
    915 			if ((s = strchr(p, '.')) != NULL) {
    916 				*s++ = '\0'; /* strike out delimiter */
    917 				pp->group = p;
    918 				p = s;
    919 				if ((s = strchr(p, '=')) != NULL) {
    920 					*s++ = '\0'; /* strike out delimiter */
    921 					pp->prop = p;
    922 					p = s;
    923 					if ((s = strchr(p, ':')) != NULL) {
    924 						*s++ = '\0';
    925 						pp->type = p;
    926 						pp->value = s;
    927 					} else {
    928 						(void) fprintf(stderr, "%s: "
    929 						    "property type not "
    930 						    "specified for assignment "
    931 						    " of %s.%s\n", g_pname,
    932 						    pp->group, pp->prop);
    933 						break;
    934 					}
    935 				} else {
    936 					pp->prop = p;
    937 				}
    938 			} else {
    939 				pp->group = p;
    940 			}
    941 			if (i >= pcnt)
    942 				break;
    943 		}
    944 	}
    945 
    946 	if (opt_all > 0) {
    947 		int j;
    948 
    949 		for (j = 0; j < i; ++j)
    950 			free(pargs[i]);
    951 		free(pargs);
    952 		pargs = NULL;
    953 	}
    954 }
    955 
    956 static int
    957 walk_topo(topo_hdl_t *thp, char *uuid)
    958 {
    959 	int err;
    960 	topo_walk_t *twp;
    961 	int flag;
    962 
    963 	if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err))
    964 	    == NULL) {
    965 		(void) fprintf(stderr, "%s: failed to walk %s topology:"
    966 		    " %s\n", g_pname, opt_s, topo_strerror(err));
    967 
    968 		return (-1);
    969 	}
    970 
    971 	/*
    972 	 * Print standard header
    973 	 */
    974 	if (!opt_e) {
    975 		char buf[32];
    976 		time_t tod = time(NULL);
    977 
    978 		(void) printf("TIME                 UUID\n");
    979 		(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
    980 		(void) printf("%-15s %-32s\n", buf, uuid);
    981 		(void) printf("\n");
    982 	}
    983 
    984 	flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD;
    985 
    986 	if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) {
    987 		(void) fprintf(stderr, "%s: failed to walk topology\n",
    988 		    g_pname);
    989 		topo_walk_fini(twp);
    990 		return (-1);
    991 	}
    992 
    993 	topo_walk_fini(twp);
    994 
    995 	return (0);
    996 }
    997 
    998 static void
    999 print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl)
   1000 {
   1001 	char *dstab = NULL, *nstab = NULL;
   1002 	int32_t version = -1;
   1003 	nvlist_t *pnvl;
   1004 	nvpair_t *pnvp;
   1005 
   1006 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab);
   1007 	(void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab);
   1008 	(void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version);
   1009 
   1010 	print_pgroup(thp, NULL, pgn, dstab, nstab, version);
   1011 
   1012 	for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL;
   1013 	    pnvp = nvlist_next_nvpair(nvl, pnvp)) {
   1014 
   1015 		/*
   1016 		 * Print property group and property name-value pair
   1017 		 */
   1018 		if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
   1019 		    == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
   1020 			(void) nvpair_value_nvlist(pnvp, &pnvl);
   1021 				print_prop_nameval(thp, NULL, pnvl);
   1022 
   1023 		}
   1024 
   1025 	}
   1026 }
   1027 
   1028 static void
   1029 print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl)
   1030 {
   1031 	int i, err;
   1032 	struct prop_args *pp;
   1033 	nvlist_t *pnvl;
   1034 
   1035 	for (i = 0; i < pcnt; ++i) {
   1036 		pp = pargs[i];
   1037 
   1038 		if (pp->group == NULL)
   1039 			continue;
   1040 
   1041 		pnvl = NULL;
   1042 
   1043 		/*
   1044 		 * If we have a valid value, this is a request to
   1045 		 * set a property.  Otherwise, just print the property
   1046 		 * group and any specified properties.
   1047 		 */
   1048 		if (pp->value == NULL) {
   1049 			if (pp->prop == NULL) {
   1050 
   1051 				/*
   1052 				 * Print all properties in this group
   1053 				 */
   1054 				if (topo_fmri_getpgrp(thp, nvl, pp->group,
   1055 				    &pnvl, &err) < 0) {
   1056 					(void) fprintf(stderr, "%s: failed to "
   1057 					    "get group %s: %s\n", g_pname,
   1058 					    pp->group, topo_strerror(err));
   1059 					continue;
   1060 				} else {
   1061 					print_fmri_pgroup(thp, pp->group,
   1062 					    pnvl);
   1063 					nvlist_free(pnvl);
   1064 					continue;
   1065 				}
   1066 			}
   1067 			if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop,
   1068 			    NULL, &pnvl, &err) < 0) {
   1069 				(void) fprintf(stderr, "%s: failed to get "
   1070 				    "%s.%s: %s\n", g_pname,
   1071 				    pp->group, pp->prop,
   1072 				    topo_strerror(err));
   1073 				continue;
   1074 			} else {
   1075 				print_fmri_pgroup(thp, pp->group, pnvl);
   1076 				print_prop_nameval(thp, NULL, pnvl);
   1077 				nvlist_free(nvl);
   1078 			}
   1079 		} else {
   1080 			set_prop(thp, NULL, nvl, pp);
   1081 		}
   1082 	}
   1083 }
   1084 
   1085 void
   1086 print_fmri(topo_hdl_t *thp, char *uuid)
   1087 {
   1088 	int ret, err;
   1089 	nvlist_t *nvl;
   1090 	char buf[32];
   1091 	time_t tod = time(NULL);
   1092 
   1093 	if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
   1094 		(void) fprintf(stderr, "%s: failed to convert %s to nvlist: "
   1095 		    "%s\n", g_pname, g_fmri, topo_strerror(err));
   1096 		return;
   1097 	}
   1098 
   1099 	(void) printf("TIME                 UUID\n");
   1100 	(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
   1101 	(void) printf("%-15s %-32s\n", buf, uuid);
   1102 	(void) printf("\n");
   1103 
   1104 	(void) printf("%s\n", (char *)g_fmri);
   1105 
   1106 	if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
   1107 		char *aname = NULL, *fname = NULL, *lname = NULL;
   1108 		nvlist_t *asru = NULL;
   1109 		nvlist_t *fru = NULL;
   1110 
   1111 		if (topo_fmri_asru(thp, nvl, &asru, &err) == 0)
   1112 			(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
   1113 		if (topo_fmri_fru(thp, nvl, &fru, &err) == 0)
   1114 			(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
   1115 		(void) topo_fmri_label(thp, nvl, &lname, &err);
   1116 
   1117 		nvlist_free(fru);
   1118 		nvlist_free(asru);
   1119 
   1120 		if (aname != NULL) {
   1121 			(void) printf("\tASRU: %s\n", aname);
   1122 			topo_hdl_strfree(thp, aname);
   1123 		} else {
   1124 			(void) printf("\tASRU: -\n");
   1125 		}
   1126 		if (fname != NULL) {
   1127 			(void) printf("\tFRU: %s\n", fname);
   1128 			topo_hdl_strfree(thp, fname);
   1129 		} else {
   1130 			(void) printf("\tFRU: -\n");
   1131 		}
   1132 		if (lname != NULL) {
   1133 			(void) printf("\tLabel: %s\n", lname);
   1134 			topo_hdl_strfree(thp, lname);
   1135 		} else {
   1136 			(void) printf("\tLabel: -\n");
   1137 		}
   1138 	}
   1139 
   1140 	if (opt_S) {
   1141 		if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
   1142 			(void) printf("\tPresent: -\n");
   1143 			(void) printf("\tUnusable: -\n");
   1144 			return;
   1145 		}
   1146 
   1147 		if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
   1148 			(void) printf("\tPresent: -\n");
   1149 		else
   1150 			(void) printf("\tPresent: %s\n",
   1151 			    ret ? "true" : "false");
   1152 
   1153 		if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
   1154 			(void) printf("\tUnusable: -\n");
   1155 		else
   1156 			(void) printf("\tUnusable: %s\n",
   1157 			    ret ? "true" : "false");
   1158 
   1159 		nvlist_free(nvl);
   1160 	}
   1161 
   1162 	if (pargs && pcnt > 0)
   1163 		print_fmri_props(thp, nvl);
   1164 }
   1165 
   1166 int
   1167 fmtopo_exit(topo_hdl_t *thp, char *uuid, int err)
   1168 {
   1169 	if (uuid != NULL)
   1170 		topo_hdl_strfree(thp, uuid);
   1171 
   1172 	if (thp != NULL) {
   1173 		topo_snap_release(thp);
   1174 		topo_close(thp);
   1175 	}
   1176 
   1177 	if (pargs) {
   1178 		int i;
   1179 		for (i = 0; i < pcnt; ++i)
   1180 			free(pargs[i]);
   1181 		free(pargs);
   1182 	}
   1183 
   1184 	return (err);
   1185 }
   1186 
   1187 int
   1188 main(int argc, char *argv[])
   1189 {
   1190 	topo_hdl_t *thp = NULL;
   1191 	char *uuid = NULL;
   1192 	int c, err = 0;
   1193 
   1194 	g_pname = argv[0];
   1195 
   1196 	while (optind < argc) {
   1197 		while ((c = getopt(argc, argv, optstr)) != -1) {
   1198 			switch (c) {
   1199 			case 'b':
   1200 				opt_b++;
   1201 				break;
   1202 			case 'C':
   1203 				(void) atexit(abort);
   1204 				break;
   1205 			case 'd':
   1206 				opt_d++;
   1207 				break;
   1208 			case 'e':
   1209 				opt_e++;
   1210 				break;
   1211 			case 'm':
   1212 				opt_m = optarg;
   1213 				break;
   1214 			case 'P':
   1215 				pcnt++;
   1216 				break;
   1217 			case 'p':
   1218 				opt_p++;
   1219 				break;
   1220 			case 'V':
   1221 				opt_V++;
   1222 				break;
   1223 			case 'R':
   1224 				opt_R = optarg;
   1225 				break;
   1226 			case 's':
   1227 				opt_s = optarg;
   1228 				break;
   1229 			case 'S':
   1230 				opt_S++;
   1231 				break;
   1232 			case 't':
   1233 				opt_t++;
   1234 				break;
   1235 			case 'x':
   1236 				opt_x++;
   1237 				break;
   1238 			default:
   1239 				return (usage(stderr));
   1240 			}
   1241 		}
   1242 
   1243 		if (optind < argc) {
   1244 			if (g_fmri != NULL) {
   1245 				(void) fprintf(stderr, "%s: illegal argument "
   1246 				    "-- %s\n", g_pname, argv[optind]);
   1247 				return (FMTOPO_EXIT_USAGE);
   1248 			} else {
   1249 				g_fmri = argv[optind++];
   1250 			}
   1251 		}
   1252 	}
   1253 
   1254 	if (pcnt > 0)
   1255 		get_pargs(argc, argv);
   1256 
   1257 	if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
   1258 		(void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
   1259 		    g_pname, topo_strerror(err));
   1260 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
   1261 	}
   1262 
   1263 	if (opt_d)
   1264 		topo_debug_set(thp, "module", "stderr");
   1265 
   1266 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
   1267 		(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
   1268 		    g_pname, topo_strerror(err));
   1269 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
   1270 	} else if (err != 0) {
   1271 		(void) fprintf(stderr, "%s: topology snapshot incomplete\n",
   1272 		    g_pname);
   1273 	}
   1274 
   1275 	if (opt_x) {
   1276 		if (opt_b) {
   1277 			(void) fprintf(stderr,
   1278 			    "%s: -b and -x cannot be specified together\n",
   1279 			    g_pname);
   1280 			return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE));
   1281 		}
   1282 
   1283 		err = 0;
   1284 		if (topo_xml_print(thp, stdout, opt_s, &err) < 0)
   1285 			(void) fprintf(stderr, "%s: failed to print xml "
   1286 			    "formatted topology:%s",  g_pname,
   1287 			    topo_strerror(err));
   1288 
   1289 		return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR :
   1290 		    FMTOPO_EXIT_SUCCESS));
   1291 	}
   1292 
   1293 	if (opt_t || walk_topo(thp, uuid) < 0) {
   1294 		if (g_fmri != NULL)
   1295 			/*
   1296 			 * Try getting some useful information
   1297 			 */
   1298 			print_fmri(thp, uuid);
   1299 
   1300 		return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
   1301 	}
   1302 
   1303 	return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS));
   1304 }
   1305