Merge from vendor branch NTPD:
[dragonfly.git] / sbin / jscan / dump_debug.c
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