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