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