# HG changeset patch # User Michael Spacefalcon # Date 1374695424 0 # Node ID 40b1ae2ab2d7884c8ddf87a2d7b092fb1747d4c5 # Parent 18fa570685de6d4c0edf412b599dac903c933938 pirollback: actual rollback utility implemented, compiles diff -r 18fa570685de -r 40b1ae2ab2d7 .hgignore --- a/.hgignore Sun Jul 07 07:44:03 2013 +0000 +++ b/.hgignore Wed Jul 24 19:50:24 2013 +0000 @@ -17,3 +17,4 @@ ^pirollback/catino$ ^pirollback/dumpjournal$ ^pirollback/inopath$ +^pirollback/rollback$ diff -r 18fa570685de -r 40b1ae2ab2d7 pirollback/Makefile --- a/pirollback/Makefile Sun Jul 07 07:44:03 2013 +0000 +++ b/pirollback/Makefile Wed Jul 24 19:50:24 2013 +0000 @@ -1,12 +1,13 @@ CC= gcc CFLAGS= -O2 -PROGS= analyze catino dumpjournal inopath +PROGS= analyze catino dumpjournal inopath rollback ANALYZE_OBJS= analyze.o checknames.o init.o journal.o treewalk.o CAT_OBJS= catino.o checknames.o init.o journal.o treewalk.o DUMPJ_OBJS= checknames.o dumpjournal.o init.o journal.o pathname.o \ treewalk.o INOPATH_OBJS= checknames.o init.o inopath.o pathname.o treewalk.o +ROLLBACK_OBJS= checknames.o init.o journal.o pathname.o rollback.o treewalk.o all: ${PROGS} @@ -22,5 +23,8 @@ inopath: ${INOPATH_OBJS} ${CC} -o $@ ${INOPATH_OBJS} +rollback: ${ROLLBACK_OBJS} + ${CC} -o $@ ${ROLLBACK_OBJS} + clean: rm -f *.o *.out *errs ${PROGS} diff -r 18fa570685de -r 40b1ae2ab2d7 pirollback/rollback.c --- /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 +#include +#include +#include +#include +#include +#include +#include +#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); +}