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