diff pirollback/rollback.c @ 50:40b1ae2ab2d7

pirollback: actual rollback utility implemented, compiles
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Wed, 24 Jul 2013 19:50:24 +0000
parents
children e516128db432
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pirollback/rollback.c	Wed Jul 24 19:50:24 2013 +0000
@@ -0,0 +1,168 @@
+#include <sys/types.h>
+#include <sys/file.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"
+#include "pathname.h"
+
+extern char *imgfile;
+extern u8 image[0x480000];
+extern struct inode_info inode[];
+extern int last_inode;
+extern int journal_start_ino;
+
+report_inode(ino)
+{
+	struct inode_info *inf = inode + ino;
+	char pathname[PATHNAME_BUF_SIZE];
+	int typechar;
+
+	switch (inf->type) {
+	case 0xF1:
+		typechar = 'f';
+		break;
+	case 0xF2:
+		typechar = 'd';
+		break;
+	case 0xF4:
+		typechar = '.';
+		break;
+	default:
+		fprintf(stderr, "inode #%x: unexpected type %02X\n",
+			ino, inf->type);
+		exit(1);
+	}
+	if (pathname_of_inode(ino, pathname) < 0)
+		strcpy(pathname, "-nopath-");
+	printf("reverting #%04X %c %s\n", ino, typechar, pathname);
+}
+
+unlink_inode(oldino, newino, is_sibling)
+{
+	struct inode_info *inf = inode + oldino;
+	struct inode_flash *fl = inf->flash;
+	u16 *flashp;
+
+	if (is_sibling)
+		flashp = &fl->sibling;
+	else
+		flashp = &fl->descend;
+	if (le16toh(*flashp) != newino) {
+		fprintf(stderr,
+	"fail: %s pointer of inode #%x does not point to #%x as expected\n",
+			is_sibling ? "sibling" : "descend", oldino, newino);
+		exit(1);
+	}
+	/* unprogram it! */
+	*flashp = 0xFFFF;
+}
+
+resurrect_old_ver(oldino, newino)
+{
+	struct inode_info *old = inode + oldino;
+	struct inode_info *new = inode + newino;
+	u8 *typebyte;
+
+	if (old->type != new->type || old->parent != new->parent ||
+	    strcmp(old->dataptr, new->dataptr)) {
+		fprintf(stderr, "inode #%x replacing #%x: mismatch error\n",
+			newino, oldino);
+		exit(1);
+	}
+	/* the item of interest is the old in-flash type byte */
+	typebyte = &old->flash->type;
+	if (*typebyte) {
+		fprintf(stderr,
+			"inode #%x to be resurrected: not in deleted state\n",
+			oldino);
+		exit(1);
+	}
+	/* undo the zeroing */
+	*typebyte = old->type;
+}
+
+roll_back_inode(ino)
+{
+	struct inode_info *inf = inode + ino;
+
+	report_inode(ino);
+	if (!inf->flash->type)
+		printf("NOTE: object is already in deleted state\n");
+	/* first order of business: unlink it */
+	if (inf->j_unlink_ptr < 0)
+		unlink_inode(-inf->j_unlink_ptr, ino, 0);
+	else
+		unlink_inode(inf->j_unlink_ptr, ino, 1);
+	/* resurrect the previous version */
+	if (inf->type != 0xF4) {
+		if (inf->j_oldver)
+			resurrect_old_ver(inf->j_oldver, ino);
+		else
+			printf("NOTE: no previous version to resurrect\n");
+	} else if (inf->j_oldver) {
+		fprintf(stderr,
+			"error: unexpected oldver on inode #%x of type F4\n",
+			ino);
+		exit(1);
+	}
+	/* reblank the 3 flash areas programmed with this inode */
+	memset(inf->flash, 0xFF, 16);
+	memset(inf->jflash, 0xFF, 16);
+	memset(inf->dataptr, 0xFF, inf->len);
+}
+
+write_new_img(outfilename)
+	char *outfilename;
+{
+	int fd, cc;
+
+	fd = open(outfilename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+	if (fd < 0) {
+		perror(outfilename);
+		exit(1);
+	}
+	cc = write(fd, image, sizeof image);
+	close(fd);
+	if (cc != sizeof image) {
+		fprintf(stderr, "error writing to %s\n", outfilename);
+		exit(1);
+	}
+}
+
+main(argc, argv)
+	char **argv;
+{
+	int ino, keep_ino;
+	char *strtoul_endp;
+
+	if (argc != 4) {
+usage:		fprintf(stderr,
+			"usage: %s ffs-image inode-to-keep new-image\n",
+			argv[0]);
+		exit(1);
+	}
+	imgfile = argv[1];
+	keep_ino = strtoul(argv[2], &strtoul_endp, 16);
+	if (!argv[2][0] || *strtoul_endp)
+		goto usage;
+
+	read_img_file();
+	read_inodes();
+	walk_tree();
+	check_object_names();
+	parse_journal();
+	check_object_names();	/* rerun for "undeleted" objects */
+	if (keep_ino < journal_start_ino || keep_ino > last_inode) {
+		fprintf(stderr, "%s: bad inode number specified\n", argv[0]);
+		exit(1);
+	}
+	for (ino = last_inode; ino > keep_ino; ino--)
+		roll_back_inode(ino);
+	write_new_img(argv[3]);
+	exit(0);
+}