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