FreeCalypso > hg > freecalypso-reveng
view 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 source
#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); }