11414Scindi /*
21414Scindi * CDDL HEADER START
31414Scindi *
41414Scindi * The contents of this file are subject to the terms of the
51414Scindi * Common Development and Distribution License (the "License").
61414Scindi * You may not use this file except in compliance with the License.
71414Scindi *
81414Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91414Scindi * or http://www.opensolaris.org/os/licensing.
101414Scindi * See the License for the specific language governing permissions
111414Scindi * and limitations under the License.
121414Scindi *
131414Scindi * When distributing Covered Code, include this CDDL HEADER in each
141414Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151414Scindi * If applicable, add the following below this CDDL HEADER, with the
161414Scindi * fields enclosed by brackets "[]" replaced with your own identifying
171414Scindi * information: Portions Copyright [yyyy] [name of copyright owner]
181414Scindi *
191414Scindi * CDDL HEADER END
201414Scindi */
211414Scindi
221414Scindi /*
23*12967Sgavin.maltby@oracle.com * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
241414Scindi */
251414Scindi
261414Scindi
271414Scindi #include <sys/fm/protocol.h>
281414Scindi #include <fm/libtopo.h>
293062Scindi #include <ctype.h>
304087Scindi #include <fnmatch.h>
311414Scindi #include <limits.h>
321414Scindi #include <strings.h>
331414Scindi #include <stdio.h>
341414Scindi #include <errno.h>
354087Scindi #include <umem.h>
36*12967Sgavin.maltby@oracle.com #include <zone.h>
373062Scindi #include <sys/param.h>
381414Scindi
391414Scindi #define FMTOPO_EXIT_SUCCESS 0
401414Scindi #define FMTOPO_EXIT_ERROR 1
411414Scindi #define FMTOPO_EXIT_USAGE 2
421414Scindi
433062Scindi #define STDERR "stderr"
443062Scindi #define DOTS "..."
453062Scindi #define ALL "all"
463062Scindi
471414Scindi static const char *g_pname;
484087Scindi static const char *g_fmri = NULL;
491414Scindi
501414Scindi static const char *opt_R = "/";
511414Scindi static const char *opt_s = FM_FMRI_SCHEME_HC;
529501SRobert.Johnston@Sun.COM static const char optstr[] = "bCdem:P:pR:s:StVx";
539501SRobert.Johnston@Sun.COM static const char *opt_m;
541414Scindi
556341Scy152378 static int opt_b = 0;
566341Scy152378 static int opt_d = 0;
573062Scindi static int opt_e = 0;
583062Scindi static int opt_p = 0;
594087Scindi static int opt_S = 0;
604087Scindi static int opt_t = 0;
616341Scy152378 static int opt_V = 0;
623062Scindi static int opt_x = 0;
634087Scindi static int opt_all = 0;
644087Scindi
654087Scindi struct prop_args {
664087Scindi const char *group;
674087Scindi const char *prop;
684087Scindi const char *type;
694087Scindi const char *value;
704087Scindi };
714087Scindi
724087Scindi static struct prop_args **pargs = NULL;
734087Scindi static int pcnt = 0;
741414Scindi
751414Scindi static int
usage(FILE * fp)761414Scindi usage(FILE *fp)
771414Scindi {
781414Scindi (void) fprintf(fp,
797585SRobert.Johnston@Sun.COM "Usage: %s [-bCedpSVx] [-P group.property[=type:value]] "
809501SRobert.Johnston@Sun.COM "[-R root] [-m method] [-s scheme] [fmri]\n", g_pname);
811414Scindi
821414Scindi (void) fprintf(fp,
836341Scy152378 "\t-b walk in sibling-first order (default is child-first)\n"
841414Scindi "\t-C dump core after completing execution\n"
853062Scindi "\t-d set debug mode for libtopo modules\n"
863062Scindi "\t-e display FMRIs as paths using esc/eft notation\n"
879501SRobert.Johnston@Sun.COM "\t-m execute given method\n"
884087Scindi "\t-P get/set specified properties\n"
893062Scindi "\t-p display of FMRI protocol properties\n"
901414Scindi "\t-R set root directory for libtopo plug-ins and other files\n"
911414Scindi "\t-s display topology for the specified FMRI scheme\n"
924087Scindi "\t-S display FMRI status (present/usable)\n"
933062Scindi "\t-V set verbose mode\n"
943062Scindi "\t-x display a xml formatted topology\n");
951414Scindi
961414Scindi return (FMTOPO_EXIT_USAGE);
971414Scindi }
981414Scindi
994087Scindi static topo_type_t
str2type(const char * tstr)1004087Scindi str2type(const char *tstr)
1011414Scindi {
1024087Scindi topo_type_t type;
1034087Scindi
1044087Scindi if (tstr == NULL)
1054087Scindi return (TOPO_TYPE_INVALID);
1061414Scindi
1074087Scindi if (strcmp(tstr, "int32") == 0)
1084087Scindi type = TOPO_TYPE_INT32;
1094087Scindi else if (strcmp(tstr, "uint32") == 0)
1104087Scindi type = TOPO_TYPE_UINT32;
1114087Scindi else if (strcmp(tstr, "int64") == 0)
1124087Scindi type = TOPO_TYPE_INT64;
1134087Scindi else if (strcmp(tstr, "uint64") == 0)
1144087Scindi type = TOPO_TYPE_UINT64;
1154087Scindi else if (strcmp(tstr, "string") == 0)
1164087Scindi type = TOPO_TYPE_STRING;
1174087Scindi else if (strcmp(tstr, "fmri") == 0)
1184087Scindi type = TOPO_TYPE_FMRI;
1194087Scindi else {
1204087Scindi type = TOPO_TYPE_INVALID;
1211414Scindi }
1221414Scindi
1234087Scindi return (type);
1244087Scindi }
1251414Scindi
1264087Scindi static void
print_node(topo_hdl_t * thp,tnode_t * node,nvlist_t * nvl,const char * fmri)1274087Scindi print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri)
1284087Scindi {
1294087Scindi int err, ret;
1301414Scindi
1314087Scindi (void) printf("%s\n", (char *)fmri);
1324087Scindi
1334087Scindi if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
1341414Scindi char *aname = NULL, *fname = NULL, *lname = NULL;
1351414Scindi nvlist_t *asru = NULL;
1361414Scindi nvlist_t *fru = NULL;
1371414Scindi
1381414Scindi if (topo_node_asru(node, &asru, NULL, &err) == 0)
1394328Scindi (void) topo_fmri_nvl2str(thp, asru, &aname, &err);
1401414Scindi if (topo_node_fru(node, &fru, NULL, &err) == 0)
1414328Scindi (void) topo_fmri_nvl2str(thp, fru, &fname, &err);
1421414Scindi (void) topo_node_label(node, &lname, &err);
1431414Scindi if (aname != NULL) {
1441414Scindi nvlist_free(asru);
1451414Scindi (void) printf("\tASRU: %s\n", aname);
1461414Scindi topo_hdl_strfree(thp, aname);
1471414Scindi } else {
1481414Scindi (void) printf("\tASRU: -\n");
1491414Scindi }
1501414Scindi if (fname != NULL) {
1511414Scindi nvlist_free(fru);
1521414Scindi (void) printf("\tFRU: %s\n", fname);
1531414Scindi topo_hdl_strfree(thp, fname);
1541414Scindi } else {
1551414Scindi (void) printf("\tFRU: -\n");
1561414Scindi }
1571414Scindi if (lname != NULL) {
1581414Scindi (void) printf("\tLabel: %s\n", lname);
1591414Scindi topo_hdl_strfree(thp, lname);
1601414Scindi } else {
1611414Scindi (void) printf("\tLabel: -\n");
1621414Scindi }
1631414Scindi }
1641414Scindi
1654087Scindi if (opt_S) {
1664087Scindi if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
1674087Scindi (void) printf("\tPresent: -\n");
1684087Scindi else
1694087Scindi (void) printf("\tPresent: %s\n",
1704087Scindi ret ? "true" : "false");
1714087Scindi
1724087Scindi if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
1734087Scindi (void) printf("\tUnusable: -\n");
1744087Scindi else
1754087Scindi (void) printf("\tUnusable: %s\n",
1764087Scindi ret ? "true" : "false");
1774087Scindi }
1781414Scindi }
1791414Scindi
1801414Scindi static void
print_everstyle(tnode_t * node)1811414Scindi print_everstyle(tnode_t *node)
1821414Scindi {
1831414Scindi char buf[PATH_MAX], numbuf[64];
1841414Scindi nvlist_t *fmri, **hcl;
1851414Scindi int i, err;
1861414Scindi uint_t n;
1871414Scindi
1881414Scindi if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
1891414Scindi TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
1901414Scindi (void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
1911414Scindi g_pname, topo_node_name(node),
1921414Scindi topo_node_instance(node), topo_strerror(err));
1931414Scindi return;
1941414Scindi }
1951414Scindi
1961414Scindi if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
1971414Scindi (void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
1981414Scindi g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
1991414Scindi topo_node_instance(node));
2007243Srobj nvlist_free(fmri);
2011414Scindi return;
2021414Scindi }
2031414Scindi
2041414Scindi buf[0] = '\0';
2051414Scindi
2061414Scindi for (i = 0; i < n; i++) {
2071414Scindi char *name, *inst, *estr;
2081414Scindi ulong_t ul;
2091414Scindi
2101414Scindi if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
2111414Scindi nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
2121414Scindi (void) fprintf(stderr, "%s: failed to get "
2131414Scindi "name-instance for %s=%d\n", g_pname,
2141414Scindi topo_node_name(node), topo_node_instance(node));
2157243Srobj nvlist_free(fmri);
2161414Scindi return;
2171414Scindi }
2181414Scindi
2191414Scindi errno = 0;
2201414Scindi ul = strtoul(inst, &estr, 10);
2211414Scindi
2221414Scindi if (errno != 0 || estr == inst) {
2231414Scindi (void) fprintf(stderr, "%s: instance %s does not "
2241414Scindi "convert to an unsigned integer\n", g_pname, inst);
2251414Scindi }
2261414Scindi
2271414Scindi (void) strlcat(buf, "/", sizeof (buf));
2281414Scindi (void) strlcat(buf, name, sizeof (buf));
2291414Scindi (void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
2301414Scindi (void) strlcat(buf, numbuf, sizeof (buf));
2311414Scindi }
2327243Srobj nvlist_free(fmri);
2331414Scindi
2341414Scindi (void) printf("%s\n", buf);
2351414Scindi }
2361414Scindi
2373062Scindi static void
print_prop_nameval(topo_hdl_t * thp,tnode_t * node,nvlist_t * nvl)2387243Srobj print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl)
2393062Scindi {
2403062Scindi int err;
2413062Scindi topo_type_t type;
2427243Srobj char *tstr, *propn, buf[48], *factype;
2433062Scindi nvpair_t *pv_nvp;
2443323Scindi int i;
2453323Scindi uint_t nelem;
2463062Scindi
2473062Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL)
2483062Scindi return;
2493062Scindi
2503062Scindi /* Print property name */
2513062Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL ||
2523062Scindi nvpair_name(pv_nvp) == NULL ||
2533062Scindi strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) {
2543062Scindi (void) fprintf(stderr, "%s: malformed property name\n",
2553062Scindi g_pname);
2563062Scindi return;
2573062Scindi } else {
2584328Scindi (void) nvpair_value_string(pv_nvp, &propn);
2593062Scindi }
2603062Scindi
2613062Scindi if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL ||
2623062Scindi nvpair_name(pv_nvp) == NULL ||
2633062Scindi strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 ||
2644087Scindi nvpair_type(pv_nvp) != DATA_TYPE_UINT32) {
2653062Scindi (void) fprintf(stderr, "%s: malformed property type for %s\n",
2663062Scindi g_pname, propn);
2673062Scindi return;
2683062Scindi } else {
2694087Scindi (void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type);
2703062Scindi }
2713062Scindi
2723062Scindi switch (type) {
2733062Scindi case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break;
2743062Scindi case TOPO_TYPE_INT32: tstr = "int32"; break;
2753062Scindi case TOPO_TYPE_UINT32: tstr = "uint32"; break;
2763062Scindi case TOPO_TYPE_INT64: tstr = "int64"; break;
2773062Scindi case TOPO_TYPE_UINT64: tstr = "uint64"; break;
2787243Srobj case TOPO_TYPE_DOUBLE: tstr = "double"; break;
2793062Scindi case TOPO_TYPE_STRING: tstr = "string"; break;
2803062Scindi case TOPO_TYPE_FMRI: tstr = "fmri"; break;
2813062Scindi case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
2823062Scindi case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break;
2833062Scindi case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break;
2843062Scindi case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break;
2853062Scindi case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break;
2863062Scindi case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break;
2873062Scindi default: tstr = "unknown type";
2883062Scindi }
2893062Scindi
29011050SRobert.Johnston@Sun.COM (void) printf(" %-17s %-8s ", propn, tstr);
2913062Scindi
2923062Scindi /*
2933062Scindi * Get property value
2943062Scindi */
2953062Scindi if (nvpair_name(pv_nvp) == NULL ||
2963062Scindi (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) {
2973062Scindi (void) fprintf(stderr, "%s: malformed property value\n",
2983062Scindi g_pname);
2993062Scindi return;
3003062Scindi }
3013062Scindi
3023062Scindi switch (nvpair_type(pv_nvp)) {
3033062Scindi case DATA_TYPE_INT32: {
3043062Scindi int32_t val;
3053062Scindi (void) nvpair_value_int32(pv_nvp, &val);
3063062Scindi (void) printf(" %d", val);
3073062Scindi break;
3083062Scindi }
3093062Scindi case DATA_TYPE_UINT32: {
3107243Srobj uint32_t val, type;
3117243Srobj char val_str[49];
3127243Srobj nvlist_t *fac, *rsrc = NULL;
3137243Srobj
3143062Scindi (void) nvpair_value_uint32(pv_nvp, &val);
3157243Srobj if (node == NULL || topo_node_flags(node) !=
3167243Srobj TOPO_NODE_FACILITY)
3177243Srobj goto uint32_def;
3187243Srobj
3197243Srobj if (topo_node_resource(node, &rsrc, &err) != 0)
3207243Srobj goto uint32_def;
3217243Srobj
3227243Srobj if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0)
3237243Srobj goto uint32_def;
3247243Srobj
3257243Srobj if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE,
3267243Srobj &factype) != 0)
3277243Srobj goto uint32_def;
3287243Srobj
3297243Srobj nvlist_free(rsrc);
3307243Srobj rsrc = NULL;
3317243Srobj
3327243Srobj /*
3337243Srobj * Special case code to do friendlier printing of
3347243Srobj * facility node properties
3357243Srobj */
3367243Srobj if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
3377243Srobj (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
3387243Srobj topo_sensor_type_name(val, val_str, 48);
3397243Srobj (void) printf(" 0x%x (%s)", val, val_str);
3407243Srobj break;
3417243Srobj } else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) &&
3427243Srobj (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) {
3437243Srobj topo_led_type_name(val, val_str, 48);
3447243Srobj (void) printf(" 0x%x (%s)", val, val_str);
3457243Srobj break;
3467243Srobj } else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) {
3477243Srobj topo_sensor_units_name(val, val_str, 48);
3487243Srobj (void) printf(" 0x%x (%s)", val, val_str);
3497243Srobj break;
3507243Srobj } else if (strcmp(propn, TOPO_LED_MODE) == 0) {
3517243Srobj topo_led_state_name(val, val_str, 48);
3527243Srobj (void) printf(" 0x%x (%s)", val, val_str);
3537243Srobj break;
3547243Srobj } else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) &&
3557243Srobj (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) {
3567243Srobj if (topo_prop_get_uint32(node,
3577243Srobj TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
3587243Srobj &type, &err) != 0) {
3597243Srobj goto uint32_def;
3607243Srobj }
3617243Srobj topo_sensor_state_name(type, val, val_str, 48);
3627243Srobj (void) printf(" 0x%x (%s)", val, val_str);
3637243Srobj break;
3647243Srobj }
3657243Srobj uint32_def:
3663062Scindi (void) printf(" 0x%x", val);
3677243Srobj if (rsrc != NULL)
3687243Srobj nvlist_free(rsrc);
3693062Scindi break;
3703062Scindi }
3713062Scindi case DATA_TYPE_INT64: {
3723062Scindi int64_t val;
3733062Scindi (void) nvpair_value_int64(pv_nvp, &val);
3743062Scindi (void) printf(" %lld", (longlong_t)val);
3753062Scindi break;
3763062Scindi }
3773062Scindi case DATA_TYPE_UINT64: {
3783062Scindi uint64_t val;
3793062Scindi (void) nvpair_value_uint64(pv_nvp, &val);
3803062Scindi (void) printf(" 0x%llx", (u_longlong_t)val);
3813062Scindi break;
3823062Scindi }
3837243Srobj case DATA_TYPE_DOUBLE: {
3847243Srobj double val;
3857243Srobj (void) nvpair_value_double(pv_nvp, &val);
3867243Srobj (void) printf(" %lf", (double)val);
3877243Srobj break;
3887243Srobj }
3893062Scindi case DATA_TYPE_STRING: {
3903062Scindi char *val;
3913062Scindi (void) nvpair_value_string(pv_nvp, &val);
3923062Scindi if (!opt_V && strlen(val) > 48) {
3933062Scindi (void) snprintf(buf, 48, "%s...", val);
3943062Scindi (void) printf(" %s", buf);
3953062Scindi } else {
3963062Scindi (void) printf(" %s", val);
3973062Scindi }
3983062Scindi break;
3993062Scindi }
4003062Scindi case DATA_TYPE_NVLIST: {
4013062Scindi nvlist_t *val;
4023062Scindi char *fmri;
4033062Scindi (void) nvpair_value_nvlist(pv_nvp, &val);
4043062Scindi if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) {
4053062Scindi if (opt_V)
4063062Scindi nvlist_print(stdout, nvl);
4073062Scindi break;
4083062Scindi }
4093062Scindi
4103062Scindi if (!opt_V && strlen(fmri) > 48) {
4113062Scindi (void) snprintf(buf, 48, "%s", fmri);
4123062Scindi (void) snprintf(&buf[45], 4, "%s", DOTS);
4133062Scindi (void) printf(" %s", buf);
4143062Scindi } else {
4153062Scindi (void) printf(" %s", fmri);
4163062Scindi }
4173062Scindi
4183062Scindi topo_hdl_strfree(thp, fmri);
4193062Scindi break;
4203062Scindi }
42110234SRobert.Johnston@Sun.COM case DATA_TYPE_INT32_ARRAY: {
42210234SRobert.Johnston@Sun.COM int32_t *val;
42310234SRobert.Johnston@Sun.COM
42410234SRobert.Johnston@Sun.COM (void) nvpair_value_int32_array(pv_nvp, &val, &nelem);
42510234SRobert.Johnston@Sun.COM (void) printf(" [ ");
42610234SRobert.Johnston@Sun.COM for (i = 0; i < nelem; i++)
42710234SRobert.Johnston@Sun.COM (void) printf("%d ", val[i]);
42810234SRobert.Johnston@Sun.COM (void) printf("]");
42910234SRobert.Johnston@Sun.COM break;
43010234SRobert.Johnston@Sun.COM }
4313323Scindi case DATA_TYPE_UINT32_ARRAY: {
4323323Scindi uint32_t *val;
4333323Scindi
4343323Scindi (void) nvpair_value_uint32_array(pv_nvp, &val, &nelem);
4353323Scindi (void) printf(" [ ");
4363323Scindi for (i = 0; i < nelem; i++)
4373323Scindi (void) printf("%u ", val[i]);
4383323Scindi (void) printf("]");
4393323Scindi break;
4403323Scindi }
4417243Srobj case DATA_TYPE_INT64_ARRAY: {
4427243Srobj int64_t *val;
4437243Srobj
4447243Srobj (void) nvpair_value_int64_array(pv_nvp, &val, &nelem);
4457243Srobj (void) printf(" [ ");
4467243Srobj for (i = 0; i < nelem; i++)
4477243Srobj (void) printf("%lld ", val[i]);
4487243Srobj (void) printf("]");
4497243Srobj break;
4507243Srobj }
45110234SRobert.Johnston@Sun.COM case DATA_TYPE_UINT64_ARRAY: {
45210234SRobert.Johnston@Sun.COM uint64_t *val;
45310234SRobert.Johnston@Sun.COM
45410234SRobert.Johnston@Sun.COM (void) nvpair_value_uint64_array(pv_nvp, &val, &nelem);
45510234SRobert.Johnston@Sun.COM (void) printf(" [ ");
45610234SRobert.Johnston@Sun.COM for (i = 0; i < nelem; i++)
45710234SRobert.Johnston@Sun.COM (void) printf("%llu ", val[i]);
45810234SRobert.Johnston@Sun.COM (void) printf("]");
45910234SRobert.Johnston@Sun.COM break;
46010234SRobert.Johnston@Sun.COM }
4616640Scth case DATA_TYPE_STRING_ARRAY: {
4626640Scth char **val;
4636640Scth
4646640Scth (void) nvpair_value_string_array(pv_nvp, &val, &nelem);
4656640Scth (void) printf(" [ ");
4666640Scth for (i = 0; i < nelem; i++)
46710234SRobert.Johnston@Sun.COM (void) printf("\"%s\" ", val[i]);
4686640Scth (void) printf("]");
4696640Scth break;
4706640Scth }
4713062Scindi default:
4723062Scindi (void) fprintf(stderr, " unknown data type (%d)",
4733062Scindi nvpair_type(pv_nvp));
4743062Scindi break;
4753062Scindi }
4763062Scindi (void) printf("\n");
4773062Scindi }
4783062Scindi
4793062Scindi static void
print_pgroup(topo_hdl_t * thp,tnode_t * node,const char * pgn,char * dstab,char * nstab,int32_t version)4804087Scindi print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab,
4814087Scindi char *nstab, int32_t version)
4823062Scindi {
4834087Scindi int err;
4843062Scindi char buf[30];
4854087Scindi topo_pgroup_info_t *pgi = NULL;
4863062Scindi
4874087Scindi if (pgn == NULL)
4883062Scindi return;
4893062Scindi
4904087Scindi if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) {
4914087Scindi if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) {
4924087Scindi dstab = (char *)topo_stability2name(pgi->tpi_datastab);
4934087Scindi nstab = (char *)topo_stability2name(pgi->tpi_namestab);
4944087Scindi version = pgi->tpi_version;
4954087Scindi }
4964087Scindi }
4974087Scindi
4984087Scindi if (dstab == NULL || nstab == NULL || version == -1) {
49911050SRobert.Johnston@Sun.COM (void) printf(" group: %-30s version: - stability: -/-\n",
50011050SRobert.Johnston@Sun.COM pgn);
5014087Scindi } else if (!opt_V && strlen(pgn) > 30) {
5023062Scindi (void) snprintf(buf, 26, "%s", pgn);
5033062Scindi (void) snprintf(&buf[27], 4, "%s", DOTS);
50411050SRobert.Johnston@Sun.COM (void) printf(" group: %-30s version: %-3d stability: %s/%s\n",
5053062Scindi buf, version, nstab, dstab);
5063062Scindi } else {
50711050SRobert.Johnston@Sun.COM (void) printf(" group: %-30s version: %-3d stability: %s/%s\n",
5083062Scindi pgn, version, nstab, dstab);
5093062Scindi }
5103062Scindi
5114087Scindi if (pgi != NULL) {
5124087Scindi topo_hdl_strfree(thp, (char *)pgi->tpi_name);
5134087Scindi topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t));
5143062Scindi }
5153062Scindi }
5163062Scindi
5173062Scindi static void
print_all_props(topo_hdl_t * thp,tnode_t * node,nvlist_t * p_nv,const char * group)5184087Scindi print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv,
5194087Scindi const char *group)
5203062Scindi {
5213062Scindi char *pgn = NULL, *dstab = NULL, *nstab = NULL;
5224087Scindi int32_t version;
5233062Scindi nvlist_t *pg_nv, *pv_nv;
5243062Scindi nvpair_t *nvp, *pg_nvp;
5254087Scindi int pg_done, match, all = strcmp(group, ALL) == 0;
5263062Scindi
5273062Scindi for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
5283062Scindi nvp = nvlist_next_nvpair(p_nv, nvp)) {
5293062Scindi if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
5303062Scindi nvpair_type(nvp) != DATA_TYPE_NVLIST)
5313062Scindi continue;
5323062Scindi
5334087Scindi nstab = NULL;
5344087Scindi dstab = NULL;
5354087Scindi version = -1;
5364087Scindi pg_done = match = 0;
5373062Scindi (void) nvpair_value_nvlist(nvp, &pg_nv);
5383062Scindi for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
5393062Scindi pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
5403062Scindi /*
5413062Scindi * Print property group name and stability levels
5423062Scindi */
5433062Scindi if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp))
5443062Scindi == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5453062Scindi (void) nvpair_value_string(pg_nvp, &pgn);
5464087Scindi match = strcmp(group, pgn) == 0;
5474087Scindi continue;
5484087Scindi }
5493062Scindi
5504087Scindi if (strcmp(TOPO_PROP_GROUP_NSTAB,
5513062Scindi nvpair_name(pg_nvp)) == 0 &&
5523062Scindi nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5533062Scindi (void) nvpair_value_string(pg_nvp, &nstab);
5544087Scindi continue;
5554087Scindi }
5564087Scindi
5574087Scindi if (strcmp(TOPO_PROP_GROUP_DSTAB,
5583062Scindi nvpair_name(pg_nvp)) == 0 &&
5593062Scindi nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
5603062Scindi (void) nvpair_value_string(pg_nvp, &dstab);
5614087Scindi continue;
5624087Scindi }
5634087Scindi
5644087Scindi if (strcmp(TOPO_PROP_GROUP_VERSION,
5653062Scindi nvpair_name(pg_nvp)) == 0 &&
5663062Scindi nvpair_type(pg_nvp) == DATA_TYPE_INT32) {
5673062Scindi (void) nvpair_value_int32(pg_nvp, &version);
5684087Scindi continue;
5694087Scindi }
5704087Scindi
5714087Scindi if ((match || all) && !pg_done) {
5724087Scindi print_pgroup(thp, node, pgn, dstab, nstab,
5734087Scindi version);
5744087Scindi pg_done++;
5754087Scindi }
5764087Scindi
5774087Scindi /*
5784087Scindi * Print property group and property name-value pair
5794087Scindi */
5804087Scindi if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp))
5814087Scindi == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
5824087Scindi (void) nvpair_value_nvlist(pg_nvp, &pv_nv);
5834087Scindi if ((match || all) && pg_done) {
5847243Srobj print_prop_nameval(thp, node, pv_nv);
5854087Scindi }
5864087Scindi
5873062Scindi }
5883062Scindi
5894087Scindi }
5904087Scindi if (match && !all)
5914087Scindi return;
5924087Scindi }
5934087Scindi }
5944087Scindi
5954087Scindi static void
set_prop(topo_hdl_t * thp,tnode_t * node,nvlist_t * fmri,struct prop_args * pp)5964087Scindi set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp)
5974087Scindi {
5984087Scindi int ret, err = 0;
5994087Scindi topo_type_t type;
6004087Scindi nvlist_t *nvl, *f = NULL;
6014087Scindi char *end;
6024087Scindi
6034087Scindi if (pp->prop == NULL || pp->type == NULL || pp->value == NULL)
6044087Scindi return;
6054087Scindi
6064087Scindi if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) {
6074087Scindi (void) fprintf(stderr, "%s: invalid property type %s for %s\n",
6084087Scindi g_pname, pp->type, pp->prop);
6094087Scindi return;
6104087Scindi }
6114087Scindi
6124087Scindi if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6134087Scindi (void) fprintf(stderr, "%s: nvlist allocation failed for "
6144087Scindi "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value);
6154087Scindi return;
6164087Scindi }
6174087Scindi ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop);
6184087Scindi ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
6194087Scindi if (ret != 0) {
6204087Scindi (void) fprintf(stderr, "%s: invalid property type %s for %s\n",
6214087Scindi g_pname, pp->type, pp->prop);
6224087Scindi nvlist_free(nvl);
6234087Scindi return;
6244087Scindi }
6254087Scindi
6264087Scindi errno = 0;
6274087Scindi switch (type) {
6284087Scindi case TOPO_TYPE_INT32:
6294087Scindi {
6304087Scindi int32_t val;
6314087Scindi
6324087Scindi val = strtol(pp->value, &end, 0);
6334087Scindi if (errno == ERANGE) {
6344087Scindi ret = -1;
6354087Scindi break;
6364087Scindi }
6374087Scindi ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
6384087Scindi break;
6394087Scindi }
6404087Scindi case TOPO_TYPE_UINT32:
6414087Scindi {
6424087Scindi uint32_t val;
6434087Scindi
6444087Scindi val = strtoul(pp->value, &end, 0);
6454087Scindi if (errno == ERANGE) {
6464087Scindi ret = -1;
6474087Scindi break;
6484087Scindi }
6494087Scindi ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
6504087Scindi break;
6514087Scindi }
6524087Scindi case TOPO_TYPE_INT64:
6534087Scindi {
6544087Scindi int64_t val;
6554087Scindi
6564087Scindi val = strtoll(pp->value, &end, 0);
6574087Scindi if (errno == ERANGE) {
6584087Scindi ret = -1;
6594087Scindi break;
6604087Scindi }
6614087Scindi ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
6624087Scindi break;
6634087Scindi }
6644087Scindi case TOPO_TYPE_UINT64:
6654087Scindi {
6664087Scindi uint64_t val;
6674087Scindi
6684087Scindi val = strtoull(pp->value, &end, 0);
6694087Scindi if (errno == ERANGE) {
6704087Scindi ret = -1;
6714087Scindi break;
6724087Scindi }
6734087Scindi ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
6744087Scindi break;
6754087Scindi }
6764087Scindi case TOPO_TYPE_STRING:
6774087Scindi {
6784087Scindi ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
6794087Scindi pp->value);
6804087Scindi break;
6814087Scindi }
6824087Scindi case TOPO_TYPE_FMRI:
6834087Scindi {
6844087Scindi if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err))
6854087Scindi < 0)
6864087Scindi break;
6874087Scindi
6884087Scindi if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
6894087Scindi f)) != 0)
6904087Scindi err = ETOPO_PROP_NVL;
6914087Scindi break;
6924087Scindi }
6934087Scindi default:
6944087Scindi ret = -1;
6954087Scindi }
6964087Scindi
6974087Scindi if (ret != 0) {
6984087Scindi (void) fprintf(stderr, "%s: unable to set property value for "
6994087Scindi "%s: %s\n", g_pname, pp->prop, topo_strerror(err));
7004087Scindi nvlist_free(nvl);
7014087Scindi return;
7024087Scindi }
7034087Scindi
7044087Scindi if (node != NULL) {
7054087Scindi if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE,
7064087Scindi f, &ret) < 0) {
7074087Scindi (void) fprintf(stderr, "%s: unable to set property "
7084087Scindi "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
7094087Scindi pp->type, pp->value, topo_strerror(ret));
7104087Scindi nvlist_free(nvl);
7114087Scindi nvlist_free(f);
7124087Scindi return;
7134087Scindi }
7144087Scindi } else {
7154087Scindi if (topo_fmri_setprop(thp, fmri, pp->group, nvl,
7164087Scindi TOPO_PROP_MUTABLE, f, &ret) < 0) {
7174087Scindi (void) fprintf(stderr, "%s: unable to set property "
7184087Scindi "value for " "%s=%s:%s: %s\n", g_pname, pp->prop,
7194087Scindi pp->type, pp->value, topo_strerror(ret));
7204087Scindi nvlist_free(nvl);
7214087Scindi nvlist_free(f);
7224087Scindi return;
7234087Scindi }
7244087Scindi }
7254087Scindi
7264087Scindi nvlist_free(nvl);
7274087Scindi
7284087Scindi /*
7294087Scindi * Now, get the property back for printing
7304087Scindi */
7314087Scindi if (node != NULL) {
7324087Scindi if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl,
7334087Scindi &err) < 0) {
7344087Scindi (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
7354087Scindi g_pname, pp->group, pp->prop, topo_strerror(err));
7364087Scindi nvlist_free(f);
7374087Scindi return;
7384087Scindi }
7394087Scindi } else {
7404087Scindi if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop,
7414087Scindi f, &nvl, &err) < 0) {
7424087Scindi (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n",
7434087Scindi g_pname, pp->group, pp->prop, topo_strerror(err));
7444087Scindi nvlist_free(f);
7454087Scindi return;
7464087Scindi }
7474087Scindi }
7484087Scindi
7494087Scindi print_pgroup(thp, node, pp->group, NULL, NULL, 0);
7507243Srobj print_prop_nameval(thp, node, nvl);
7514087Scindi nvlist_free(nvl);
7524087Scindi
7534087Scindi nvlist_free(f);
7544087Scindi }
7554087Scindi
7564087Scindi static void
print_props(topo_hdl_t * thp,tnode_t * node)7574087Scindi print_props(topo_hdl_t *thp, tnode_t *node)
7584087Scindi {
7594087Scindi int i, err;
7604087Scindi nvlist_t *nvl;
7614087Scindi struct prop_args *pp;
7624087Scindi
7634087Scindi if (pcnt == 0)
7644087Scindi return;
7654087Scindi
7664087Scindi for (i = 0; i < pcnt; ++i) {
7674087Scindi pp = pargs[i];
7684087Scindi
7694087Scindi if (pp->group == NULL)
7704087Scindi continue;
7714087Scindi
7724087Scindi /*
7734087Scindi * If we have a valid value, this is a request to
7744087Scindi * set a property. Otherwise, just print the property
7754087Scindi * group and any specified properties.
7764087Scindi */
7774087Scindi if (pp->value == NULL) {
7784087Scindi if (pp->prop == NULL) {
7794087Scindi
7804087Scindi /*
7814087Scindi * Print all properties in this group
7824087Scindi */
7834087Scindi if ((nvl = topo_prop_getprops(node, &err))
7844087Scindi == NULL) {
7854087Scindi (void) fprintf(stderr, "%s: failed to "
7864087Scindi "get %s: %s\n", g_pname,
7874087Scindi pp->group,
7884087Scindi topo_strerror(err));
7894087Scindi continue;
7903062Scindi } else {
7914087Scindi print_all_props(thp, node, nvl,
7924087Scindi pp->group);
7934087Scindi nvlist_free(nvl);
7943062Scindi continue;
7953062Scindi }
7963062Scindi }
7974087Scindi if (topo_prop_getprop(node, pp->group, pp->prop,
7984087Scindi NULL, &nvl, &err) < 0) {
7994087Scindi (void) fprintf(stderr, "%s: failed to get "
8004087Scindi "%s.%s: %s\n", g_pname,
8014087Scindi pp->group, pp->prop,
8024087Scindi topo_strerror(err));
8034087Scindi continue;
8044087Scindi } else {
8054087Scindi print_pgroup(thp, node, pp->group, NULL,
8064087Scindi NULL, 0);
8077243Srobj print_prop_nameval(thp, node, nvl);
8084087Scindi nvlist_free(nvl);
8094087Scindi }
8104087Scindi } else {
8114087Scindi set_prop(thp, node, NULL, pp);
8123062Scindi }
8133062Scindi }
8143062Scindi }
8153062Scindi
8161414Scindi /*ARGSUSED*/
8171414Scindi static int
walk_node(topo_hdl_t * thp,tnode_t * node,void * arg)8184087Scindi walk_node(topo_hdl_t *thp, tnode_t *node, void *arg)
8191414Scindi {
8203062Scindi int err;
8213062Scindi nvlist_t *nvl;
8229501SRobert.Johnston@Sun.COM nvlist_t *rsrc, *out;
8234087Scindi char *s;
8243062Scindi
8253062Scindi if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
8261414Scindi print_everstyle(node);
8273062Scindi return (TOPO_WALK_NEXT);
8283062Scindi }
8291414Scindi
8304087Scindi if (topo_node_resource(node, &rsrc, &err) < 0) {
8314087Scindi (void) fprintf(stderr, "%s: failed to get resource: "
8324087Scindi "%s", g_pname, topo_strerror(err));
8334087Scindi return (TOPO_WALK_NEXT);
8344087Scindi }
8354087Scindi if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) {
8364087Scindi (void) fprintf(stderr, "%s: failed to convert "
8374087Scindi "resource to FMRI string: %s", g_pname,
8384087Scindi topo_strerror(err));
8394087Scindi nvlist_free(rsrc);
8404087Scindi return (TOPO_WALK_NEXT);
8414087Scindi }
8421414Scindi
8434087Scindi if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) {
8449501SRobert.Johnston@Sun.COM nvlist_free(rsrc);
8459501SRobert.Johnston@Sun.COM topo_hdl_strfree(thp, s);
8469501SRobert.Johnston@Sun.COM return (TOPO_WALK_NEXT);
8474087Scindi }
8484087Scindi
8494087Scindi print_node(thp, node, rsrc, s);
8504087Scindi topo_hdl_strfree(thp, s);
8514087Scindi nvlist_free(rsrc);
8524087Scindi
8539501SRobert.Johnston@Sun.COM if (opt_m != NULL) {
8549501SRobert.Johnston@Sun.COM if (topo_method_invoke(node, opt_m, 0, NULL, &out, &err) == 0) {
8559501SRobert.Johnston@Sun.COM nvlist_print(stdout, out);
8569501SRobert.Johnston@Sun.COM nvlist_free(out);
8579501SRobert.Johnston@Sun.COM } else if (err != ETOPO_METHOD_NOTSUP)
8589501SRobert.Johnston@Sun.COM (void) fprintf(stderr, "%s: method failed unexpectedly "
8599501SRobert.Johnston@Sun.COM "on %s=%d (%s)\n", g_pname, topo_node_name(node),
8609501SRobert.Johnston@Sun.COM topo_node_instance(node), topo_strerror(err));
8619501SRobert.Johnston@Sun.COM }
8629501SRobert.Johnston@Sun.COM
8634087Scindi if (opt_V || opt_all) {
8643062Scindi if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
8653062Scindi (void) fprintf(stderr, "%s: failed to get "
8663062Scindi "properties for %s=%d: %s\n", g_pname,
8673062Scindi topo_node_name(node), topo_node_instance(node),
8683062Scindi topo_strerror(err));
8691414Scindi } else {
8704087Scindi print_all_props(thp, node, nvl, ALL);
8711414Scindi nvlist_free(nvl);
8721414Scindi }
8737243Srobj } else if (pcnt > 0)
8744087Scindi print_props(thp, node);
8751414Scindi
87611050SRobert.Johnston@Sun.COM (void) printf("\n");
8773062Scindi
8781414Scindi return (TOPO_WALK_NEXT);
8791414Scindi }
8801414Scindi
8814087Scindi static void
get_pargs(int argc,char * argv[])8824087Scindi get_pargs(int argc, char *argv[])
8831414Scindi {
8844087Scindi struct prop_args *pp;
8854087Scindi char c, *s, *p;
8864087Scindi int i = 0;
8871414Scindi
8884087Scindi if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) {
8894087Scindi (void) fprintf(stderr, "%s: failed to allocate property "
8904087Scindi "arguments\n", g_pname);
8914087Scindi return;
8924087Scindi }
8934087Scindi
8944087Scindi for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) {
8954087Scindi if (c == 'P') {
8964087Scindi
8974087Scindi if (strcmp(optarg, ALL) == 0) {
8984087Scindi opt_all++;
8993062Scindi break;
9004087Scindi }
9014087Scindi
9024087Scindi if ((pp = pargs[i] = malloc(sizeof (struct prop_args)))
9034087Scindi == NULL) {
9044087Scindi (void) fprintf(stderr, "%s: failed to "
9054087Scindi "allocate propertyarguments\n", g_pname);
9064087Scindi return;
9074087Scindi }
9084087Scindi ++i;
9094087Scindi pp->group = NULL;
9104087Scindi pp->prop = NULL;
9114087Scindi pp->type = NULL;
9124087Scindi pp->value = NULL;
9134087Scindi
9144087Scindi p = optarg;
9154087Scindi if ((s = strchr(p, '.')) != NULL) {
9164087Scindi *s++ = '\0'; /* strike out delimiter */
9174087Scindi pp->group = p;
9184087Scindi p = s;
9194087Scindi if ((s = strchr(p, '=')) != NULL) {
9204087Scindi *s++ = '\0'; /* strike out delimiter */
9214087Scindi pp->prop = p;
9224087Scindi p = s;
9234087Scindi if ((s = strchr(p, ':')) != NULL) {
9244087Scindi *s++ = '\0';
9254087Scindi pp->type = p;
9264087Scindi pp->value = s;
9274087Scindi } else {
9284087Scindi (void) fprintf(stderr, "%s: "
9294087Scindi "property type not "
9304087Scindi "specified for assignment "
9314087Scindi " of %s.%s\n", g_pname,
9324087Scindi pp->group, pp->prop);
9334087Scindi break;
9344087Scindi }
9354087Scindi } else {
9364087Scindi pp->prop = p;
9374087Scindi }
9384087Scindi } else {
9394087Scindi pp->group = p;
9404087Scindi }
9414087Scindi if (i >= pcnt)
9421414Scindi break;
9431414Scindi }
9441414Scindi }
9451414Scindi
9464087Scindi if (opt_all > 0) {
9474087Scindi int j;
9481414Scindi
9494087Scindi for (j = 0; j < i; ++j)
9504087Scindi free(pargs[i]);
9514087Scindi free(pargs);
9524087Scindi pargs = NULL;
9531414Scindi }
9544087Scindi }
9553062Scindi
9564087Scindi static int
walk_topo(topo_hdl_t * thp,char * uuid)9574087Scindi walk_topo(topo_hdl_t *thp, char *uuid)
9584087Scindi {
9594087Scindi int err;
9604087Scindi topo_walk_t *twp;
9616341Scy152378 int flag;
9623062Scindi
963*12967Sgavin.maltby@oracle.com if (getzoneid() != GLOBAL_ZONEID &&
964*12967Sgavin.maltby@oracle.com strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
965*12967Sgavin.maltby@oracle.com return (0);
966*12967Sgavin.maltby@oracle.com }
967*12967Sgavin.maltby@oracle.com
9684087Scindi if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err))
9691414Scindi == NULL) {
9701414Scindi (void) fprintf(stderr, "%s: failed to walk %s topology:"
9711414Scindi " %s\n", g_pname, opt_s, topo_strerror(err));
9721414Scindi
9734087Scindi return (-1);
9741414Scindi }
9751414Scindi
9763062Scindi /*
9773062Scindi * Print standard header
9783062Scindi */
9793062Scindi if (!opt_e) {
9803062Scindi char buf[32];
9813062Scindi time_t tod = time(NULL);
9823062Scindi
98311050SRobert.Johnston@Sun.COM (void) printf("TIME UUID\n");
9843062Scindi (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
9853062Scindi (void) printf("%-15s %-32s\n", buf, uuid);
9863062Scindi (void) printf("\n");
9873062Scindi }
9881414Scindi
9896341Scy152378 flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD;
9906341Scy152378
9916341Scy152378 if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) {
9921414Scindi (void) fprintf(stderr, "%s: failed to walk topology\n",
9931414Scindi g_pname);
9942027Ssethg topo_walk_fini(twp);
9954087Scindi return (-1);
9961414Scindi }
9971414Scindi
9981414Scindi topo_walk_fini(twp);
9994087Scindi
10004087Scindi return (0);
10014087Scindi }
10024087Scindi
10034087Scindi static void
print_fmri_pgroup(topo_hdl_t * thp,const char * pgn,nvlist_t * nvl)10044087Scindi print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl)
10054087Scindi {
10064087Scindi char *dstab = NULL, *nstab = NULL;
10074087Scindi int32_t version = -1;
10084087Scindi nvlist_t *pnvl;
10094087Scindi nvpair_t *pnvp;
10104087Scindi
10114087Scindi (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab);
10124087Scindi (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab);
10134087Scindi (void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version);
10144087Scindi
10154087Scindi print_pgroup(thp, NULL, pgn, dstab, nstab, version);
10164087Scindi
10174087Scindi for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL;
10184087Scindi pnvp = nvlist_next_nvpair(nvl, pnvp)) {
10194087Scindi
10204087Scindi /*
10214087Scindi * Print property group and property name-value pair
10224087Scindi */
10234087Scindi if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp))
10244087Scindi == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) {
10254087Scindi (void) nvpair_value_nvlist(pnvp, &pnvl);
10267243Srobj print_prop_nameval(thp, NULL, pnvl);
10274087Scindi
10284087Scindi }
10294087Scindi
10304087Scindi }
10314087Scindi }
10324087Scindi
10334087Scindi static void
print_fmri_props(topo_hdl_t * thp,nvlist_t * nvl)10344087Scindi print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl)
10354087Scindi {
10364087Scindi int i, err;
10374087Scindi struct prop_args *pp;
10384087Scindi nvlist_t *pnvl;
10394087Scindi
10404087Scindi for (i = 0; i < pcnt; ++i) {
10414087Scindi pp = pargs[i];
10424087Scindi
10434087Scindi if (pp->group == NULL)
10444087Scindi continue;
10454087Scindi
10464087Scindi pnvl = NULL;
10474087Scindi
10484087Scindi /*
10494087Scindi * If we have a valid value, this is a request to
10504087Scindi * set a property. Otherwise, just print the property
10514087Scindi * group and any specified properties.
10524087Scindi */
10534087Scindi if (pp->value == NULL) {
10544087Scindi if (pp->prop == NULL) {
10554087Scindi
10564087Scindi /*
10574087Scindi * Print all properties in this group
10584087Scindi */
10594087Scindi if (topo_fmri_getpgrp(thp, nvl, pp->group,
10604087Scindi &pnvl, &err) < 0) {
10614087Scindi (void) fprintf(stderr, "%s: failed to "
10624087Scindi "get group %s: %s\n", g_pname,
10634087Scindi pp->group, topo_strerror(err));
10644087Scindi continue;
10654087Scindi } else {
10667243Srobj print_fmri_pgroup(thp, pp->group,
10677243Srobj pnvl);
10684087Scindi nvlist_free(pnvl);
10694087Scindi continue;
10704087Scindi }
10714087Scindi }
10724087Scindi if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop,
10734087Scindi NULL, &pnvl, &err) < 0) {
10744087Scindi (void) fprintf(stderr, "%s: failed to get "
10754087Scindi "%s.%s: %s\n", g_pname,
10764087Scindi pp->group, pp->prop,
10774087Scindi topo_strerror(err));
10784087Scindi continue;
10794087Scindi } else {
10804087Scindi print_fmri_pgroup(thp, pp->group, pnvl);
10817243Srobj print_prop_nameval(thp, NULL, pnvl);
10824087Scindi nvlist_free(nvl);
10834087Scindi }
10844087Scindi } else {
10854087Scindi set_prop(thp, NULL, nvl, pp);
10864087Scindi }
10874087Scindi }
10884087Scindi }
10894087Scindi
10904087Scindi void
print_fmri(topo_hdl_t * thp,char * uuid)10914087Scindi print_fmri(topo_hdl_t *thp, char *uuid)
10924087Scindi {
10934087Scindi int ret, err;
10944087Scindi nvlist_t *nvl;
10954087Scindi char buf[32];
10964087Scindi time_t tod = time(NULL);
10974087Scindi
10984087Scindi if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
10994087Scindi (void) fprintf(stderr, "%s: failed to convert %s to nvlist: "
11004087Scindi "%s\n", g_pname, g_fmri, topo_strerror(err));
11014087Scindi return;
11024087Scindi }
11034087Scindi
110411050SRobert.Johnston@Sun.COM (void) printf("TIME UUID\n");
11054087Scindi (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
11064087Scindi (void) printf("%-15s %-32s\n", buf, uuid);
11074087Scindi (void) printf("\n");
11084087Scindi
11094087Scindi (void) printf("%s\n", (char *)g_fmri);
11104087Scindi
11114087Scindi if (opt_p && !(pcnt > 0 || opt_V || opt_all)) {
11124087Scindi char *aname = NULL, *fname = NULL, *lname = NULL;
11134087Scindi nvlist_t *asru = NULL;
11144087Scindi nvlist_t *fru = NULL;
11154087Scindi
11164087Scindi if (topo_fmri_asru(thp, nvl, &asru, &err) == 0)
11174328Scindi (void) topo_fmri_nvl2str(thp, asru, &aname, &err);
11184087Scindi if (topo_fmri_fru(thp, nvl, &fru, &err) == 0)
11194328Scindi (void) topo_fmri_nvl2str(thp, fru, &fname, &err);
11204087Scindi (void) topo_fmri_label(thp, nvl, &lname, &err);
11214087Scindi
11224087Scindi nvlist_free(fru);
11234087Scindi nvlist_free(asru);
11244087Scindi
11254087Scindi if (aname != NULL) {
11264087Scindi (void) printf("\tASRU: %s\n", aname);
11274087Scindi topo_hdl_strfree(thp, aname);
11284087Scindi } else {
11294087Scindi (void) printf("\tASRU: -\n");
11304087Scindi }
11314087Scindi if (fname != NULL) {
11324087Scindi (void) printf("\tFRU: %s\n", fname);
11334087Scindi topo_hdl_strfree(thp, fname);
11344087Scindi } else {
11354087Scindi (void) printf("\tFRU: -\n");
11364087Scindi }
11374087Scindi if (lname != NULL) {
11384087Scindi (void) printf("\tLabel: %s\n", lname);
11394087Scindi topo_hdl_strfree(thp, lname);
11404087Scindi } else {
11414087Scindi (void) printf("\tLabel: -\n");
11424087Scindi }
11434087Scindi }
11444087Scindi
11454087Scindi if (opt_S) {
11464087Scindi if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) {
11474087Scindi (void) printf("\tPresent: -\n");
11484087Scindi (void) printf("\tUnusable: -\n");
11494087Scindi return;
11504087Scindi }
11514087Scindi
11524087Scindi if ((ret = topo_fmri_present(thp, nvl, &err)) < 0)
11534087Scindi (void) printf("\tPresent: -\n");
11544087Scindi else
11554087Scindi (void) printf("\tPresent: %s\n",
11564087Scindi ret ? "true" : "false");
11574087Scindi
11584087Scindi if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0)
11594087Scindi (void) printf("\tUnusable: -\n");
11604087Scindi else
11614087Scindi (void) printf("\tUnusable: %s\n",
11624087Scindi ret ? "true" : "false");
11634087Scindi
11644087Scindi nvlist_free(nvl);
11654087Scindi }
11664087Scindi
11675068Srobj if (pargs && pcnt > 0)
11684087Scindi print_fmri_props(thp, nvl);
11694087Scindi }
11704087Scindi
11714087Scindi int
fmtopo_exit(topo_hdl_t * thp,char * uuid,int err)11724087Scindi fmtopo_exit(topo_hdl_t *thp, char *uuid, int err)
11734087Scindi {
11744087Scindi if (uuid != NULL)
11754087Scindi topo_hdl_strfree(thp, uuid);
11764087Scindi
11774087Scindi if (thp != NULL) {
11784087Scindi topo_snap_release(thp);
11794087Scindi topo_close(thp);
11804087Scindi }
11814087Scindi
11824087Scindi if (pargs) {
11834087Scindi int i;
11844087Scindi for (i = 0; i < pcnt; ++i)
11854087Scindi free(pargs[i]);
11864087Scindi free(pargs);
11874087Scindi }
11884087Scindi
11894087Scindi return (err);
11904087Scindi }
11914087Scindi
11924087Scindi int
main(int argc,char * argv[])11934087Scindi main(int argc, char *argv[])
11944087Scindi {
11954087Scindi topo_hdl_t *thp = NULL;
11964087Scindi char *uuid = NULL;
11974087Scindi int c, err = 0;
11984087Scindi
11994087Scindi g_pname = argv[0];
12004087Scindi
12014087Scindi while (optind < argc) {
12024087Scindi while ((c = getopt(argc, argv, optstr)) != -1) {
12034087Scindi switch (c) {
12046341Scy152378 case 'b':
12056341Scy152378 opt_b++;
12066341Scy152378 break;
12074087Scindi case 'C':
120811050SRobert.Johnston@Sun.COM (void) atexit(abort);
12094087Scindi break;
12104087Scindi case 'd':
12114087Scindi opt_d++;
12124087Scindi break;
12134087Scindi case 'e':
12144087Scindi opt_e++;
12154087Scindi break;
12169501SRobert.Johnston@Sun.COM case 'm':
12179501SRobert.Johnston@Sun.COM opt_m = optarg;
12189501SRobert.Johnston@Sun.COM break;
12194087Scindi case 'P':
12204087Scindi pcnt++;
12214087Scindi break;
12224087Scindi case 'p':
12234087Scindi opt_p++;
12244087Scindi break;
12254087Scindi case 'V':
12264087Scindi opt_V++;
12274087Scindi break;
12284087Scindi case 'R':
12294087Scindi opt_R = optarg;
12304087Scindi break;
12314087Scindi case 's':
12324087Scindi opt_s = optarg;
12334087Scindi break;
12344087Scindi case 'S':
12354087Scindi opt_S++;
12364087Scindi break;
12374087Scindi case 't':
12384087Scindi opt_t++;
12394087Scindi break;
12404087Scindi case 'x':
12414087Scindi opt_x++;
12424087Scindi break;
12434087Scindi default:
12444087Scindi return (usage(stderr));
12454087Scindi }
12464087Scindi }
12474087Scindi
12484087Scindi if (optind < argc) {
12494087Scindi if (g_fmri != NULL) {
12504087Scindi (void) fprintf(stderr, "%s: illegal argument "
12514087Scindi "-- %s\n", g_pname, argv[optind]);
12524087Scindi return (FMTOPO_EXIT_USAGE);
12534087Scindi } else {
12544087Scindi g_fmri = argv[optind++];
12554087Scindi }
12564087Scindi }
12574087Scindi }
12584087Scindi
12594087Scindi if (pcnt > 0)
12604087Scindi get_pargs(argc, argv);
12614087Scindi
12624087Scindi if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
12634087Scindi (void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
12644087Scindi g_pname, topo_strerror(err));
12654087Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
12664087Scindi }
12674087Scindi
12684087Scindi if (opt_d)
12694087Scindi topo_debug_set(thp, "module", "stderr");
12704087Scindi
12714087Scindi if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
12724087Scindi (void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
12734087Scindi g_pname, topo_strerror(err));
12744087Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
12754087Scindi } else if (err != 0) {
1276*12967Sgavin.maltby@oracle.com (void) fprintf(stderr, "%s: topology snapshot incomplete%s\n",
1277*12967Sgavin.maltby@oracle.com g_pname, getzoneid() != GLOBAL_ZONEID &&
1278*12967Sgavin.maltby@oracle.com strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0 ?
1279*12967Sgavin.maltby@oracle.com " (" FM_FMRI_SCHEME_HC " scheme does not enumerate "
1280*12967Sgavin.maltby@oracle.com "in a non-global zone)": "");
12814087Scindi }
12824087Scindi
12836341Scy152378 if (opt_x) {
12846341Scy152378 if (opt_b) {
12856341Scy152378 (void) fprintf(stderr,
12866341Scy152378 "%s: -b and -x cannot be specified together\n",
12876341Scy152378 g_pname);
12886341Scy152378 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE));
12896341Scy152378 }
12904087Scindi
12914087Scindi err = 0;
12924087Scindi if (topo_xml_print(thp, stdout, opt_s, &err) < 0)
12934087Scindi (void) fprintf(stderr, "%s: failed to print xml "
12944087Scindi "formatted topology:%s", g_pname,
12954087Scindi topo_strerror(err));
12964087Scindi
12974087Scindi return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR :
12984087Scindi FMTOPO_EXIT_SUCCESS));
12994087Scindi }
13004087Scindi
13014087Scindi if (opt_t || walk_topo(thp, uuid) < 0) {
13024087Scindi if (g_fmri != NULL)
13034087Scindi /*
13044087Scindi * Try getting some useful information
13054087Scindi */
13064087Scindi print_fmri(thp, uuid);
13074087Scindi
13084087Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR));
13094087Scindi }
13104087Scindi
13114328Scindi return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS));
13121414Scindi }
1313