xref: /illumos-gate/usr/src/cmd/fm/fmdump/common/fault.c (revision 24fe0b3bf671e123467ce1df0b67cadd3614c8e4)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <fmdump.h>
27 #include <stdio.h>
28 #include <strings.h>
29 
30 /*ARGSUSED*/
31 static int
32 flt_short(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
33 {
34 	char buf[32], str[32];
35 	char *class = NULL, *uuid = "-", *code = "-";
36 
37 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
38 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
39 
40 	(void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
41 	if (class != NULL && strcmp(class, FM_LIST_REPAIRED_CLASS) == 0) {
42 		(void) snprintf(str, sizeof (str), "%s %s", code, "Repaired");
43 		code = str;
44 	}
45 	if (class != NULL && strcmp(class, FM_LIST_RESOLVED_CLASS) == 0) {
46 		(void) snprintf(str, sizeof (str), "%s %s", code, "Resolved");
47 		code = str;
48 	}
49 
50 	if (class != NULL && strcmp(class, FM_LIST_UPDATED_CLASS) == 0) {
51 		(void) snprintf(str, sizeof (str), "%s %s", code, "Updated");
52 		code = str;
53 	}
54 
55 	fmdump_printf(fp, "%-20s %-32s %s\n",
56 	    fmdump_date(buf, sizeof (buf), rp), uuid, code);
57 
58 	return (0);
59 }
60 
61 static int
62 flt_verb1(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
63 {
64 	uint_t i, size = 0;
65 	nvlist_t **nva;
66 	uint8_t *ba;
67 
68 	(void) flt_short(lp, rp, fp);
69 	(void) nvlist_lookup_uint32(rp->rec_nvl, FM_SUSPECT_FAULT_SZ, &size);
70 
71 	if (size != 0) {
72 		(void) nvlist_lookup_nvlist_array(rp->rec_nvl,
73 		    FM_SUSPECT_FAULT_LIST, &nva, &size);
74 		(void) nvlist_lookup_uint8_array(rp->rec_nvl,
75 		    FM_SUSPECT_FAULT_STATUS, &ba, &size);
76 	}
77 
78 	for (i = 0; i < size; i++) {
79 		char *class = NULL, *rname = NULL, *aname = NULL, *fname = NULL;
80 		char *loc = NULL;
81 		nvlist_t *fru, *asru, *rsrc;
82 		uint8_t pct = 0;
83 
84 		(void) nvlist_lookup_uint8(nva[i], FM_FAULT_CERTAINTY, &pct);
85 		(void) nvlist_lookup_string(nva[i], FM_CLASS, &class);
86 
87 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_FRU, &fru) == 0)
88 			fname = fmdump_nvl2str(fru);
89 
90 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_ASRU, &asru) == 0)
91 			aname = fmdump_nvl2str(asru);
92 
93 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_RESOURCE, &rsrc) == 0)
94 			rname = fmdump_nvl2str(rsrc);
95 
96 		if (nvlist_lookup_string(nva[i], FM_FAULT_LOCATION, &loc)
97 		    == 0) {
98 			if (fname && strncmp(fname, FM_FMRI_LEGACY_HC_PREFIX,
99 			    sizeof (FM_FMRI_LEGACY_HC_PREFIX)) == 0)
100 				loc = fname + sizeof (FM_FMRI_LEGACY_HC_PREFIX);
101 		}
102 
103 
104 		fmdump_printf(fp, "  %3u%%  %s",
105 		    pct, class ? class : "-");
106 
107 		if (ba[i] & FM_SUSPECT_FAULTY)
108 			fmdump_printf(fp, "\n\n");
109 		else if (ba[i] & FM_SUSPECT_NOT_PRESENT)
110 			fmdump_printf(fp, "\tRemoved\n\n");
111 		else if (ba[i] & FM_SUSPECT_REPLACED)
112 			fmdump_printf(fp, "\tReplaced\n\n");
113 		else if (ba[i] & FM_SUSPECT_REPAIRED)
114 			fmdump_printf(fp, "\tRepair Attempted\n\n");
115 		else if (ba[i] & FM_SUSPECT_ACQUITTED)
116 			fmdump_printf(fp, "\tAcquitted\n\n");
117 		else
118 			fmdump_printf(fp, "\n\n");
119 
120 		fmdump_printf(fp, "        Problem in: %s\n",
121 		    rname ? rname : "-");
122 
123 		fmdump_printf(fp, "           Affects: %s\n",
124 		    aname ? aname : "-");
125 
126 		fmdump_printf(fp, "               FRU: %s\n",
127 		    fname ? fname : "-");
128 
129 		fmdump_printf(fp, "          Location: %s\n\n",
130 		    loc ? loc : "-");
131 
132 		free(fname);
133 		free(aname);
134 		free(rname);
135 	}
136 
137 	return (0);
138 }
139 
140 static int
141 flt_verb2(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
142 {
143 	const struct fmdump_fmt *efp = &fmdump_err_ops.do_formats[FMDUMP_VERB1];
144 	const struct fmdump_fmt *ffp = &fmdump_flt_ops.do_formats[FMDUMP_VERB1];
145 	uint_t i;
146 
147 	fmdump_printf(fp, "%s\n", ffp->do_hdr);
148 	(void) flt_short(lp, rp, fp);
149 
150 	if (rp->rec_nrefs != 0)
151 		fmdump_printf(fp, "\n  %s\n", efp->do_hdr);
152 
153 	for (i = 0; i < rp->rec_nrefs; i++) {
154 		fmdump_printf(fp, "  ");
155 		efp->do_func(lp, &rp->rec_xrefs[i], fp);
156 	}
157 
158 	fmdump_printf(fp, "\n");
159 	nvlist_print(fp, rp->rec_nvl);
160 	fmdump_printf(fp, "\n");
161 
162 	return (0);
163 }
164 
165 /*
166  * There is a lack of uniformity in how the various entries in our diagnosis
167  * are terminated.  Some end with one newline, others with two.  This makes the
168  * output of fmdump -m look a bit ugly.  Therefore we postprocess the message
169  * before printing it, removing consecutive occurences of newlines.
170  */
171 static void
172 postprocess_msg(char *msg)
173 {
174 	int i = 0, j = 0;
175 	char *buf;
176 
177 	if ((buf = malloc(strlen(msg) + 1)) == NULL)
178 		return;
179 
180 	buf[j++] = msg[i++];
181 	for (i = 1; i < strlen(msg); i++) {
182 		if (!(msg[i] == '\n' && msg[i - 1] == '\n'))
183 			buf[j++] = msg[i];
184 	}
185 	buf[j] = '\0';
186 	(void) strncpy(msg, buf, j+1);
187 	free(buf);
188 }
189 
190 /*ARGSUSED*/
191 static int
192 flt_msg(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
193 {
194 	char *msg;
195 
196 	if ((msg = fmd_msg_gettext_nv(g_msg, NULL, rp->rec_nvl)) == NULL) {
197 		(void) fprintf(stderr, "%s: failed to format message: %s\n",
198 		    g_pname, strerror(errno));
199 		g_errs++;
200 		return (-1);
201 	} else {
202 		postprocess_msg(msg);
203 		fmdump_printf(fp, "%s\n", msg);
204 		free(msg);
205 	}
206 
207 	return (0);
208 }
209 
210 const fmdump_ops_t fmdump_flt_ops = {
211 "fault", {
212 {
213 "TIME                 UUID                                 SUNW-MSG-ID",
214 (fmd_log_rec_f *)flt_short
215 }, {
216 "TIME                 UUID                                 SUNW-MSG-ID",
217 (fmd_log_rec_f *)flt_verb1
218 }, {
219 NULL,
220 (fmd_log_rec_f *)flt_verb2
221 }, {
222 NULL,
223 (fmd_log_rec_f *)flt_msg
224 } }
225 };
226