FreeCalypso > hg > freecalypso-reveng
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); +}