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