FreeCalypso > hg > freecalypso-reveng
view mpffs/dbgls.c @ 41:86a494a5f2b0
MPFFS description: documented relocated chunks and the journal file
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Fri, 05 Jul 2013 03:26:06 +0000 |
parents | e9c6d6615f32 |
children |
line wrap: on
line source
/* * Whereas mpffs-ls is more user-oriented, mpffs-dbgls is structured a little * different in order to provide a more low-level view of the FFS structure. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <unistd.h> #include "types.h" #include "struct.h" extern char *imgfile; extern u8 *image; extern struct objinfo root; extern int verbose; char workpath[512]; void dump_extra_chunks(first_extra_chunk) { int ent; struct objinfo ch; struct chunkinfo chi; for (ent = first_extra_chunk; ent != 0xFFFF; ent = ch.descend) { loop: ch.entryno = ent; get_index_entry(&ch); switch (ch.type) { case 0xF4: validate_chunk(&ch); printf(" #%x chunk addr=0x%x len=0x%x\n", ch.entryno, ch.offset, ch.len); size_extra_chunk(&ch, &chi); printf(" extra chunk: %lu bytes at 0x%lx\n", (u_long) chi.len, (u_long)(chi.start-image)); break; case 0x00: printf(" #%x marked as deleted\n", ch.entryno); if (ch.sibling == 0xFFFF) { printf(" nil sibling pointer!\n"); break; } ent = ch.sibling; printf(" relocated to #%x\n", ent); goto loop; default: printf( " file continuation object at index %x: unexpected type %02X\n", ent, ch.type); } if (ch.sibling != 0xFFFF) printf( " file continuation object (index %x) has a non-nil sibling pointer\n", ent); } } void dump_object(obj) struct objinfo *obj; { int typechar; struct chunkinfo chi; switch (obj->type) { case 0xF2: /* directory */ typechar = 'd'; break; case 0xF1: /* regular file */ typechar = 'f'; break; case 0xE1: /* special .journal file */ typechar = 'j'; break; default: /* unknown! */ typechar = 'U'; } printf("%c %s\n", typechar, workpath); printf(" #%x chunk addr=0x%x len=0x%x\n", obj->entryno, obj->offset, obj->len); switch (obj->type) { case 0xF2: /* directory */ return; case 0xF1: /* regular file */ size_head_chunk(obj, &chi); printf(" head chunk: %lu bytes at 0x%lx\n", (u_long) chi.len, (u_long)(chi.start-image)); dump_extra_chunks(obj->descend); return; default: if (obj->descend != 0xFFFF) printf(" unexpected descend pointer: %x\n", obj->descend); } } dump_dir(firstent, path_prefix) { int ent; struct objinfo obj; for (ent = firstent; ent != 0xFFFF; ent = obj.sibling) { obj.entryno = ent; get_index_entry(&obj); if (!obj.type) /* skip deleted objects w/o further validation */ continue; validate_chunk(&obj); validate_obj_name(&obj); if (path_prefix + strlen(obj.dataptr) + 2 > sizeof workpath) { fprintf(stderr, "handling object at index %x, name \"%s\": path buffer overflow\n", obj.entryno, (char *)obj.dataptr); exit(1); } sprintf(workpath + path_prefix, "/%s", (char *)obj.dataptr); dump_object(&obj); if (obj.type == 0xF2) dump_dir(obj.descend, strlen(workpath)); } } save_pathname_arg(pnarg) char *pnarg; { if (*pnarg == '/') pnarg++; if (strlen(pnarg) + 2 > sizeof workpath) { fprintf(stderr, "error: specified pathname is too long (overflows internal buffer)\n"); exit(1); } sprintf(workpath, "/%s", pnarg); } dump_by_pathname(pnarg) char *pnarg; { struct objinfo obj; save_pathname_arg(pnarg); obj.entryno = find_pathname(pnarg); get_index_entry(&obj); validate_chunk(&obj); dump_object(&obj); } usage() { fprintf(stderr, "usage: mpffs-dbgls [options] ffs-image [pathname]\n"); exit(1); } main(argc, argv) char **argv; { extern int optind; parse_cmdline_options(argc, argv); argc -= optind; argv += optind; if (argc < 1 || argc > 2) usage(); verbose++; imgfile = argv[0]; preliminaries(); if (argc == 1) dump_dir(root.descend, 0); else dump_by_pathname(argv[1]); exit(0); }