Print this page
3373 gcc >= 4.5 concerns about offsetof()
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/fmadm/common/faulty.c
+++ new/usr/src/cmd/fm/fmadm/common/faulty.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <sys/types.h>
26 26 #include <fmadm.h>
27 27 #include <errno.h>
28 28 #include <limits.h>
29 29 #include <strings.h>
30 30 #include <stdio.h>
31 31 #include <unistd.h>
32 32 #include <sys/wait.h>
33 33 #include <sys/stat.h>
34 34 #include <fcntl.h>
35 35 #include <fm/fmd_log.h>
36 36 #include <sys/fm/protocol.h>
37 37 #include <fm/libtopo.h>
38 38 #include <fm/fmd_adm.h>
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
39 39 #include <fm/fmd_msg.h>
40 40 #include <dlfcn.h>
41 41 #include <sys/systeminfo.h>
42 42 #include <sys/utsname.h>
43 43 #include <libintl.h>
44 44 #include <locale.h>
45 45 #include <sys/smbios.h>
46 46 #include <libdevinfo.h>
47 47 #include <stdlib.h>
48 48
49 +#if defined(__GNUC__)
50 +#define offsetof(s, m) __builtin_offsetof(s, m)
51 +#else
49 52 #define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
53 +#endif
50 54
51 55 /*
52 56 * Fault records are added to catalog by calling add_fault_record_to_catalog()
53 57 * records are stored in order of importance to the system.
54 58 * If -g flag is set or not_suppressed is not set and the class fru, fault,
55 59 * type are the same then details are merged into an existing record, with uuid
56 60 * records are stored in time order.
57 61 * For each record information is extracted from nvlist and merged into linked
58 62 * list each is checked for identical records for which percentage certainty are
59 63 * added together.
60 64 * print_catalog() is called to print out catalog and release external resources
61 65 *
62 66 * /---------------\
63 67 * status_rec_list -> | | -|
64 68 * \---------------/
65 69 * \/
66 70 * /---------------\ /-------\ /-------\
67 71 * status_fru_list | status_record | -> | uurec | -> | uurec | -|
68 72 * \/ | | |- | | <- | |
69 73 * /-------------\ | | \-------/ \-------/
70 74 * | | -> | | \/ \/
71 75 * \-------------/ | | /-------\ /-------\
72 76 * \/ | | -> | asru | -> | asru |
73 77 * --- | | | | <- | |
74 78 * | | \-------/ \-------/
75 79 * status_asru_list | class |
76 80 * \/ | resource | /-------\ /-------\
77 81 * /-------------\ | fru | -> | list | -> | list |
78 82 * | | -> | serial | | | <- | |
79 83 * \-------------/ | | \-------/ \-------/
80 84 * \/ \---------------/
81 85 * --- \/ /\
82 86 * /---------------\
83 87 * | status_record |
84 88 * \---------------/
85 89 *
86 90 * Fmadm faulty takes a number of options which affect the format of the
87 91 * output displayed. By default, the display reports the FRU and ASRU along
88 92 * with other information on per-case basis as in the example below.
89 93 *
90 94 * --------------- ------------------------------------ -------------- -------
91 95 * TIME EVENT-ID MSG-ID SEVERITY
92 96 * --------------- ------------------------------------ -------------- -------
93 97 * Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c AMD-8000-2F Major
94 98 *
95 99 * Fault class : fault.memory.dimm_sb
96 100 * Affects : mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0
97 101 * faulted but still in service
98 102 * FRU : "CPU 0 DIMM 0" (hc://.../memory-controller=0/dimm=0)
99 103 * faulty
100 104 *
101 105 * Description : The number of errors associated with this memory module has
102 106 * exceeded acceptable levels. Refer to
103 107 * http://illumos.org/msg/AMD-8000-2F for more information.
104 108 *
105 109 * Response : Pages of memory associated with this memory module are being
106 110 * removed from service as errors are reported.
107 111 *
108 112 * Impact : Total system memory capacity will be reduced as pages are
109 113 * retired.
110 114 *
111 115 * Action : Schedule a repair procedure to replace the affected memory
112 116 * module. Use fmdump -v -u <EVENT_ID> to identify the module.
113 117 *
114 118 * The -v flag is similar, but adds some additonal information such as the
115 119 * resource. The -s flag is also similar but just gives the top line summary.
116 120 * All these options (ie without the -f or -r flags) use the print_catalog()
117 121 * function to do the display.
118 122 *
119 123 * The -f flag changes the output so that it appears sorted on a per-fru basis.
120 124 * The output is somewhat cut down compared to the default output. If -f is
121 125 * used, then print_fru() is used to print the output.
122 126 *
123 127 * -----------------------------------------------------------------------------
124 128 * "SLOT 2" (hc://.../hostbridge=3/pciexrc=3/pciexbus=4/pciexdev=0) faulty
125 129 * 5ca4aeb3-36...f6be-c2e8166dc484 2 suspects in this FRU total certainty 100%
126 130 *
127 131 * Description : A problem was detected for a PCI device.
128 132 * Refer to http://illumos.org/msg/PCI-8000-7J
129 133 * for more information.
130 134 *
131 135 * Response : One or more device instances may be disabled
132 136 *
133 137 * Impact : Possible loss of services provided by the device instances
134 138 * associated with this fault
135 139 *
136 140 * Action : Schedule a repair procedure to replace the affected device.
137 141 * Use fmdump -v -u <EVENT_ID> to identify the device or contact
138 142 * Sun for support.
139 143 *
140 144 * The -r flag changes the output so that it appears sorted on a per-asru basis.
141 145 * The output is very much cut down compared to the default output, just giving
142 146 * the asru fmri and state. Here print_asru() is used to print the output.
143 147 *
144 148 * mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 degraded
145 149 *
146 150 * For all fmadm faulty options, the sequence of events is
147 151 *
148 152 * 1) Walk through all the cases in the system using fmd_adm_case_iter() and
149 153 * for each case call dfault_rec(). This will call add_fault_record_to_catalog()
150 154 * This will extract the data from the nvlist and call catalog_new_record() to
151 155 * save the data away in various linked lists in the catalogue.
152 156 *
153 157 * 2) Once this is done, the data can be supplemented by using
154 158 * fmd_adm_rsrc_iter(). However this is now only necessary for the -i option.
155 159 *
156 160 * 3) Finally print_catalog(), print_fru() or print_asru() are called as
157 161 * appropriate to display the information from the catalogue sorted in the
158 162 * requested way.
159 163 *
160 164 */
161 165
162 166 typedef struct name_list {
163 167 struct name_list *next;
164 168 struct name_list *prev;
165 169 char *name;
166 170 uint8_t pct;
167 171 uint8_t max_pct;
168 172 ushort_t count;
169 173 int status;
170 174 char *label;
171 175 } name_list_t;
172 176
173 177 typedef struct ari_list {
174 178 char *ari_uuid;
175 179 struct ari_list *next;
176 180 } ari_list_t;
177 181
178 182 typedef struct uurec {
179 183 struct uurec *next;
180 184 struct uurec *prev;
181 185 char *uuid;
182 186 ari_list_t *ari_uuid_list;
183 187 name_list_t *asru;
184 188 uint64_t sec;
185 189 nvlist_t *event;
186 190 } uurec_t;
187 191
188 192 typedef struct uurec_select {
189 193 struct uurec_select *next;
190 194 char *uuid;
191 195 } uurec_select_t;
192 196
193 197 typedef struct host_id {
194 198 char *chassis;
195 199 char *server;
196 200 char *platform;
197 201 char *domain;
198 202 char *product_sn;
199 203 } hostid_t;
200 204
201 205 typedef struct host_id_list {
202 206 hostid_t hostid;
203 207 struct host_id_list *next;
204 208 } host_id_list_t;
205 209
206 210 typedef struct status_record {
207 211 hostid_t *host;
208 212 int nrecs;
209 213 uurec_t *uurec;
210 214 char *severity; /* in C locale */
211 215 char *msgid;
212 216 name_list_t *class;
213 217 name_list_t *resource;
214 218 name_list_t *asru;
215 219 name_list_t *fru;
216 220 name_list_t *serial;
217 221 uint8_t not_suppressed;
218 222 uint8_t injected;
219 223 } status_record_t;
220 224
221 225 typedef struct sr_list {
222 226 struct sr_list *next;
223 227 struct sr_list *prev;
224 228 struct status_record *status_record;
225 229 } sr_list_t;
226 230
227 231 typedef struct resource_list {
228 232 struct resource_list *next;
229 233 struct resource_list *prev;
230 234 sr_list_t *status_rec_list;
231 235 char *resource;
232 236 uint8_t not_suppressed;
233 237 uint8_t injected;
234 238 uint8_t max_pct;
235 239 } resource_list_t;
236 240
237 241 sr_list_t *status_rec_list;
238 242 resource_list_t *status_fru_list;
239 243 resource_list_t *status_asru_list;
240 244
241 245 static int max_display;
242 246 static int max_fault = 0;
243 247 static topo_hdl_t *topo_handle;
244 248 static host_id_list_t *host_list;
245 249 static int n_server;
246 250 static int opt_g;
247 251 static fmd_msg_hdl_t *fmadm_msghdl = NULL; /* handle for libfmd_msg calls */
248 252
249 253 static char *
250 254 format_date(char *buf, size_t len, uint64_t sec)
251 255 {
252 256 if (sec > LONG_MAX) {
253 257 (void) fprintf(stderr,
254 258 "record time is too large for 32-bit utility\n");
255 259 (void) snprintf(buf, len, "0x%llx", sec);
256 260 } else {
257 261 time_t tod = (time_t)sec;
258 262 time_t now = time(NULL);
259 263 if (tod > now+60 ||
260 264 tod < now - 6L*30L*24L*60L*60L) { /* 6 months ago */
261 265 (void) strftime(buf, len, "%b %d %Y ",
262 266 localtime(&tod));
263 267 } else {
264 268 (void) strftime(buf, len, "%b %d %T", localtime(&tod));
265 269 }
266 270 }
267 271
268 272 return (buf);
269 273 }
270 274
271 275 static hostid_t *
272 276 find_hostid_in_list(char *platform, char *chassis, char *server, char *domain,
273 277 char *product_sn)
274 278 {
275 279 hostid_t *rt = NULL;
276 280 host_id_list_t *hostp;
277 281
278 282 if (platform == NULL)
279 283 platform = "-";
280 284 if (server == NULL)
281 285 server = "-";
282 286 hostp = host_list;
283 287 while (hostp) {
284 288 if (hostp->hostid.platform &&
285 289 strcmp(hostp->hostid.platform, platform) == 0 &&
286 290 hostp->hostid.server &&
287 291 strcmp(hostp->hostid.server, server) == 0 &&
288 292 (chassis == NULL || hostp->hostid.chassis == NULL ||
289 293 strcmp(chassis, hostp->hostid.chassis) == 0) &&
290 294 (product_sn == NULL || hostp->hostid.product_sn == NULL ||
291 295 strcmp(product_sn, hostp->hostid.product_sn) == 0) &&
292 296 (domain == NULL || hostp->hostid.domain == NULL ||
293 297 strcmp(domain, hostp->hostid.domain) == 0)) {
294 298 rt = &hostp->hostid;
295 299 break;
296 300 }
297 301 hostp = hostp->next;
298 302 }
299 303 if (rt == NULL) {
300 304 hostp = malloc(sizeof (host_id_list_t));
301 305 hostp->hostid.platform = strdup(platform);
302 306 hostp->hostid.product_sn =
303 307 product_sn ? strdup(product_sn) : NULL;
304 308 hostp->hostid.server = strdup(server);
305 309 hostp->hostid.chassis = chassis ? strdup(chassis) : NULL;
306 310 hostp->hostid.domain = domain ? strdup(domain) : NULL;
307 311 hostp->next = host_list;
308 312 host_list = hostp;
309 313 rt = &hostp->hostid;
310 314 n_server++;
311 315 }
312 316 return (rt);
313 317 }
314 318
315 319 static hostid_t *
316 320 find_hostid(nvlist_t *nvl)
317 321 {
318 322 char *platform = NULL, *chassis = NULL, *server = NULL, *domain = NULL;
319 323 char *product_sn = NULL;
320 324 nvlist_t *auth, *fmri;
321 325 hostid_t *rt = NULL;
322 326
323 327 if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &fmri) == 0 &&
324 328 nvlist_lookup_nvlist(fmri, FM_FMRI_AUTHORITY, &auth) == 0) {
325 329 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
326 330 &platform);
327 331 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
328 332 &product_sn);
329 333 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server);
330 334 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS,
331 335 &chassis);
332 336 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_DOMAIN, &domain);
333 337 rt = find_hostid_in_list(platform, chassis, server,
334 338 domain, product_sn);
335 339 }
336 340 return (rt);
337 341 }
338 342
339 343 static char *
340 344 get_nvl2str_topo(nvlist_t *nvl)
341 345 {
342 346 char *name = NULL;
343 347 char *tname;
344 348 int err;
345 349 char *scheme = NULL;
346 350 char *mod_name = NULL;
347 351 char buf[128];
348 352
349 353 if (topo_handle == NULL)
350 354 topo_handle = topo_open(TOPO_VERSION, 0, &err);
351 355 if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) {
352 356 name = strdup(tname);
353 357 topo_hdl_strfree(topo_handle, tname);
354 358 } else {
355 359 (void) nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme);
356 360 (void) nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &mod_name);
357 361 if (scheme && strcmp(scheme, FM_FMRI_SCHEME_FMD) == 0 &&
358 362 mod_name) {
359 363 (void) snprintf(buf, sizeof (buf), "%s:///module/%s",
360 364 scheme, mod_name);
361 365 name = strdup(buf);
362 366 }
363 367 }
364 368 return (name);
365 369 }
366 370
367 371 static int
368 372 set_priority(char *s)
369 373 {
370 374 int rt = 0;
371 375
372 376 if (s) {
373 377 if (strcmp(s, "Minor") == 0)
374 378 rt = 1;
375 379 else if (strcmp(s, "Major") == 0)
376 380 rt = 10;
377 381 else if (strcmp(s, "Critical") == 0)
378 382 rt = 100;
379 383 }
380 384 return (rt);
381 385 }
382 386
383 387 static int
384 388 cmp_priority(char *s1, char *s2, uint64_t t1, uint64_t t2, uint8_t p1,
385 389 uint8_t p2)
386 390 {
387 391 int r1, r2;
388 392 int rt;
389 393
390 394 r1 = set_priority(s1);
391 395 r2 = set_priority(s2);
392 396 rt = r1 - r2;
393 397 if (rt == 0) {
394 398 if (t1 > t2)
395 399 rt = 1;
396 400 else if (t1 < t2)
397 401 rt = -1;
398 402 else
399 403 rt = p1 - p2;
400 404 }
401 405 return (rt);
402 406 }
403 407
404 408 /*
405 409 * merge two lists into one, by comparing enties in new and moving into list if
406 410 * name is not there or free off memory for names which are already there
407 411 * add_pct indicates if pct is the sum or highest pct
408 412 */
409 413 static name_list_t *
410 414 merge_name_list(name_list_t **list, name_list_t *new, int add_pct)
411 415 {
412 416 name_list_t *lp, *np, *sp, *rt = NULL;
413 417 int max_pct;
414 418
415 419 rt = *list;
416 420 np = new;
417 421 while (np) {
418 422 lp = *list;
419 423 while (lp) {
420 424 if (strcmp(lp->name, np->name) == 0)
421 425 break;
422 426 lp = lp->next;
423 427 if (lp == *list)
424 428 lp = NULL;
425 429 }
426 430 if (np->next == new)
427 431 sp = NULL;
428 432 else
429 433 sp = np->next;
430 434 if (lp) {
431 435 lp->status |= (np->status & FM_SUSPECT_FAULTY);
432 436 if (add_pct) {
433 437 lp->pct += np->pct;
434 438 lp->count += np->count;
435 439 } else if (np->pct > lp->pct) {
436 440 lp->pct = np->pct;
437 441 }
438 442 max_pct = np->max_pct;
439 443 if (np->label)
440 444 free(np->label);
441 445 free(np->name);
442 446 free(np);
443 447 np = NULL;
444 448 if (max_pct > lp->max_pct) {
445 449 lp->max_pct = max_pct;
446 450 if (lp->max_pct > lp->prev->max_pct &&
447 451 lp != *list) {
448 452 lp->prev->next = lp->next;
449 453 lp->next->prev = lp->prev;
450 454 np = lp;
451 455 }
452 456 }
453 457 }
454 458 if (np) {
455 459 lp = *list;
456 460 if (lp) {
457 461 if (np->max_pct > lp->max_pct) {
458 462 np->next = lp;
459 463 np->prev = lp->prev;
460 464 lp->prev->next = np;
461 465 lp->prev = np;
462 466 *list = np;
463 467 rt = np;
464 468 } else {
465 469 lp = lp->next;
466 470 while (lp != *list &&
467 471 np->max_pct < lp->max_pct) {
468 472 lp = lp->next;
469 473 }
470 474 np->next = lp;
471 475 np->prev = lp->prev;
472 476 lp->prev->next = np;
473 477 lp->prev = np;
474 478 }
475 479 } else {
476 480 *list = np;
477 481 np->next = np;
478 482 np->prev = np;
479 483 rt = np;
480 484 }
481 485 }
482 486 np = sp;
483 487 }
484 488 return (rt);
485 489 }
486 490
487 491 static name_list_t *
488 492 alloc_name_list(char *name, uint8_t pct)
489 493 {
490 494 name_list_t *nlp;
491 495
492 496 nlp = malloc(sizeof (*nlp));
493 497 nlp->name = strdup(name);
494 498 nlp->pct = pct;
495 499 nlp->max_pct = pct;
496 500 nlp->count = 1;
497 501 nlp->next = nlp;
498 502 nlp->prev = nlp;
499 503 nlp->status = 0;
500 504 nlp->label = NULL;
501 505 return (nlp);
502 506 }
503 507
504 508 static status_record_t *
505 509 new_record_init(uurec_t *uurec_p, char *msgid, name_list_t *class,
506 510 name_list_t *fru, name_list_t *asru, name_list_t *resource,
507 511 name_list_t *serial, boolean_t not_suppressed,
508 512 hostid_t *hostid, boolean_t injected)
509 513 {
510 514 status_record_t *status_rec_p;
511 515
512 516 status_rec_p = (status_record_t *)malloc(sizeof (status_record_t));
513 517 status_rec_p->nrecs = 1;
514 518 status_rec_p->host = hostid;
515 519 status_rec_p->uurec = uurec_p;
516 520 uurec_p->next = NULL;
517 521 uurec_p->prev = NULL;
518 522 uurec_p->asru = asru;
519 523 if ((status_rec_p->severity = fmd_msg_getitem_id(fmadm_msghdl, NULL,
520 524 msgid, FMD_MSG_ITEM_SEVERITY)) == NULL)
521 525 status_rec_p->severity = strdup("unknown");
522 526 status_rec_p->class = class;
523 527 status_rec_p->fru = fru;
524 528 status_rec_p->asru = asru;
525 529 status_rec_p->resource = resource;
526 530 status_rec_p->serial = serial;
527 531 status_rec_p->msgid = strdup(msgid);
528 532 status_rec_p->not_suppressed = not_suppressed;
529 533 status_rec_p->injected = injected;
530 534 return (status_rec_p);
531 535 }
532 536
533 537 /*
534 538 * add record to given list maintaining order higher priority first.
535 539 */
536 540 static void
537 541 add_rec_list(status_record_t *status_rec_p, sr_list_t **list_pp)
538 542 {
539 543 sr_list_t *tp, *np, *sp;
540 544 int order;
541 545 uint64_t sec;
542 546
543 547 np = malloc(sizeof (sr_list_t));
544 548 np->status_record = status_rec_p;
545 549 sec = status_rec_p->uurec->sec;
546 550 if ((sp = *list_pp) == NULL) {
547 551 *list_pp = np;
548 552 np->next = np;
549 553 np->prev = np;
550 554 } else {
551 555 /* insert new record in front of lower priority */
552 556 tp = sp;
553 557 order = cmp_priority(status_rec_p->severity,
554 558 sp->status_record->severity, sec,
555 559 tp->status_record->uurec->sec, 0, 0);
556 560 if (order > 0) {
557 561 *list_pp = np;
558 562 } else {
559 563 tp = sp->next;
560 564 while (tp != sp &&
561 565 cmp_priority(status_rec_p->severity,
562 566 tp->status_record->severity, sec,
563 567 tp->status_record->uurec->sec, 0, 0)) {
564 568 tp = tp->next;
565 569 }
566 570 }
567 571 np->next = tp;
568 572 np->prev = tp->prev;
569 573 tp->prev->next = np;
570 574 tp->prev = np;
571 575 }
572 576 }
573 577
574 578 static void
575 579 add_resource(status_record_t *status_rec_p, resource_list_t **rp,
576 580 resource_list_t *np)
577 581 {
578 582 int order;
579 583 uint64_t sec;
580 584 resource_list_t *sp, *tp;
581 585 status_record_t *srp;
582 586 char *severity = status_rec_p->severity;
583 587
584 588 add_rec_list(status_rec_p, &np->status_rec_list);
585 589 if ((sp = *rp) == NULL) {
586 590 np->next = np;
587 591 np->prev = np;
588 592 *rp = np;
589 593 } else {
590 594 /*
591 595 * insert new record in front of lower priority
592 596 */
593 597 tp = sp->next;
594 598 srp = sp->status_rec_list->status_record;
595 599 sec = status_rec_p->uurec->sec;
596 600 order = cmp_priority(severity, srp->severity, sec,
597 601 srp->uurec->sec, np->max_pct, sp->max_pct);
598 602 if (order > 0) {
599 603 *rp = np;
600 604 } else {
601 605 srp = tp->status_rec_list->status_record;
602 606 while (tp != sp &&
603 607 cmp_priority(severity, srp->severity, sec,
604 608 srp->uurec->sec, np->max_pct, sp->max_pct) < 0) {
605 609 tp = tp->next;
606 610 srp = tp->status_rec_list->status_record;
607 611 }
608 612 }
609 613 np->next = tp;
610 614 np->prev = tp->prev;
611 615 tp->prev->next = np;
612 616 tp->prev = np;
613 617 }
614 618 }
615 619
616 620 static void
617 621 add_resource_list(status_record_t *status_rec_p, name_list_t *fp,
618 622 resource_list_t **rpp)
619 623 {
620 624 int order;
621 625 resource_list_t *np, *end;
622 626 status_record_t *srp;
623 627
624 628 np = *rpp;
625 629 end = np;
626 630 while (np) {
627 631 if (strcmp(fp->name, np->resource) == 0) {
628 632 np->not_suppressed |= status_rec_p->not_suppressed;
629 633 np->injected |= status_rec_p->injected;
630 634 srp = np->status_rec_list->status_record;
631 635 order = cmp_priority(status_rec_p->severity,
632 636 srp->severity, status_rec_p->uurec->sec,
633 637 srp->uurec->sec, fp->max_pct, np->max_pct);
634 638 if (order > 0 && np != end) {
635 639 /*
636 640 * remove from list and add again using
637 641 * new priority
638 642 */
639 643 np->prev->next = np->next;
640 644 np->next->prev = np->prev;
641 645 add_resource(status_rec_p,
642 646 rpp, np);
643 647 } else {
644 648 add_rec_list(status_rec_p,
645 649 &np->status_rec_list);
646 650 }
647 651 break;
648 652 }
649 653 np = np->next;
650 654 if (np == end) {
651 655 np = NULL;
652 656 break;
653 657 }
654 658 }
655 659 if (np == NULL) {
656 660 np = malloc(sizeof (resource_list_t));
657 661 np->resource = fp->name;
658 662 np->not_suppressed = status_rec_p->not_suppressed;
659 663 np->injected = status_rec_p->injected;
660 664 np->status_rec_list = NULL;
661 665 np->max_pct = fp->max_pct;
662 666 add_resource(status_rec_p, rpp, np);
663 667 }
664 668 }
665 669
666 670 static void
667 671 add_list(status_record_t *status_rec_p, name_list_t *listp,
668 672 resource_list_t **glistp)
669 673 {
670 674 name_list_t *fp, *end;
671 675
672 676 fp = listp;
673 677 end = fp;
674 678 while (fp) {
675 679 add_resource_list(status_rec_p, fp, glistp);
676 680 fp = fp->next;
677 681 if (fp == end)
678 682 break;
679 683 }
680 684 }
681 685
682 686 /*
683 687 * add record to rec, fru and asru lists.
684 688 */
685 689 static void
686 690 catalog_new_record(uurec_t *uurec_p, char *msgid, name_list_t *class,
687 691 name_list_t *fru, name_list_t *asru, name_list_t *resource,
688 692 name_list_t *serial, boolean_t not_suppressed,
689 693 hostid_t *hostid, boolean_t injected, boolean_t dummy_fru)
690 694 {
691 695 status_record_t *status_rec_p;
692 696
693 697 status_rec_p = new_record_init(uurec_p, msgid, class, fru, asru,
694 698 resource, serial, not_suppressed, hostid, injected);
695 699 add_rec_list(status_rec_p, &status_rec_list);
696 700 if (status_rec_p->fru && !dummy_fru)
697 701 add_list(status_rec_p, status_rec_p->fru, &status_fru_list);
698 702 if (status_rec_p->asru)
699 703 add_list(status_rec_p, status_rec_p->asru, &status_asru_list);
700 704 }
701 705
702 706 static void
703 707 get_serial_no(nvlist_t *nvl, name_list_t **serial_p, uint8_t pct)
704 708 {
705 709 char *name;
706 710 char *serial = NULL;
707 711 char **lserial = NULL;
708 712 uint64_t serint;
709 713 name_list_t *nlp;
710 714 int j;
711 715 uint_t nelem;
712 716 char buf[64];
713 717
714 718 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) == 0) {
715 719 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
716 720 if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID,
717 721 &serint) == 0) {
718 722 (void) snprintf(buf, sizeof (buf), "%llX",
719 723 serint);
720 724 nlp = alloc_name_list(buf, pct);
721 725 (void) merge_name_list(serial_p, nlp, 1);
722 726 }
723 727 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
724 728 if (nvlist_lookup_string_array(nvl,
725 729 FM_FMRI_MEM_SERIAL_ID, &lserial, &nelem) == 0) {
726 730 nlp = alloc_name_list(lserial[0], pct);
727 731 for (j = 1; j < nelem; j++) {
728 732 name_list_t *n1lp;
729 733 n1lp = alloc_name_list(lserial[j], pct);
730 734 (void) merge_name_list(&nlp, n1lp, 1);
731 735 }
732 736 (void) merge_name_list(serial_p, nlp, 1);
733 737 }
734 738 } else if (strcmp(name, FM_FMRI_SCHEME_HC) == 0) {
735 739 if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID,
736 740 &serial) == 0) {
737 741 nlp = alloc_name_list(serial, pct);
738 742 (void) merge_name_list(serial_p, nlp, 1);
739 743 }
740 744 }
741 745 }
742 746 }
743 747
744 748 static void
745 749 extract_record_info(nvlist_t *nvl, name_list_t **class_p,
746 750 name_list_t **fru_p, name_list_t **serial_p, name_list_t **resource_p,
747 751 name_list_t **asru_p, boolean_t *dummy_fru, uint8_t status)
748 752 {
749 753 nvlist_t *lfru, *lasru, *rsrc;
750 754 name_list_t *nlp;
751 755 char *name;
752 756 uint8_t lpct = 0;
753 757 char *lclass = NULL;
754 758 char *label;
755 759
756 760 (void) nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &lpct);
757 761 if (nvlist_lookup_string(nvl, FM_CLASS, &lclass) == 0) {
758 762 nlp = alloc_name_list(lclass, lpct);
759 763 (void) merge_name_list(class_p, nlp, 1);
760 764 }
761 765 if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &lfru) == 0) {
762 766 name = get_nvl2str_topo(lfru);
763 767 if (name != NULL) {
764 768 nlp = alloc_name_list(name, lpct);
765 769 nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
766 770 FM_SUSPECT_DEGRADED);
767 771 free(name);
768 772 if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
769 773 &label) == 0)
770 774 nlp->label = strdup(label);
771 775 (void) merge_name_list(fru_p, nlp, 1);
772 776 }
773 777 get_serial_no(lfru, serial_p, lpct);
774 778 } else if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) != 0) {
775 779 /*
776 780 * No FRU or resource. But we want to display the repair status
777 781 * somehow, so create a dummy FRU field.
778 782 */
779 783 *dummy_fru = 1;
780 784 nlp = alloc_name_list(dgettext("FMD", "None"), lpct);
781 785 nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
782 786 FM_SUSPECT_DEGRADED);
783 787 (void) merge_name_list(fru_p, nlp, 1);
784 788 }
785 789 if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &lasru) == 0) {
786 790 name = get_nvl2str_topo(lasru);
787 791 if (name != NULL) {
788 792 nlp = alloc_name_list(name, lpct);
789 793 nlp->status = status & ~(FM_SUSPECT_NOT_PRESENT |
790 794 FM_SUSPECT_REPAIRED | FM_SUSPECT_REPLACED |
791 795 FM_SUSPECT_ACQUITTED);
792 796 free(name);
793 797 (void) merge_name_list(asru_p, nlp, 1);
794 798 }
795 799 get_serial_no(lasru, serial_p, lpct);
796 800 }
797 801 if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
798 802 name = get_nvl2str_topo(rsrc);
799 803 if (name != NULL) {
800 804 nlp = alloc_name_list(name, lpct);
801 805 nlp->status = status;
802 806 free(name);
803 807 if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
804 808 &label) == 0)
805 809 nlp->label = strdup(label);
806 810 (void) merge_name_list(resource_p, nlp, 1);
807 811 }
808 812 }
809 813 }
810 814
811 815 static void
812 816 add_fault_record_to_catalog(nvlist_t *nvl, uint64_t sec, char *uuid)
813 817 {
814 818 char *msgid = "-";
815 819 uint_t i, size = 0;
816 820 name_list_t *class = NULL, *resource = NULL;
817 821 name_list_t *asru = NULL, *fru = NULL, *serial = NULL;
818 822 nvlist_t **nva;
819 823 uint8_t *ba;
820 824 uurec_t *uurec_p;
821 825 hostid_t *host;
822 826 boolean_t not_suppressed = 1;
823 827 boolean_t any_present = 0;
824 828 boolean_t injected = 0;
825 829 boolean_t dummy_fru = 0;
826 830
827 831 (void) nvlist_lookup_string(nvl, FM_SUSPECT_DIAG_CODE, &msgid);
828 832 (void) nvlist_lookup_uint32(nvl, FM_SUSPECT_FAULT_SZ, &size);
829 833 (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE,
830 834 ¬_suppressed);
831 835 (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_INJECTED, &injected);
832 836
833 837 if (size != 0) {
834 838 (void) nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST,
835 839 &nva, &size);
836 840 (void) nvlist_lookup_uint8_array(nvl, FM_SUSPECT_FAULT_STATUS,
837 841 &ba, &size);
838 842 for (i = 0; i < size; i++) {
839 843 extract_record_info(nva[i], &class, &fru, &serial,
840 844 &resource, &asru, &dummy_fru, ba[i]);
841 845 if (!(ba[i] & FM_SUSPECT_NOT_PRESENT) &&
842 846 (ba[i] & FM_SUSPECT_FAULTY))
843 847 any_present = 1;
844 848 }
845 849 /*
846 850 * also suppress if no resources present
847 851 */
848 852 if (any_present == 0)
849 853 not_suppressed = 0;
850 854 }
851 855
852 856 uurec_p = (uurec_t *)malloc(sizeof (uurec_t));
853 857 uurec_p->uuid = strdup(uuid);
854 858 uurec_p->sec = sec;
855 859 uurec_p->ari_uuid_list = NULL;
856 860 uurec_p->event = NULL;
857 861 (void) nvlist_dup(nvl, &uurec_p->event, 0);
858 862 host = find_hostid(nvl);
859 863 catalog_new_record(uurec_p, msgid, class, fru, asru,
860 864 resource, serial, not_suppressed, host, injected, dummy_fru);
861 865 }
862 866
863 867 static void
864 868 update_asru_state_in_catalog(const char *uuid, const char *ari_uuid)
865 869 {
866 870 sr_list_t *srp;
867 871 uurec_t *uurp;
868 872 ari_list_t *ari_list;
869 873
870 874 srp = status_rec_list;
871 875 if (srp) {
872 876 for (;;) {
873 877 uurp = srp->status_record->uurec;
874 878 while (uurp) {
875 879 if (strcmp(uuid, uurp->uuid) == 0) {
876 880 ari_list = (ari_list_t *)
877 881 malloc(sizeof (ari_list_t));
878 882 ari_list->ari_uuid = strdup(ari_uuid);
879 883 ari_list->next = uurp->ari_uuid_list;
880 884 uurp->ari_uuid_list = ari_list;
881 885 return;
882 886 }
883 887 uurp = uurp->next;
884 888 }
885 889 if (srp->next == status_rec_list)
886 890 break;
887 891 srp = srp->next;
888 892 }
889 893 }
890 894 }
891 895
892 896 static void
893 897 print_line(char *label, char *buf)
894 898 {
895 899 char *cp, *ep, *wp;
896 900 char c;
897 901 int i;
898 902 int lsz;
899 903 char *padding;
900 904
901 905 lsz = strlen(label);
902 906 padding = malloc(lsz + 1);
903 907 for (i = 0; i < lsz; i++)
904 908 padding[i] = ' ';
905 909 padding[i] = 0;
906 910 cp = buf;
907 911 ep = buf;
908 912 c = *ep;
909 913 (void) printf("\n");
910 914 while (c) {
911 915 i = lsz;
912 916 wp = NULL;
913 917 while ((c = *ep) != NULL && (wp == NULL || i < 80)) {
914 918 if (c == ' ')
915 919 wp = ep;
916 920 else if (c == '\n') {
917 921 i = 0;
918 922 *ep = 0;
919 923 do {
920 924 ep++;
921 925 } while ((c = *ep) != NULL && c == ' ');
922 926 break;
923 927 }
924 928 ep++;
925 929 i++;
926 930 }
927 931 if (i >= 80 && wp) {
928 932 *wp = 0;
929 933 ep = wp + 1;
930 934 c = *ep;
931 935 }
932 936 (void) printf("%s%s\n", label, cp);
933 937 cp = ep;
934 938 label = padding;
935 939 }
936 940 free(padding);
937 941 }
938 942
939 943 static void
940 944 print_dict_info_line(nvlist_t *e, fmd_msg_item_t what, const char *linehdr)
941 945 {
942 946 char *cp = fmd_msg_getitem_nv(fmadm_msghdl, NULL, e, what);
943 947
944 948 if (cp) {
945 949 print_line(dgettext("FMD", linehdr), cp);
946 950 free(cp);
947 951 }
948 952 }
949 953
950 954 static void
951 955 print_dict_info(nvlist_t *nvl)
952 956 {
953 957 print_dict_info_line(nvl, FMD_MSG_ITEM_DESC, "Description : ");
954 958 print_dict_info_line(nvl, FMD_MSG_ITEM_RESPONSE, "Response : ");
955 959 print_dict_info_line(nvl, FMD_MSG_ITEM_IMPACT, "Impact : ");
956 960 print_dict_info_line(nvl, FMD_MSG_ITEM_ACTION, "Action : ");
957 961 }
958 962
959 963 static void
960 964 print_name(name_list_t *list, char *padding, int *np, int pct, int full)
961 965 {
962 966 char *name;
963 967
964 968 name = list->name;
965 969 if (list->label) {
966 970 (void) printf("%s \"%s\" (%s)", padding, list->label, name);
967 971 *np += 1;
968 972 } else {
969 973 (void) printf("%s %s", padding, name);
970 974 *np += 1;
971 975 }
972 976 if (list->pct && pct > 0 && pct < 100) {
973 977 if (list->count > 1) {
974 978 if (full) {
975 979 (void) printf(" %d @ %s %d%%\n", list->count,
976 980 dgettext("FMD", "max"),
977 981 list->max_pct);
978 982 } else {
979 983 (void) printf(" %s %d%%\n",
980 984 dgettext("FMD", "max"),
981 985 list->max_pct);
982 986 }
983 987 } else {
984 988 (void) printf(" %d%%\n", list->pct);
985 989 }
986 990 } else {
987 991 (void) printf("\n");
988 992 }
989 993 }
990 994
991 995 static void
992 996 print_asru_status(int status, char *label)
993 997 {
994 998 char *msg = NULL;
995 999
996 1000 switch (status) {
997 1001 case 0:
998 1002 msg = dgettext("FMD", "ok and in service");
999 1003 break;
1000 1004 case FM_SUSPECT_DEGRADED:
1001 1005 msg = dgettext("FMD", "service degraded, "
1002 1006 "but associated components no longer faulty");
1003 1007 break;
1004 1008 case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
1005 1009 msg = dgettext("FMD", "faulted but still "
1006 1010 "providing degraded service");
1007 1011 break;
1008 1012 case FM_SUSPECT_FAULTY:
1009 1013 msg = dgettext("FMD", "faulted but still in service");
1010 1014 break;
1011 1015 case FM_SUSPECT_UNUSABLE:
1012 1016 msg = dgettext("FMD", "out of service, "
1013 1017 "but associated components no longer faulty");
1014 1018 break;
1015 1019 case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
1016 1020 msg = dgettext("FMD", "faulted and taken out of service");
1017 1021 break;
1018 1022 default:
1019 1023 break;
1020 1024 }
1021 1025 if (msg) {
1022 1026 (void) printf("%s %s\n", label, msg);
1023 1027 }
1024 1028 }
1025 1029
1026 1030 static void
1027 1031 print_fru_status(int status, char *label)
1028 1032 {
1029 1033 char *msg = NULL;
1030 1034
1031 1035 if (status & FM_SUSPECT_NOT_PRESENT)
1032 1036 msg = dgettext("FMD", "not present");
1033 1037 else if (status & FM_SUSPECT_FAULTY)
1034 1038 msg = dgettext("FMD", "faulty");
1035 1039 else if (status & FM_SUSPECT_REPLACED)
1036 1040 msg = dgettext("FMD", "replaced");
1037 1041 else if (status & FM_SUSPECT_REPAIRED)
1038 1042 msg = dgettext("FMD", "repair attempted");
1039 1043 else if (status & FM_SUSPECT_ACQUITTED)
1040 1044 msg = dgettext("FMD", "acquitted");
1041 1045 else
1042 1046 msg = dgettext("FMD", "removed");
1043 1047 (void) printf("%s %s\n", label, msg);
1044 1048 }
1045 1049
1046 1050 static void
1047 1051 print_rsrc_status(int status, char *label)
1048 1052 {
1049 1053 char *msg = "";
1050 1054
1051 1055 if (status & FM_SUSPECT_NOT_PRESENT)
1052 1056 msg = dgettext("FMD", "not present");
1053 1057 else if (status & FM_SUSPECT_FAULTY) {
1054 1058 if (status & FM_SUSPECT_DEGRADED)
1055 1059 msg = dgettext("FMD",
1056 1060 "faulted but still providing degraded service");
1057 1061 else if (status & FM_SUSPECT_UNUSABLE)
1058 1062 msg = dgettext("FMD",
1059 1063 "faulted and taken out of service");
1060 1064 else
1061 1065 msg = dgettext("FMD", "faulted but still in service");
1062 1066 } else if (status & FM_SUSPECT_REPLACED)
1063 1067 msg = dgettext("FMD", "replaced");
1064 1068 else if (status & FM_SUSPECT_REPAIRED)
1065 1069 msg = dgettext("FMD", "repair attempted");
1066 1070 else if (status & FM_SUSPECT_ACQUITTED)
1067 1071 msg = dgettext("FMD", "acquitted");
1068 1072 else
1069 1073 msg = dgettext("FMD", "removed");
1070 1074 (void) printf("%s %s\n", label, msg);
1071 1075 }
1072 1076
1073 1077 static void
1074 1078 print_name_list(name_list_t *list, char *label,
1075 1079 int limit, int pct, void (func1)(int, char *), int full)
1076 1080 {
1077 1081 char *name;
1078 1082 char *padding;
1079 1083 int i, j, l, n;
1080 1084 name_list_t *end = list;
1081 1085
1082 1086 l = strlen(label);
1083 1087 padding = malloc(l + 1);
1084 1088 for (i = 0; i < l; i++)
1085 1089 padding[i] = ' ';
1086 1090 padding[l] = 0;
1087 1091 (void) printf("%s", label);
1088 1092 name = list->name;
1089 1093 if (list->label)
1090 1094 (void) printf(" \"%s\" (%s)", list->label, name);
1091 1095 else
1092 1096 (void) printf(" %s", name);
1093 1097 if (list->pct && pct > 0 && pct < 100) {
1094 1098 if (list->count > 1) {
1095 1099 if (full) {
1096 1100 (void) printf(" %d @ %s %d%%\n", list->count,
1097 1101 dgettext("FMD", "max"), list->max_pct);
1098 1102 } else {
1099 1103 (void) printf(" %s %d%%\n",
1100 1104 dgettext("FMD", "max"), list->max_pct);
1101 1105 }
1102 1106 } else {
1103 1107 (void) printf(" %d%%\n", list->pct);
1104 1108 }
1105 1109 } else {
1106 1110 (void) printf("\n");
1107 1111 }
1108 1112 if (func1)
1109 1113 func1(list->status, padding);
1110 1114 n = 1;
1111 1115 j = 0;
1112 1116 while ((list = list->next) != end) {
1113 1117 if (limit == 0 || n < limit) {
1114 1118 print_name(list, padding, &n, pct, full);
1115 1119 if (func1)
1116 1120 func1(list->status, padding);
1117 1121 } else
1118 1122 j++;
1119 1123 }
1120 1124 if (j == 1) {
1121 1125 print_name(list->prev, padding, &n, pct, full);
1122 1126 } else if (j > 1) {
1123 1127 (void) printf("%s... %d %s\n", padding, j,
1124 1128 dgettext("FMD", "more entries suppressed,"
1125 1129 " use -v option for full list"));
1126 1130 }
1127 1131 free(padding);
1128 1132 }
1129 1133
1130 1134 static int
1131 1135 asru_same_status(name_list_t *list)
1132 1136 {
1133 1137 name_list_t *end = list;
1134 1138 int status = list->status;
1135 1139
1136 1140 while ((list = list->next) != end) {
1137 1141 if (status == -1) {
1138 1142 status = list->status;
1139 1143 continue;
1140 1144 }
1141 1145 if (list->status != -1 && status != list->status) {
1142 1146 status = -1;
1143 1147 break;
1144 1148 }
1145 1149 }
1146 1150 return (status);
1147 1151 }
1148 1152
1149 1153 static int
1150 1154 serial_in_fru(name_list_t *fru, name_list_t *serial)
1151 1155 {
1152 1156 name_list_t *sp = serial;
1153 1157 name_list_t *fp;
1154 1158 int nserial = 0;
1155 1159 int found = 0;
1156 1160 char buf[128];
1157 1161
1158 1162 while (sp) {
1159 1163 fp = fru;
1160 1164 nserial++;
1161 1165 (void) snprintf(buf, sizeof (buf), "serial=%s", sp->name);
1162 1166 buf[sizeof (buf) - 1] = 0;
1163 1167 while (fp) {
1164 1168 if (strstr(fp->name, buf) != NULL) {
1165 1169 found++;
1166 1170 break;
1167 1171 }
1168 1172 fp = fp->next;
1169 1173 if (fp == fru)
1170 1174 break;
1171 1175 }
1172 1176 sp = sp->next;
1173 1177 if (sp == serial)
1174 1178 break;
1175 1179 }
1176 1180 return (found == nserial ? 1 : 0);
1177 1181 }
1178 1182
1179 1183 static void
1180 1184 print_sup_record(status_record_t *srp, int opt_i, int full)
1181 1185 {
1182 1186 char buf[32];
1183 1187 uurec_t *uurp = srp->uurec;
1184 1188 int n, j, k, max;
1185 1189 int status;
1186 1190 ari_list_t *ari_list;
1187 1191
1188 1192 n = 0;
1189 1193 max = max_fault;
1190 1194 if (max < 0) {
1191 1195 max = 0;
1192 1196 }
1193 1197 j = max / 2;
1194 1198 max -= j;
1195 1199 k = srp->nrecs - max;
1196 1200 while ((uurp = uurp->next) != NULL) {
1197 1201 if (full || n < j || n >= k || max_fault == 0 ||
1198 1202 srp->nrecs == max_fault+1) {
1199 1203 if (opt_i) {
1200 1204 ari_list = uurp->ari_uuid_list;
1201 1205 while (ari_list) {
1202 1206 (void) printf("%-15s %s\n",
1203 1207 format_date(buf, sizeof (buf),
1204 1208 uurp->sec), ari_list->ari_uuid);
1205 1209 ari_list = ari_list->next;
1206 1210 }
1207 1211 } else {
1208 1212 (void) printf("%-15s %s\n",
1209 1213 format_date(buf, sizeof (buf), uurp->sec),
1210 1214 uurp->uuid);
1211 1215 }
1212 1216 } else if (n == j)
1213 1217 (void) printf("... %d %s\n", srp->nrecs - max_fault,
1214 1218 dgettext("FMD", "more entries suppressed"));
1215 1219 n++;
1216 1220 }
1217 1221 (void) printf("\n");
1218 1222 (void) printf("%s %s", dgettext("FMD", "Host :"),
1219 1223 srp->host->server);
1220 1224 if (srp->host->domain)
1221 1225 (void) printf("\t%s %s", dgettext("FMD", "Domain :"),
1222 1226 srp->host->domain);
1223 1227 (void) printf("\n%s %s", dgettext("FMD", "Platform :"),
1224 1228 srp->host->platform);
1225 1229 (void) printf("\t%s %s", dgettext("FMD", "Chassis_id :"),
1226 1230 srp->host->chassis ? srp->host->chassis : "");
1227 1231 (void) printf("\n%s %s\n\n", dgettext("FMD", "Product_sn :"),
1228 1232 srp->host->product_sn? srp->host->product_sn : "");
1229 1233 if (srp->class)
1230 1234 print_name_list(srp->class,
1231 1235 dgettext("FMD", "Fault class :"), 0, srp->class->pct,
1232 1236 NULL, full);
1233 1237 if (srp->asru) {
1234 1238 status = asru_same_status(srp->asru);
1235 1239 if (status != -1) {
1236 1240 print_name_list(srp->asru,
1237 1241 dgettext("FMD", "Affects :"),
1238 1242 full ? 0 : max_display, 0, NULL, full);
1239 1243 print_asru_status(status, " ");
1240 1244 } else
1241 1245 print_name_list(srp->asru,
1242 1246 dgettext("FMD", "Affects :"),
1243 1247 full ? 0 : max_display, 0, print_asru_status, full);
1244 1248 }
1245 1249 if (full || srp->fru == NULL || srp->asru == NULL) {
1246 1250 if (srp->resource) {
1247 1251 status = asru_same_status(srp->resource);
1248 1252 if (status != -1) {
1249 1253 print_name_list(srp->resource,
1250 1254 dgettext("FMD", "Problem in :"),
1251 1255 full ? 0 : max_display, 0, NULL, full);
1252 1256 print_rsrc_status(status, " ");
1253 1257 } else
1254 1258 print_name_list(srp->resource,
1255 1259 dgettext("FMD", "Problem in :"),
1256 1260 full ? 0 : max_display, 0,
1257 1261 print_rsrc_status, full);
1258 1262 }
1259 1263 }
1260 1264 if (srp->fru) {
1261 1265 status = asru_same_status(srp->fru);
1262 1266 if (status != -1) {
1263 1267 print_name_list(srp->fru, dgettext("FMD",
1264 1268 "FRU :"), 0,
1265 1269 srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
1266 1270 NULL, full);
1267 1271 print_fru_status(status, " ");
1268 1272 } else
1269 1273 print_name_list(srp->fru, dgettext("FMD",
1270 1274 "FRU :"), 0,
1271 1275 srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
1272 1276 print_fru_status, full);
1273 1277 }
1274 1278 if (srp->serial && !serial_in_fru(srp->fru, srp->serial) &&
1275 1279 !serial_in_fru(srp->asru, srp->serial)) {
1276 1280 print_name_list(srp->serial, dgettext("FMD", "Serial ID. :"),
1277 1281 0, 0, NULL, full);
1278 1282 }
1279 1283 print_dict_info(srp->uurec->event);
1280 1284 (void) printf("\n");
1281 1285 }
1282 1286
1283 1287 static void
1284 1288 print_status_record(status_record_t *srp, int summary, int opt_i, int full)
1285 1289 {
1286 1290 char buf[32];
1287 1291 uurec_t *uurp = srp->uurec;
1288 1292 static int header = 0;
1289 1293 char *head;
1290 1294 ari_list_t *ari_list;
1291 1295
1292 1296 if (!summary || !header) {
1293 1297 if (opt_i) {
1294 1298 head = "--------------- "
1295 1299 "------------------------------------ "
1296 1300 "-------------- ---------\n"
1297 1301 "TIME CACHE-ID"
1298 1302 " MSG-ID"
1299 1303 " SEVERITY\n--------------- "
1300 1304 "------------------------------------ "
1301 1305 " -------------- ---------";
1302 1306 } else {
1303 1307 head = "--------------- "
1304 1308 "------------------------------------ "
1305 1309 "-------------- ---------\n"
1306 1310 "TIME EVENT-ID"
1307 1311 " MSG-ID"
1308 1312 " SEVERITY\n--------------- "
1309 1313 "------------------------------------ "
1310 1314 " -------------- ---------";
1311 1315 }
1312 1316 (void) printf("%s\n", dgettext("FMD", head));
1313 1317 header = 1;
1314 1318 }
1315 1319 if (opt_i) {
1316 1320 ari_list = uurp->ari_uuid_list;
1317 1321 while (ari_list) {
1318 1322 (void) printf("%-15s %-37s %-14s %-9s %s\n",
1319 1323 format_date(buf, sizeof (buf), uurp->sec),
1320 1324 ari_list->ari_uuid, srp->msgid, srp->severity,
1321 1325 srp->injected ? dgettext("FMD", "injected") : "");
1322 1326 ari_list = ari_list->next;
1323 1327 }
1324 1328 } else {
1325 1329 (void) printf("%-15s %-37s %-14s %-9s %s\n",
1326 1330 format_date(buf, sizeof (buf), uurp->sec),
1327 1331 uurp->uuid, srp->msgid, srp->severity,
1328 1332 srp->injected ? dgettext("FMD", "injected") : "");
1329 1333 }
1330 1334
1331 1335 if (!summary)
1332 1336 print_sup_record(srp, opt_i, full);
1333 1337 }
1334 1338
1335 1339 static void
1336 1340 print_catalog(int summary, int opt_a, int full, int opt_i, int page_feed)
1337 1341 {
1338 1342 status_record_t *srp;
1339 1343 sr_list_t *slp;
1340 1344
1341 1345 slp = status_rec_list;
1342 1346 if (slp) {
1343 1347 for (;;) {
1344 1348 srp = slp->status_record;
1345 1349 if (opt_a || srp->not_suppressed) {
1346 1350 if (page_feed)
1347 1351 (void) printf("\f\n");
1348 1352 print_status_record(srp, summary, opt_i, full);
1349 1353 }
1350 1354 if (slp->next == status_rec_list)
1351 1355 break;
1352 1356 slp = slp->next;
1353 1357 }
1354 1358 }
1355 1359 }
1356 1360
1357 1361 static name_list_t *
1358 1362 find_fru(status_record_t *srp, char *resource)
1359 1363 {
1360 1364 name_list_t *rt = NULL;
1361 1365 name_list_t *fru = srp->fru;
1362 1366
1363 1367 while (fru) {
1364 1368 if (strcmp(resource, fru->name) == 0) {
1365 1369 rt = fru;
1366 1370 break;
1367 1371 }
1368 1372 fru = fru->next;
1369 1373 if (fru == srp->fru)
1370 1374 break;
1371 1375 }
1372 1376 return (rt);
1373 1377 }
1374 1378
1375 1379 static void
1376 1380 print_fru_line(name_list_t *fru, char *uuid)
1377 1381 {
1378 1382 if (fru->pct == 100) {
1379 1383 (void) printf("%s %d %s %d%%\n", uuid, fru->count,
1380 1384 dgettext("FMD", "suspects in this FRU total certainty"),
1381 1385 100);
1382 1386 } else {
1383 1387 (void) printf("%s %d %s %d%%\n", uuid, fru->count,
1384 1388 dgettext("FMD", "suspects in this FRU max certainty"),
1385 1389 fru->max_pct);
1386 1390 }
1387 1391 }
1388 1392
1389 1393 static void
1390 1394 print_fru(int summary, int opt_a, int opt_i, int page_feed)
1391 1395 {
1392 1396 resource_list_t *tp = status_fru_list;
1393 1397 status_record_t *srp;
1394 1398 sr_list_t *slp, *end;
1395 1399 uurec_t *uurp;
1396 1400 name_list_t *fru;
1397 1401 int status;
1398 1402 ari_list_t *ari_list;
1399 1403
1400 1404 while (tp) {
1401 1405 if (opt_a || tp->not_suppressed) {
1402 1406 if (page_feed)
1403 1407 (void) printf("\f\n");
1404 1408 if (!summary)
1405 1409 (void) printf("-----------------------------"
1406 1410 "---------------------------------------"
1407 1411 "----------\n");
1408 1412 slp = tp->status_rec_list;
1409 1413 end = slp;
1410 1414 do {
1411 1415 srp = slp->status_record;
1412 1416 if (!srp->not_suppressed) {
1413 1417 slp = slp->next;
1414 1418 continue;
1415 1419 }
1416 1420 fru = find_fru(srp, tp->resource);
1417 1421 if (fru) {
1418 1422 if (fru->label)
1419 1423 (void) printf("\"%s\" (%s) ",
1420 1424 fru->label, fru->name);
1421 1425 else
1422 1426 (void) printf("%s ",
1423 1427 fru->name);
1424 1428 break;
1425 1429 }
1426 1430 slp = slp->next;
1427 1431 } while (slp != end);
1428 1432
1429 1433 slp = tp->status_rec_list;
1430 1434 end = slp;
1431 1435 status = 0;
1432 1436 do {
1433 1437 srp = slp->status_record;
1434 1438 if (!srp->not_suppressed) {
1435 1439 slp = slp->next;
1436 1440 continue;
1437 1441 }
1438 1442 fru = srp->fru;
1439 1443 while (fru) {
1440 1444 if (strcmp(tp->resource,
1441 1445 fru->name) == 0)
1442 1446 status |= fru->status;
1443 1447 fru = fru->next;
1444 1448 if (fru == srp->fru)
1445 1449 break;
1446 1450 }
1447 1451 slp = slp->next;
1448 1452 } while (slp != end);
1449 1453 if (status & FM_SUSPECT_NOT_PRESENT)
1450 1454 (void) printf(dgettext("FMD", "not present"));
1451 1455 else if (status & FM_SUSPECT_FAULTY)
1452 1456 (void) printf(dgettext("FMD", "faulty"));
1453 1457 else if (status & FM_SUSPECT_REPLACED)
1454 1458 (void) printf(dgettext("FMD", "replaced"));
1455 1459 else if (status & FM_SUSPECT_REPAIRED)
1456 1460 (void) printf(dgettext("FMD",
1457 1461 "repair attempted"));
1458 1462 else if (status & FM_SUSPECT_ACQUITTED)
1459 1463 (void) printf(dgettext("FMD", "acquitted"));
1460 1464 else
1461 1465 (void) printf(dgettext("FMD", "removed"));
1462 1466
1463 1467 if (tp->injected)
1464 1468 (void) printf(dgettext("FMD", " injected\n"));
1465 1469 else
1466 1470 (void) printf(dgettext("FMD", "\n"));
1467 1471
1468 1472 slp = tp->status_rec_list;
1469 1473 end = slp;
1470 1474 do {
1471 1475 srp = slp->status_record;
1472 1476 if (!srp->not_suppressed) {
1473 1477 slp = slp->next;
1474 1478 continue;
1475 1479 }
1476 1480 uurp = srp->uurec;
1477 1481 fru = find_fru(srp, tp->resource);
1478 1482 if (fru) {
1479 1483 if (opt_i) {
1480 1484 ari_list = uurp->ari_uuid_list;
1481 1485 while (ari_list) {
1482 1486 print_fru_line(fru,
1483 1487 ari_list->ari_uuid);
1484 1488 ari_list =
1485 1489 ari_list->next;
1486 1490 }
1487 1491 } else {
1488 1492 print_fru_line(fru, uurp->uuid);
1489 1493 }
1490 1494 }
1491 1495 slp = slp->next;
1492 1496 } while (slp != end);
1493 1497 if (!summary) {
1494 1498 slp = tp->status_rec_list;
1495 1499 end = slp;
1496 1500 do {
1497 1501 srp = slp->status_record;
1498 1502 if (!srp->not_suppressed) {
1499 1503 slp = slp->next;
1500 1504 continue;
1501 1505 }
1502 1506 if (srp->serial &&
1503 1507 !serial_in_fru(srp->fru,
1504 1508 srp->serial)) {
1505 1509 print_name_list(srp->serial,
1506 1510 dgettext("FMD",
1507 1511 "Serial ID. :"),
1508 1512 0, 0, NULL, 1);
1509 1513 break;
1510 1514 }
1511 1515 slp = slp->next;
1512 1516 } while (slp != end);
1513 1517 }
1514 1518 }
1515 1519 tp = tp->next;
1516 1520 if (tp == status_fru_list)
1517 1521 break;
1518 1522 }
1519 1523 }
1520 1524
1521 1525 static void
1522 1526 print_asru(int opt_a)
1523 1527 {
1524 1528 resource_list_t *tp = status_asru_list;
1525 1529 status_record_t *srp;
1526 1530 sr_list_t *slp, *end;
1527 1531 char *msg;
1528 1532 int status;
1529 1533 name_list_t *asru;
1530 1534
1531 1535 while (tp) {
1532 1536 if (opt_a || tp->not_suppressed) {
1533 1537 status = 0;
1534 1538 slp = tp->status_rec_list;
1535 1539 end = slp;
1536 1540 do {
1537 1541 srp = slp->status_record;
1538 1542 if (!srp->not_suppressed) {
1539 1543 slp = slp->next;
1540 1544 continue;
1541 1545 }
1542 1546 asru = srp->asru;
1543 1547 while (asru) {
1544 1548 if (strcmp(tp->resource,
1545 1549 asru->name) == 0)
1546 1550 status |= asru->status;
1547 1551 asru = asru->next;
1548 1552 if (asru == srp->asru)
1549 1553 break;
1550 1554 }
1551 1555 slp = slp->next;
1552 1556 } while (slp != end);
1553 1557 switch (status) {
1554 1558 case 0:
1555 1559 msg = dgettext("FMD", "ok");
1556 1560 break;
1557 1561 case FM_SUSPECT_DEGRADED:
1558 1562 msg = dgettext("FMD", "degraded");
1559 1563 break;
1560 1564 case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
1561 1565 msg = dgettext("FMD", "degraded");
1562 1566 break;
1563 1567 case FM_SUSPECT_FAULTY:
1564 1568 msg = dgettext("FMD", "degraded");
1565 1569 break;
1566 1570 case FM_SUSPECT_UNUSABLE:
1567 1571 msg = dgettext("FMD", "unknown");
1568 1572 break;
1569 1573 case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
1570 1574 msg = dgettext("FMD", "faulted");
1571 1575 break;
1572 1576 default:
1573 1577 msg = "";
1574 1578 break;
1575 1579 }
1576 1580 (void) printf("%-69s %s", tp->resource, msg);
1577 1581 if (tp->injected)
1578 1582 (void) printf(dgettext("FMD", " injected\n"));
1579 1583 else
1580 1584 (void) printf(dgettext("FMD", "\n"));
1581 1585 }
1582 1586 tp = tp->next;
1583 1587 if (tp == status_asru_list)
1584 1588 break;
1585 1589 }
1586 1590 }
1587 1591
1588 1592 static int
1589 1593 uuid_in_list(char *uuid, uurec_select_t *uurecp)
1590 1594 {
1591 1595 while (uurecp) {
1592 1596 if (strcmp(uuid, uurecp->uuid) == 0)
1593 1597 return (1);
1594 1598 uurecp = uurecp->next;
1595 1599 }
1596 1600 return (0);
1597 1601 }
1598 1602
1599 1603 static int
1600 1604 dfault_rec(const fmd_adm_caseinfo_t *acp, void *arg)
1601 1605 {
1602 1606 int64_t *diag_time;
1603 1607 uint_t nelem;
1604 1608 int rt = 0;
1605 1609 char *uuid = "-";
1606 1610 uurec_select_t *uurecp = (uurec_select_t *)arg;
1607 1611
1608 1612 if (nvlist_lookup_int64_array(acp->aci_event, FM_SUSPECT_DIAG_TIME,
1609 1613 &diag_time, &nelem) == 0 && nelem >= 2) {
1610 1614 (void) nvlist_lookup_string(acp->aci_event, FM_SUSPECT_UUID,
1611 1615 &uuid);
1612 1616 if (uurecp == NULL || uuid_in_list(uuid, uurecp))
1613 1617 add_fault_record_to_catalog(acp->aci_event, *diag_time,
1614 1618 uuid);
1615 1619 } else {
1616 1620 rt = -1;
1617 1621 }
1618 1622 return (rt);
1619 1623 }
1620 1624
1621 1625 /*ARGSUSED*/
1622 1626 static int
1623 1627 dstatus_rec(const fmd_adm_rsrcinfo_t *ari, void *unused)
1624 1628 {
1625 1629 update_asru_state_in_catalog(ari->ari_case, ari->ari_uuid);
1626 1630 return (0);
1627 1631 }
1628 1632
1629 1633 static int
1630 1634 get_cases_from_fmd(fmd_adm_t *adm, uurec_select_t *uurecp, int opt_i)
1631 1635 {
1632 1636 int rt = FMADM_EXIT_SUCCESS;
1633 1637
1634 1638 /*
1635 1639 * These calls may fail with Protocol error if message payload is
1636 1640 * too big
1637 1641 */
1638 1642 if (fmd_adm_case_iter(adm, NULL, dfault_rec, uurecp) != 0)
1639 1643 die("failed to get case list from fmd");
1640 1644 if (opt_i && fmd_adm_rsrc_iter(adm, 1, dstatus_rec, NULL) != 0)
1641 1645 die("failed to get case status from fmd");
1642 1646 return (rt);
1643 1647 }
1644 1648
1645 1649 /*
1646 1650 * fmadm faulty command
1647 1651 *
1648 1652 * -a show hidden fault records
1649 1653 * -f show faulty fru's
1650 1654 * -g force grouping of similar faults on the same fru
1651 1655 * -n number of fault records to display
1652 1656 * -p pipe output through pager
1653 1657 * -r show faulty asru's
1654 1658 * -s print summary of first fault
1655 1659 * -u print listed uuid's only
1656 1660 * -v full output
1657 1661 */
1658 1662
1659 1663 int
1660 1664 cmd_faulty(fmd_adm_t *adm, int argc, char *argv[])
1661 1665 {
1662 1666 int opt_a = 0, opt_v = 0, opt_p = 0, opt_s = 0, opt_r = 0, opt_f = 0;
1663 1667 int opt_i = 0;
1664 1668 char *pager;
1665 1669 FILE *fp;
1666 1670 int rt, c, stat;
1667 1671 uurec_select_t *tp;
1668 1672 uurec_select_t *uurecp = NULL;
1669 1673
1670 1674 while ((c = getopt(argc, argv, "afgin:prsu:v")) != EOF) {
1671 1675 switch (c) {
1672 1676 case 'a':
1673 1677 opt_a++;
1674 1678 break;
1675 1679 case 'f':
1676 1680 opt_f++;
1677 1681 break;
1678 1682 case 'g':
1679 1683 opt_g++;
1680 1684 break;
1681 1685 case 'i':
1682 1686 opt_i++;
1683 1687 break;
1684 1688 case 'n':
1685 1689 max_fault = atoi(optarg);
1686 1690 break;
1687 1691 case 'p':
1688 1692 opt_p++;
1689 1693 break;
1690 1694 case 'r':
1691 1695 opt_r++;
1692 1696 break;
1693 1697 case 's':
1694 1698 opt_s++;
1695 1699 break;
1696 1700 case 'u':
1697 1701 tp = (uurec_select_t *)malloc(sizeof (uurec_select_t));
1698 1702 tp->uuid = optarg;
1699 1703 tp->next = uurecp;
1700 1704 uurecp = tp;
1701 1705 opt_a = 1;
1702 1706 break;
1703 1707 case 'v':
1704 1708 opt_v++;
1705 1709 break;
1706 1710 default:
1707 1711 return (FMADM_EXIT_USAGE);
1708 1712 }
1709 1713 }
1710 1714 if (optind < argc)
1711 1715 return (FMADM_EXIT_USAGE);
1712 1716
1713 1717 if ((fmadm_msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) == NULL)
1714 1718 return (FMADM_EXIT_ERROR);
1715 1719 rt = get_cases_from_fmd(adm, uurecp, opt_i);
1716 1720 if (opt_p) {
1717 1721 if ((pager = getenv("PAGER")) == NULL)
1718 1722 pager = "/usr/bin/more";
1719 1723 fp = popen(pager, "w");
1720 1724 if (fp == NULL) {
1721 1725 rt = FMADM_EXIT_ERROR;
1722 1726 opt_p = 0;
1723 1727 } else {
1724 1728 (void) dup2(fileno(fp), 1);
1725 1729 setbuf(stdout, NULL);
1726 1730 (void) fclose(fp);
1727 1731 }
1728 1732 }
1729 1733 max_display = max_fault;
1730 1734 if (opt_f)
1731 1735 print_fru(opt_s, opt_a, opt_i, opt_p && !opt_s);
1732 1736 if (opt_r)
1733 1737 print_asru(opt_a);
1734 1738 if (opt_f == 0 && opt_r == 0)
1735 1739 print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s);
1736 1740 fmd_msg_fini(fmadm_msghdl);
1737 1741 if (topo_handle)
1738 1742 topo_close(topo_handle);
1739 1743 if (opt_p) {
1740 1744 (void) fclose(stdout);
1741 1745 (void) wait(&stat);
1742 1746 }
1743 1747 return (rt);
1744 1748 }
1745 1749
1746 1750 int
1747 1751 cmd_flush(fmd_adm_t *adm, int argc, char *argv[])
1748 1752 {
1749 1753 int i, status = FMADM_EXIT_SUCCESS;
1750 1754
1751 1755 if (argc < 2 || (i = getopt(argc, argv, "")) != EOF)
1752 1756 return (FMADM_EXIT_USAGE);
1753 1757
1754 1758 for (i = 1; i < argc; i++) {
1755 1759 if (fmd_adm_rsrc_flush(adm, argv[i]) != 0) {
1756 1760 warn("failed to flush %s", argv[i]);
1757 1761 status = FMADM_EXIT_ERROR;
1758 1762 } else
1759 1763 note("flushed resource history for %s\n", argv[i]);
1760 1764 }
1761 1765
1762 1766 return (status);
1763 1767 }
1764 1768
1765 1769 int
1766 1770 cmd_repair(fmd_adm_t *adm, int argc, char *argv[])
1767 1771 {
1768 1772 int err;
1769 1773
1770 1774 if (getopt(argc, argv, "") != EOF)
1771 1775 return (FMADM_EXIT_USAGE);
1772 1776
1773 1777 if (argc - optind != 1)
1774 1778 return (FMADM_EXIT_USAGE);
1775 1779
1776 1780 /*
1777 1781 * argument could be a uuid, an fmri (asru, fru or resource)
1778 1782 * or a label. Try uuid first, If that fails try the others.
1779 1783 */
1780 1784 err = fmd_adm_case_repair(adm, argv[optind]);
1781 1785 if (err != 0)
1782 1786 err = fmd_adm_rsrc_repaired(adm, argv[optind]);
1783 1787
1784 1788 if (err != 0)
1785 1789 die("failed to record repair to %s", argv[optind]);
1786 1790
1787 1791 note("recorded repair to %s\n", argv[optind]);
1788 1792 return (FMADM_EXIT_SUCCESS);
1789 1793 }
1790 1794
1791 1795 int
1792 1796 cmd_repaired(fmd_adm_t *adm, int argc, char *argv[])
1793 1797 {
1794 1798 int err;
1795 1799
1796 1800 if (getopt(argc, argv, "") != EOF)
1797 1801 return (FMADM_EXIT_USAGE);
1798 1802
1799 1803 if (argc - optind != 1)
1800 1804 return (FMADM_EXIT_USAGE);
1801 1805
1802 1806 /*
1803 1807 * argument could be an fmri (asru, fru or resource) or a label.
1804 1808 */
1805 1809 err = fmd_adm_rsrc_repaired(adm, argv[optind]);
1806 1810 if (err != 0)
1807 1811 die("failed to record repair to %s", argv[optind]);
1808 1812
1809 1813 note("recorded repair to of %s\n", argv[optind]);
1810 1814 return (FMADM_EXIT_SUCCESS);
1811 1815 }
1812 1816
1813 1817 int
1814 1818 cmd_replaced(fmd_adm_t *adm, int argc, char *argv[])
1815 1819 {
1816 1820 int err;
1817 1821
1818 1822 if (getopt(argc, argv, "") != EOF)
1819 1823 return (FMADM_EXIT_USAGE);
1820 1824
1821 1825 if (argc - optind != 1)
1822 1826 return (FMADM_EXIT_USAGE);
1823 1827
1824 1828 /*
1825 1829 * argument could be an fmri (asru, fru or resource) or a label.
1826 1830 */
1827 1831 err = fmd_adm_rsrc_replaced(adm, argv[optind]);
1828 1832 if (err != 0)
1829 1833 die("failed to record replacement of %s", argv[optind]);
1830 1834
1831 1835 note("recorded replacement of %s\n", argv[optind]);
1832 1836 return (FMADM_EXIT_SUCCESS);
1833 1837 }
1834 1838
1835 1839 int
1836 1840 cmd_acquit(fmd_adm_t *adm, int argc, char *argv[])
1837 1841 {
1838 1842 int err;
1839 1843
1840 1844 if (getopt(argc, argv, "") != EOF)
1841 1845 return (FMADM_EXIT_USAGE);
1842 1846
1843 1847 if (argc - optind != 1 && argc - optind != 2)
1844 1848 return (FMADM_EXIT_USAGE);
1845 1849
1846 1850 /*
1847 1851 * argument could be a uuid, an fmri (asru, fru or resource)
1848 1852 * or a label. Or it could be a uuid and an fmri or label.
1849 1853 */
1850 1854 if (argc - optind == 2) {
1851 1855 err = fmd_adm_rsrc_acquit(adm, argv[optind], argv[optind + 1]);
1852 1856 if (err != 0)
1853 1857 err = fmd_adm_rsrc_acquit(adm, argv[optind + 1],
1854 1858 argv[optind]);
1855 1859 } else {
1856 1860 err = fmd_adm_case_acquit(adm, argv[optind]);
1857 1861 if (err != 0)
1858 1862 err = fmd_adm_rsrc_acquit(adm, argv[optind], "");
1859 1863 }
1860 1864
1861 1865 if (err != 0)
1862 1866 die("failed to record acquital of %s", argv[optind]);
1863 1867
1864 1868 note("recorded acquital of %s\n", argv[optind]);
1865 1869 return (FMADM_EXIT_SUCCESS);
1866 1870 }
↓ open down ↓ |
1807 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX