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.3 2005/07/05 00:26:03 dillon Exp $ 35 */ 36 37 #include "jscan.h" 38 39 static void dump_debug_stream(struct jstream *js); 40 static int dump_debug_subrecord(struct jstream *js, off_t *off, 41 off_t recsize, int level); 42 43 void 44 dump_debug(struct jfile *jf) 45 { 46 struct jstream *js; 47 48 while ((js = jscan_stream(jf)) != NULL) { 49 dump_debug_stream(js); 50 jscan_dispose(js); 51 } 52 } 53 54 static void 55 dump_debug_stream(struct jstream *js) 56 { 57 struct journal_rawrecbeg head; 58 int16_t sid; 59 60 jsread(js, 0, &head, sizeof(head)); 61 62 sid = head.streamid & JREC_STREAMID_MASK; 63 printf("STREAM %04x {\n", (int)(u_int16_t)head.streamid); 64 if (sid >= JREC_STREAMID_JMIN && sid < JREC_STREAMID_JMAX) { 65 off_t off = sizeof(head); 66 67 dump_debug_subrecord(js, &off, 68 js->js_normalized_total - sizeof(head), 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_debug_subrecord(struct jstream *js, off_t *off, off_t recsize, int level) 94 { 95 struct journal_subrecord sub; 96 int payload; 97 int subsize; 98 int error; 99 off_t base = *off; 100 101 error = 0; 102 while (recsize > 0) { 103 if ((error = jsread(js, base, &sub, sizeof(sub))) != 0) { 104 break; 105 } 106 printf("%*.*s", level * 4, level * 4, ""); 107 printf("@%lld ", base); 108 printf("RECORD %s [%04x/%d]", type_to_name(sub.rectype), 109 (int)(u_int16_t)sub.rectype, sub.recsize); 110 if (sub.recsize == -1) { 111 if ((sub.rectype & JMASK_NESTED) == 0) { 112 printf("Record size of -1 only works for nested records\n"); 113 error = -1; 114 break; 115 } 116 payload = 0x7FFFFFFF; 117 subsize = 0x7FFFFFFF; 118 } else { 119 payload = sub.recsize - sizeof(sub); 120 subsize = (sub.recsize + 7) & ~7; 121 } 122 if (sub.rectype & JMASK_NESTED) { 123 printf(" {\n"); 124 if (payload) { 125 *off = base + sizeof(sub); 126 error = dump_debug_subrecord(js, off, payload, level + 1); 127 } 128 printf("%*.*s}\n", level * 4, level * 4, ""); 129 } else if (sub.rectype & JMASK_SUBRECORD) { 130 printf(" DATA (%d)", payload); 131 error = dump_debug_payload(sub.rectype, js, base + sizeof(sub), payload, level); 132 *off = base + sizeof(sub) + payload; 133 printf("\n"); 134 } else { 135 printf("[%d bytes of unknown content]\n", sub.recsize); 136 } 137 if (error) 138 break; 139 if (sub.recsize == -1) { 140 recsize -= ((*off + 7) & ~7) - base; 141 base = (*off + 7) & ~7; 142 } else { 143 if (subsize == 0) 144 subsize = sizeof(sub); 145 recsize -= subsize; 146 base += subsize; 147 } 148 if (sub.rectype & JMASK_LAST) 149 break; 150 } 151 *off = base; 152 return(error); 153 } 154 155 int 156 dump_debug_payload(int16_t rectype, struct jstream *js, off_t off, 157 int recsize, int level) 158 { 159 enum { DT_NONE, DT_STRING, DT_DEC, DT_HEX, DT_OCT, 160 DT_DATA, DT_TIMESTAMP } dt = DT_DATA; 161 const char *buf; 162 int error; 163 int i; 164 int j; 165 166 error = jsreadp(js, off, (const void **)&buf, recsize); 167 if (error) 168 return (error); 169 170 switch(rectype & ~JMASK_LAST) { 171 case JLEAF_PAD: 172 case JLEAF_ABORT: 173 break; 174 case JLEAF_FILEDATA: 175 break; 176 case JLEAF_PATH1: 177 case JLEAF_PATH2: 178 case JLEAF_PATH3: 179 case JLEAF_PATH4: 180 dt = DT_STRING; 181 break; 182 case JLEAF_UID: 183 case JLEAF_GID: 184 case JLEAF_VTYPE: 185 dt = DT_DEC; 186 break; 187 case JLEAF_MODES: 188 dt = DT_OCT; 189 break; 190 case JLEAF_FFLAGS: 191 dt = DT_HEX; 192 break; 193 case JLEAF_PID: 194 case JLEAF_PPID: 195 dt = DT_DEC; 196 break; 197 case JLEAF_COMM: 198 dt = DT_STRING; 199 break; 200 case JLEAF_ATTRNAME: 201 dt = DT_STRING; 202 break; 203 case JLEAF_PATH_REF: 204 dt = DT_STRING; 205 break; 206 case JLEAF_RESERVED_0F: 207 break; 208 case JLEAF_SYMLINKDATA: 209 dt = DT_STRING; 210 break; 211 case JLEAF_SEEKPOS: 212 dt = DT_HEX; 213 break; 214 case JLEAF_INUM: 215 dt = DT_HEX; 216 break; 217 case JLEAF_NLINK: 218 dt = DT_DEC; 219 break; 220 case JLEAF_FSID: 221 dt = DT_HEX; 222 break; 223 case JLEAF_SIZE: 224 dt = DT_HEX; 225 break; 226 case JLEAF_ATIME: 227 case JLEAF_MTIME: 228 case JLEAF_CTIME: 229 dt = DT_TIMESTAMP; 230 break; 231 case JLEAF_GEN: 232 dt = DT_HEX; 233 break; 234 case JLEAF_FLAGS: 235 dt = DT_HEX; 236 break; 237 case JLEAF_UDEV: 238 dt = DT_HEX; 239 break; 240 case JLEAF_FILEREV: 241 dt = DT_HEX; 242 break; 243 default: 244 break; 245 } 246 switch(dt) { 247 case DT_NONE: 248 break; 249 case DT_STRING: 250 printf(" \""); 251 for (i = 0; i < recsize; ++i) 252 stringout(stdout, buf[i], 1); 253 printf("\""); 254 break; 255 case DT_DEC: 256 switch(recsize) { 257 case 1: 258 printf(" %d", (int)*(const u_int8_t *)buf); 259 break; 260 case 2: 261 printf(" %d", (int)*(const u_int16_t *)buf); 262 break; 263 case 4: 264 printf(" %d", (int)*(const u_int32_t *)buf); 265 break; 266 case 8: 267 printf(" %lld", (int64_t)*(const u_int64_t *)buf); 268 break; 269 default: 270 printf(" ?"); 271 break; 272 } 273 break; 274 case DT_HEX: 275 switch(recsize) { 276 case 1: 277 printf(" 0x%02x", (int)*(const u_int8_t *)buf); 278 break; 279 case 2: 280 printf(" 0x%04x", (int)*(const u_int16_t *)buf); 281 break; 282 case 4: 283 printf(" 0x%08x", (int)*(const u_int32_t *)buf); 284 break; 285 case 8: 286 printf(" 0x%016llx", (int64_t)*(const u_int64_t *)buf); 287 break; 288 default: 289 printf(" ?"); 290 break; 291 } 292 break; 293 case DT_OCT: 294 switch(recsize) { 295 case 1: 296 printf(" %03o", (int)*(const u_int8_t *)buf); 297 break; 298 case 2: 299 printf(" %06o", (int)*(const u_int16_t *)buf); 300 break; 301 case 4: 302 printf(" %011o", (int)*(const u_int32_t *)buf); 303 break; 304 case 8: 305 printf(" %022llo", (int64_t)*(const u_int64_t *)buf); 306 break; 307 default: 308 printf(" ?"); 309 break; 310 } 311 break; 312 case DT_TIMESTAMP: 313 { 314 struct tm *tp; 315 time_t t = ((const struct timespec *)buf)->tv_sec; 316 char outbuf[64]; 317 318 tp = localtime(&t); 319 strftime(outbuf, sizeof(outbuf), " <%d-%b-%Y %H:%M:%S>", tp); 320 printf("%s", outbuf); 321 } 322 break; 323 case DT_DATA: 324 default: 325 if (recsize < 16) { 326 for (i = 0; i < recsize; ++i) 327 printf(" %02x", (int)(unsigned char)buf[i]); 328 printf(" \""); 329 for (i = 0; i < recsize; ++i) 330 stringout(stdout, buf[i], 0); 331 printf("\""); 332 } else { 333 printf(" {\n"); 334 for (i = 0; i < recsize; i += 16) { 335 printf("%*.*s", level * 4 + 4, level * 4 + 4, ""); 336 for (j = i; j < i + 16 && j < recsize; ++j) 337 printf(" %02x", (int)(unsigned char)buf[j]); 338 for (; j < i + 16; ++j) 339 printf(" "); 340 printf(" \""); 341 for (j = i; j < i + 16 && j < recsize; ++j) 342 stringout(stdout, buf[j], 0); 343 printf("\"\n"); 344 } 345 printf("%*.*s}", level * 4, level * 4, ""); 346 } 347 break; 348 } 349 return (0); 350 } 351 352