# HG changeset patch # User Michael Spacefalcon # Date 1373177680 0 # Node ID 78ac405716db220fdb7d192bd90e8fed35a3b312 # Parent 18472a2ccf5555c0b30ff5137df1b047bc9b37de pirollback: journal parsing implemented diff -r 18472a2ccf55 -r 78ac405716db pirollback/Makefile --- a/pirollback/Makefile Sat Jul 06 22:06:38 2013 +0000 +++ b/pirollback/Makefile Sun Jul 07 06:14:40 2013 +0000 @@ -2,7 +2,7 @@ CFLAGS= -O2 PROGS= analyze inopath -ANALYZE_OBJS= analyze.o checknames.o init.o treewalk.o +ANALYZE_OBJS= analyze.o checknames.o init.o journal.o treewalk.o INOPATH_OBJS= checknames.o init.o inopath.o pathname.o treewalk.o all: ${PROGS} diff -r 18472a2ccf55 -r 78ac405716db pirollback/analyze.c --- a/pirollback/analyze.c Sat Jul 06 22:06:38 2013 +0000 +++ b/pirollback/analyze.c Sun Jul 07 06:14:40 2013 +0000 @@ -3,6 +3,7 @@ extern char *imgfile; extern int last_inode; +extern int journal_start_ino; main(argc, argv) char **argv; @@ -19,5 +20,8 @@ printf("Tree walk succeeded\n"); check_object_names(); printf("Name check succeeded\n"); + parse_journal(); + printf("Journal parse successful, start inode is #%x\n", + journal_start_ino); exit(0); } diff -r 18472a2ccf55 -r 78ac405716db pirollback/checknames.c --- a/pirollback/checknames.c Sat Jul 06 22:06:38 2013 +0000 +++ b/pirollback/checknames.c Sun Jul 07 06:14:40 2013 +0000 @@ -21,8 +21,13 @@ case 0xF1: case 0xF2: break; + case 0x00: + case 0xF4: + return; default: - return; + fprintf(stderr, "inode #%x: unexpected type %02X\n", ino, + in->type); + exit(1); } for (cp = in->dataptr, cnt = 0; ; cp++, cnt++) { if (cnt >= in->len) { diff -r 18472a2ccf55 -r 78ac405716db pirollback/journal.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pirollback/journal.c Sun Jul 07 06:14:40 2013 +0000 @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include "types.h" +#include "struct.h" + +extern u8 image[0x480000]; +extern struct inode_info inode[]; +extern int last_inode; +extern u8 blank_flash_line[16]; + +int journal_start_ino; + +find_journal() +{ + int ino; + struct inode_info *inf; + + for (ino = 2; ino <= last_inode; ino++) { + inf = inode + ino; + if (inf->type == 0xE1 && inf->parent == 1 && + !strcmp(inf->dataptr, ".journal")) + return(ino); + } + fprintf(stderr, "error: cannot find /.journal\n"); + exit(1); +} + +parse_journal() +{ + struct inode_info *inf; + struct journal_entry *jr, *endp; + int ino = 0; + u16 tempu16; + s16 temps16; + + inf = inode + find_journal(); + if (inf->len != 0x4010) { + fprintf(stderr, + "error: /.journal file length differs from expected\n"); + exit(1); + } + jr = (struct journal_entry *)(inf->dataptr + 0xC); + for (endp = jr + 0x3FF; jr < endp; jr++) { + if (!bcmp(jr, blank_flash_line, 16)) + break; + if (jr->status != 0xF1) { + fprintf(stderr, + "journal record at %x: status byte != F1\n", + (u8 *) jr - image); + exit(1); + } + tempu16 = le16toh(jr->this_ino); + if (ino) { + ino++; + if (ino != tempu16) { + fprintf(stderr, + "journal record at %x: break in inode # sequence\n", + (u8 *) jr - image); + exit(1); + } + } else { + ino = tempu16; + journal_start_ino = ino; + } + if (ino < 3 || ino > last_inode) { + fprintf(stderr, + "journal record at %x: inode # out of range\n", + (u8 *) jr - image); + exit(1); + } + inf = inode + ino; + inf->jflash = jr; + if (inf->type) { + if (jr->objtype != inf->type) { + fprintf(stderr, + "journal record at %x: type mismatch\n", + (u8 *) jr - image); + exit(1); + } + } else { + switch (jr->objtype) { + case 0xE1: + case 0xF1: + case 0xF2: + case 0xF4: + break; + default: + fprintf(stderr, + "journal record at %x: unexpected type byte value\n", + (u8 *) jr - image); + exit(1); + } + inf->type = jr->objtype; + } + if (le32toh(jr->location) != inf->rawloc) { + fprintf(stderr, + "journal record at %x: location field mismatch\n", + (u8 *) jr - image); + exit(1); + } + if (le16toh(jr->size) != inf->len) { + fprintf(stderr, + "journal record at %x: size field mismatch\n", + (u8 *) jr - image); + exit(1); + } + temps16 = le16toh(jr->link_ptr); + if (temps16 < -last_inode || temps16 > last_inode) { + fprintf(stderr, + "journal record at %x: linkptr field out of range\n", + (u8 *) jr - image); + exit(1); + } + inf->j_unlink_ptr = temps16; + temps16 = le16toh(jr->replacee); + if (temps16 < 0 || temps16 > last_inode) { + fprintf(stderr, + "journal record at %x: replacee field out of range\n", + (u8 *) jr - image); + exit(1); + } + inf->j_oldver = temps16; + if (jr->repli) { + fprintf(stderr, + "journal record at %x: last 16-bit word is not zero as expected\n", + (u8 *) jr - image); + exit(1); + } + } + if (!ino) { + fprintf(stderr, "error: journal is empty!\n"); + exit(1); + } + if (ino != last_inode) { + fprintf(stderr, "error: journal end != inode block end\n"); + exit(1); + } +} diff -r 18472a2ccf55 -r 78ac405716db pirollback/struct.h --- a/pirollback/struct.h Sat Jul 06 22:06:38 2013 +0000 +++ b/pirollback/struct.h Sun Jul 07 06:14:40 2013 +0000 @@ -10,6 +10,17 @@ u16 updates; }; +struct journal_entry { + u8 status; + u8 objtype; + u16 this_ino; + u16 link_ptr; + u16 replacee; + u32 location; + u16 size; + u16 repli; /* ??? */ +}; + /* our own struct for convenience */ struct inode_info { struct inode_flash *flash; @@ -22,4 +33,8 @@ int descend; int sibling; u8 *byte_after_name; + /* info added from parsing the journal */ + struct journal_entry *jflash; + int j_unlink_ptr; + int j_oldver; };