diff pirollback/journal.c @ 46:78ac405716db

pirollback: journal parsing implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 07 Jul 2013 06:14:40 +0000
parents
children
line wrap: on
line diff
--- /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);
+	}
+}