changeset 46:78ac405716db

pirollback: journal parsing implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 07 Jul 2013 06:14:40 +0000
parents 18472a2ccf55
children 3b6296382e24
files pirollback/Makefile pirollback/analyze.c pirollback/checknames.c pirollback/journal.c pirollback/struct.h
diffstat 5 files changed, 169 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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}
--- 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);
 }
--- 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) {
--- /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 <sys/types.h>
+#include <endian.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#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);
+	}
+}
--- 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;
 };