xref: /illumos-gate/usr/src/cmd/fm/fmdump/common/fault.c (revision 540db9a9)
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_VERB2];
145 	uint_t i;
146 	char buf[32], str[32];
147 	char *class = NULL, *uuid = "-", *code = "-";
148 
149 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
150 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
151 
152 	(void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
153 	if (class != NULL && strcmp(class, FM_LIST_REPAIRED_CLASS) == 0) {
154 		(void) snprintf(str, sizeof (str), "%s %s", code, "Repaired");
155 		code = str;
156 	}
157 	if (class != NULL && strcmp(class, FM_LIST_RESOLVED_CLASS) == 0) {
158 		(void) snprintf(str, sizeof (str), "%s %s", code, "Resolved");
159 		code = str;
160 	}
161 	if (class != NULL && strcmp(class, FM_LIST_UPDATED_CLASS) == 0) {
162 		(void) snprintf(str, sizeof (str), "%s %s", code, "Updated");
163 		code = str;
164 	}
165 
166 	fmdump_printf(fp, "%s\n", ffp->do_hdr);
167 	fmdump_printf(fp, "%-20s.%9.9llu %-32s %s\n",
168 	    fmdump_year(buf, sizeof (buf), rp), rp->rec_nsec, uuid, code);
169 
170 	if (rp->rec_nrefs != 0)
171 		fmdump_printf(fp, "\n  %s\n", efp->do_hdr);
172 
173 	for (i = 0; i < rp->rec_nrefs; i++) {
174 		fmdump_printf(fp, "  ");
175 		efp->do_func(lp, &rp->rec_xrefs[i], fp);
176 	}
177 
178 	fmdump_printf(fp, "\n");
179 	nvlist_print(fp, rp->rec_nvl);
180 	fmdump_printf(fp, "\n");
181 
182 	return (0);
183 }
184 
185 /*
186  * There is a lack of uniformity in how the various entries in our diagnosis
187  * are terminated.  Some end with one newline, others with two.  This makes the
188  * output of fmdump -m look a bit ugly.  Therefore we postprocess the message
189  * before printing it, removing consecutive occurences of newlines.
190  */
191 static void
192 postprocess_msg(char *msg)
193 {
194 	int i = 0, j = 0;
195 	char *buf;
196 
197 	if ((buf = malloc(strlen(msg) + 1)) == NULL)
198 		return;
199 
200 	buf[j++] = msg[i++];
201 	for (i = 1; i < strlen(msg); i++) {
202 		if (!(msg[i] == '\n' && msg[i - 1] == '\n'))
203 			buf[j++] = msg[i];
204 	}
205 	buf[j] = '\0';
206 	(void) strncpy(msg, buf, j+1);
207 	free(buf);
208 }
209 
210 /*ARGSUSED*/
211 static int
212 flt_msg(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
213 {
214 	char *msg;
215 
216 	if ((msg = fmd_msg_gettext_nv(g_msg, NULL, rp->rec_nvl)) == NULL) {
217 		(void) fprintf(stderr, "%s: failed to format message: %s\n",
218 		    g_pname, strerror(errno));
219 		g_errs++;
220 		return (-1);
221 	} else {
222 		postprocess_msg(msg);
223 		fmdump_printf(fp, "%s\n", msg);
224 		free(msg);
225 	}
226 
227 	return (0);
228 }
229 
230 const fmdump_ops_t fmdump_flt_ops = {
231 "fault", {
232 {
233 "TIME                 UUID                                 SUNW-MSG-ID",
234 (fmd_log_rec_f *)flt_short
235 }, {
236 "TIME                 UUID                                 SUNW-MSG-ID",
237 (fmd_log_rec_f *)flt_verb1
238 }, {
239 "TIME                           UUID"
240 "                                 SUNW-MSG-ID",
241 (fmd_log_rec_f *)flt_verb2
242 }, {
243 NULL,
244 (fmd_log_rec_f *)flt_msg
245 } }
246 };
247