xref: /dflybsd-src/sbin/jscan/dump_debug.c (revision b5b0912b1891e95ccc48cad83f09239ccb7ffc16)
1 /*
2  * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/sbin/jscan/dump_debug.c,v 1.2 2005/03/07 05:05:04 dillon Exp $
35  */
36 
37 #include "jscan.h"
38 
39 static void dump_debug_stream(struct jstream *js);
40 static int dump_subrecord(struct jstream *js, off_t off, int recsize, int level);
41 static int dump_payload(int16_t rectype, struct jstream *js, off_t off,
42 	     int recsize, int level);
43 
44 void
45 dump_debug(struct jfile *jf)
46 {
47     struct jstream *js;
48 
49     while ((js = jscan_stream(jf)) != NULL) {
50 	dump_debug_stream(js);
51 	jscan_dispose(js);
52     }
53 }
54 
55 static void
56 dump_debug_stream(struct jstream *js)
57 {
58 	struct journal_rawrecbeg head;
59 	int16_t sid;
60 
61 	jsread(js, 0, &head, sizeof(head));
62 
63 	sid = head.streamid & JREC_STREAMID_MASK;
64 	printf("STREAM %04x {\n", (int)(u_int16_t)head.streamid);
65 	if (sid >= JREC_STREAMID_JMIN && sid < JREC_STREAMID_JMAX) {
66 	    dump_subrecord(js, sizeof(head),
67 			head.recsize - sizeof(struct journal_rawrecbeg) -
68 			sizeof(struct journal_rawrecend),
69 			1);
70 	} else {
71 	    switch(head.streamid & JREC_STREAMID_MASK) {
72 	    case JREC_STREAMID_SYNCPT & JREC_STREAMID_MASK:
73 		printf("    SYNCPT\n");
74 		break;
75 	    case JREC_STREAMID_PAD & JREC_STREAMID_MASK:
76 		printf("    PAD\n");
77 		break;
78 	    case JREC_STREAMID_DISCONT & JREC_STREAMID_MASK:
79 		printf("    DISCONT\n");
80 		break;
81 	    case JREC_STREAMID_ANNOTATE & JREC_STREAMID_MASK:
82 		printf("    ANNOTATION\n");
83 		break;
84 	    default:
85 		printf("    UNKNOWN\n");
86 		break;
87 	    }
88 	}
89 	printf("}\n");
90 }
91 
92 static int
93 dump_subrecord(struct jstream *js, off_t off, int recsize, int level)
94 {
95     struct journal_subrecord sub;
96     int payload;
97     int subsize;
98     int error;
99     int i;
100 
101     error = 0;
102     while (recsize > 0) {
103 	if ((error = jsread(js, off, &sub, sizeof(sub))) != 0)
104 	    break;
105 	printf("%*.*s", level * 4, level * 4, "");
106 	printf("@%lld ", off);
107 	printf("RECORD %s [%04x/%d]", type_to_name(sub.rectype),
108 				(int)(u_int16_t)sub.rectype, sub.recsize);
109 	payload = sub.recsize - sizeof(sub);
110 	subsize = (sub.recsize + 7) & ~7;
111 	if (sub.rectype & JMASK_NESTED) {
112 	    printf(" {\n");
113 	    if (payload)
114 		error = dump_subrecord(js, off + sizeof(sub), payload, level + 1);
115 	    printf("%*.*s}\n", level * 4, level * 4, "");
116 	} else if (sub.rectype & JMASK_SUBRECORD) {
117 	    printf(" DATA (%d)", payload);
118 	    error = dump_payload(sub.rectype, js, off + sizeof(sub), payload, level);
119 	    printf("\n");
120 	    if (error)
121 		break;
122 	} else {
123 	    printf("[unknown content]\n", sub.recsize);
124 	}
125 	if (subsize == 0)
126 		subsize = sizeof(sub);
127 	recsize -= subsize;
128 	off += subsize;
129     }
130     return(error);
131 }
132 
133 static int
134 dump_payload(int16_t rectype, struct jstream *js, off_t off,
135 	     int recsize, int level)
136 {
137     enum { DT_NONE, DT_STRING, DT_DEC, DT_HEX, DT_OCT,
138 	   DT_DATA, DT_TIMESTAMP } dt = DT_DATA;
139     const char *buf;
140     int didalloc;
141     int error;
142     int i;
143     int j;
144 
145     error = jsreadp(js, off, (const void **)&buf, recsize);
146     if (error)
147 	return (error);
148 
149     switch(rectype & ~JMASK_LAST) {
150     case JLEAF_PAD:
151     case JLEAF_ABORT:
152 	break;
153     case JLEAF_FILEDATA:
154 	break;
155     case JLEAF_PATH1:
156     case JLEAF_PATH2:
157     case JLEAF_PATH3:
158     case JLEAF_PATH4:
159 	dt = DT_STRING;
160 	break;
161     case JLEAF_UID:
162     case JLEAF_GID:
163 	dt = DT_DEC;
164 	break;
165     case JLEAF_MODES:
166 	dt = DT_OCT;
167 	break;
168     case JLEAF_FFLAGS:
169 	dt = DT_HEX;
170 	break;
171     case JLEAF_PID:
172     case JLEAF_PPID:
173 	dt = DT_DEC;
174 	break;
175     case JLEAF_COMM:
176 	dt = DT_STRING;
177 	break;
178     case JLEAF_ATTRNAME:
179 	dt = DT_STRING;
180 	break;
181     case JLEAF_PATH_REF:
182 	dt = DT_STRING;
183 	break;
184     case JLEAF_RESERVED_0F:
185 	break;
186     case JLEAF_SYMLINKDATA:
187 	dt = DT_STRING;
188 	break;
189     case JLEAF_SEEKPOS:
190 	dt = DT_HEX;
191 	break;
192     case JLEAF_INUM:
193 	dt = DT_HEX;
194 	break;
195     case JLEAF_NLINK:
196 	dt = DT_DEC;
197 	break;
198     case JLEAF_FSID:
199 	dt = DT_HEX;
200 	break;
201     case JLEAF_SIZE:
202 	dt = DT_HEX;
203 	break;
204     case JLEAF_ATIME:
205     case JLEAF_MTIME:
206     case JLEAF_CTIME:
207 	dt = DT_TIMESTAMP;
208 	break;
209     case JLEAF_GEN:
210 	dt = DT_HEX;
211 	break;
212     case JLEAF_FLAGS:
213 	dt = DT_HEX;
214 	break;
215     case JLEAF_UDEV:
216 	dt = DT_HEX;
217 	break;
218     case JLEAF_FILEREV:
219 	dt = DT_HEX;
220 	break;
221     default:
222 	break;
223     }
224     switch(dt) {
225     case DT_NONE:
226 	break;
227     case DT_STRING:
228 	printf(" \"");
229 	for (i = 0; i < recsize; ++i)
230 	    stringout(stdout, buf[i], 1);
231 	printf("\"");
232 	break;
233     case DT_DEC:
234 	switch(recsize) {
235 	case 1:
236 	    printf(" %d", (int)*(u_int8_t *)buf);
237 	    break;
238 	case 2:
239 	    printf(" %d", (int)*(u_int16_t *)buf);
240 	    break;
241 	case 4:
242 	    printf(" %d", (int)*(u_int32_t *)buf);
243 	    break;
244 	case 8:
245 	    printf(" %d", (int64_t)*(u_int64_t *)buf);
246 	    break;
247 	default:
248 	    printf(" ?");
249 	    break;
250 	}
251 	break;
252     case DT_HEX:
253 	switch(recsize) {
254 	case 1:
255 	    printf(" 0x%02x", (int)*(u_int8_t *)buf);
256 	    break;
257 	case 2:
258 	    printf(" 0x%04x", (int)*(u_int16_t *)buf);
259 	    break;
260 	case 4:
261 	    printf(" 0x%08x", (int)*(u_int32_t *)buf);
262 	    break;
263 	case 8:
264 	    printf(" 0x%016llx", (int64_t)*(u_int64_t *)buf);
265 	    break;
266 	default:
267 	    printf(" ?");
268 	    break;
269 	}
270 	break;
271     case DT_OCT:
272 	switch(recsize) {
273 	case 1:
274 	    printf(" %03o", (int)*(u_int8_t *)buf);
275 	    break;
276 	case 2:
277 	    printf(" %06o", (int)*(u_int16_t *)buf);
278 	    break;
279 	case 4:
280 	    printf(" %011o", (int)*(u_int32_t *)buf);
281 	    break;
282 	case 8:
283 	    printf(" %022llo", (int64_t)*(u_int64_t *)buf);
284 	    break;
285 	default:
286 	    printf(" ?");
287 	    break;
288 	}
289 	break;
290     case DT_TIMESTAMP:
291 	{
292 	    struct tm *tp;
293 	    time_t t = ((struct timespec *)buf)->tv_sec;
294 	    char outbuf[64];
295 
296 	    tp = localtime(&t);
297 	    strftime(outbuf, sizeof(outbuf), " <%d-%b-%Y %H:%M:%S>", tp);
298 	    printf("%s", outbuf);
299 	}
300 	break;
301     case DT_DATA:
302     default:
303 	if (recsize < 16) {
304 	    for (i = 0; i < recsize; ++i)
305 		printf(" %02x", (int)(unsigned char)buf[i]);
306 	    printf(" \"");
307 	    for (i = 0; i < recsize; ++i)
308 		stringout(stdout, buf[i], 0);
309 	    printf("\"");
310 	} else {
311 	    printf(" {\n");
312 	    for (i = 0; i < recsize; i += 16) {
313 		printf("%*.*s", level * 4 + 4, level * 4 + 4, "");
314 		for (j = i; j < i + 16 && j < recsize; ++j)
315 		    printf(" %02x", (int)(unsigned char)buf[j]);
316 		for (; j < i + 16; ++j)
317 		    printf("   ");
318 		printf(" \"");
319 		for (j = i; j < i + 16 && j < recsize; ++j)
320 		    stringout(stdout, buf[j], 0);
321 		printf("\"\n");
322 	    }
323 	    printf("%*.*s}", level * 4, level * 4, "");
324 	}
325 	break;
326     }
327     return (0);
328 }
329 
330