fmtopo.c revision 724365f7556fc4201fdb11766ebc6bd918523130
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/fm/protocol.h>
#include <fm/libtopo.h>
#include <limits.h>
#include <strings.h>
#include <stdio.h>
#include <errno.h>
#define FMTOPO_EXIT_SUCCESS 0
#define FMTOPO_EXIT_ERROR 1
#define FMTOPO_EXIT_USAGE 2
static const char *g_pname;
static const char *opt_R = "/";
static const char *opt_s = FM_FMRI_SCHEME_HC;
static int opt_e;
static int opt_d;
static int opt_v;
static int opt_V;
static int
usage(FILE *fp)
{
(void) fprintf(fp,
"Usage: %s [-Cdev] [-R root] [-s scheme]\n", g_pname);
(void) fprintf(fp,
"\t-C dump core after completing execution\n"
"\t-d set debug mode for libtopo\n"
"\t-e display nodes as paths using esc/eft notation\n"
"\t-R set root directory for libtopo plug-ins and other files\n"
"\t-s display topology for the specified FMRI scheme\n"
"\t-v set verbose mode (display node ASRU, FRU and label)\n"
"\t-V set verbose mode (display node properties)\n");
return (FMTOPO_EXIT_USAGE);
}
static void
print_fmri(topo_hdl_t *thp, tnode_t *node)
{
int err;
char *name;
nvlist_t *fmri;
if (topo_node_resource(node, &fmri, &err) < 0) {
(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
g_pname, topo_node_name(node),
topo_node_instance(node), topo_strerror(err));
return;
}
if (topo_fmri_nvl2str(thp, fmri, &name, &err) < 0) {
(void) fprintf(stderr, "%s: failed to convert fmri for %s=%d "
"to a string: %s\n", g_pname, topo_node_name(node),
topo_node_instance(node), topo_strerror(err));
nvlist_free(fmri);
return;
}
(void) printf("%s\n", name);
if (opt_v) {
char *aname = NULL, *fname = NULL, *lname = NULL;
nvlist_t *asru = NULL;
nvlist_t *fru = NULL;
if (topo_node_asru(node, &asru, NULL, &err) == 0)
(void) topo_fmri_nvl2str(thp, asru, &aname, &err);
if (topo_node_fru(node, &fru, NULL, &err) == 0)
(void) topo_fmri_nvl2str(thp, fru, &fname, &err);
(void) topo_node_label(node, &lname, &err);
if (aname != NULL) {
nvlist_free(asru);
(void) printf("\tASRU: %s\n", aname);
topo_hdl_strfree(thp, aname);
} else {
(void) printf("\tASRU: -\n");
}
if (fname != NULL) {
nvlist_free(fru);
(void) printf("\tFRU: %s\n", fname);
topo_hdl_strfree(thp, fname);
} else {
(void) printf("\tFRU: -\n");
}
if (lname != NULL) {
(void) printf("\tLabel: %s\n", lname);
topo_hdl_strfree(thp, lname);
} else {
(void) printf("\tLabel: -\n");
}
}
nvlist_free(fmri);
if (opt_d) {
fmri = NULL;
if (topo_fmri_str2nvl(thp, name, &fmri, &err) < 0) {
(void) fprintf(stderr, "%s: failed to convert "
"alternate fmri for %s=%d: %s\n", g_pname,
topo_node_name(node), topo_node_instance(node),
topo_strerror(err));
} else {
nvlist_print(stderr, fmri);
nvlist_free(fmri);
}
}
topo_hdl_strfree(thp, name);
}
static void
print_everstyle(tnode_t *node)
{
char buf[PATH_MAX], numbuf[64];
nvlist_t *fmri, **hcl;
int i, err;
uint_t n;
if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL,
TOPO_PROP_RESOURCE, &fmri, &err) < 0) {
(void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n",
g_pname, topo_node_name(node),
topo_node_instance(node), topo_strerror(err));
return;
}
if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) {
(void) fprintf(stderr, "%s: failed to find %s for %s=%d\n",
g_pname, FM_FMRI_HC_LIST, topo_node_name(node),
topo_node_instance(node));
return;
}
buf[0] = '\0';
for (i = 0; i < n; i++) {
char *name, *inst, *estr;
ulong_t ul;
if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 ||
nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) {
(void) fprintf(stderr, "%s: failed to get "
"name-instance for %s=%d\n", g_pname,
topo_node_name(node), topo_node_instance(node));
return;
}
errno = 0;
ul = strtoul(inst, &estr, 10);
if (errno != 0 || estr == inst) {
(void) fprintf(stderr, "%s: instance %s does not "
"convert to an unsigned integer\n", g_pname, inst);
}
(void) strlcat(buf, "/", sizeof (buf));
(void) strlcat(buf, name, sizeof (buf));
(void) snprintf(numbuf, sizeof (numbuf), "%u", ul);
(void) strlcat(buf, numbuf, sizeof (buf));
}
(void) printf("%s\n", buf);
}
/*ARGSUSED*/
static int
print_tnode(topo_hdl_t *thp, tnode_t *node, void *arg)
{
if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0)
print_everstyle(node);
else
print_fmri(thp, node);
if (opt_V) {
nvlist_t *nvl = topo_prop_get_all(thp, node);
if (nvl == NULL) {
(void) fprintf(stderr, "%s: failed to get properties "
"for %s=%d\n", g_pname, topo_node_name(node),
topo_node_instance(node));
} else {
nvlist_print(stdout, nvl);
nvlist_free(nvl);
}
}
return (TOPO_WALK_NEXT);
}
int
main(int argc, char *argv[])
{
topo_hdl_t *thp;
topo_walk_t *twp;
char *uuid;
int c, err;
g_pname = argv[0];
while (optind < argc) {
while ((c = getopt(argc, argv, "aCdeR:s:vV")) != -1) {
switch (c) {
case 'C':
atexit(abort);
break;
case 'd':
opt_d++;
break;
case 'e':
opt_e++;
break;
case 'v':
opt_v++;
break;
case 'V':
opt_V++;
break;
case 'R':
opt_R = optarg;
break;
case 's':
opt_s = optarg;
break;
default:
return (usage(stderr));
}
}
if (optind < argc) {
(void) fprintf(stderr, "%s: illegal argument -- %s\n",
g_pname, argv[optind]);
return (FMTOPO_EXIT_USAGE);
}
}
if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) {
(void) fprintf(stderr, "%s: failed to open topology tree: %s\n",
g_pname, topo_strerror(err));
return (FMTOPO_EXIT_ERROR);
}
if (opt_d)
topo_debug_set(thp, TOPO_DBG_ALL, "stderr");
if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
g_pname, topo_strerror(err));
topo_close(thp);
return (FMTOPO_EXIT_ERROR);
}
if ((twp = topo_walk_init(thp, opt_s, print_tnode, NULL, &err))
== NULL) {
(void) fprintf(stderr, "%s: failed to walk %s topology:"
" %s\n", g_pname, opt_s, topo_strerror(err));
topo_hdl_strfree(thp, uuid);
topo_snap_release(thp);
topo_close(thp);
return (err ? FMTOPO_EXIT_ERROR : FMTOPO_EXIT_SUCCESS);
}
if (!opt_e)
(void) printf("Topology Snapshot %s\n", uuid);
topo_hdl_strfree(thp, uuid);
if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
(void) fprintf(stderr, "%s: failed to walk topology\n",
g_pname);
topo_walk_fini(twp);
topo_snap_release(thp);
topo_close(thp);
return (FMTOPO_EXIT_ERROR);
}
if (opt_d)
(void) printf("--------------------\n");
topo_walk_fini(twp);
topo_snap_release(thp);
topo_close(thp);
return (FMTOPO_EXIT_SUCCESS);
}