FreeCalypso > hg > freecalypso-reveng
comparison 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 |
comparison
equal
deleted
inserted
replaced
49:18fa570685de | 50:40b1ae2ab2d7 |
---|---|
1 #include <sys/types.h> | |
2 #include <sys/file.h> | |
3 #include <endian.h> | |
4 #include <stdio.h> | |
5 #include <string.h> | |
6 #include <strings.h> | |
7 #include <stdlib.h> | |
8 #include <unistd.h> | |
9 #include "types.h" | |
10 #include "struct.h" | |
11 #include "pathname.h" | |
12 | |
13 extern char *imgfile; | |
14 extern u8 image[0x480000]; | |
15 extern struct inode_info inode[]; | |
16 extern int last_inode; | |
17 extern int journal_start_ino; | |
18 | |
19 report_inode(ino) | |
20 { | |
21 struct inode_info *inf = inode + ino; | |
22 char pathname[PATHNAME_BUF_SIZE]; | |
23 int typechar; | |
24 | |
25 switch (inf->type) { | |
26 case 0xF1: | |
27 typechar = 'f'; | |
28 break; | |
29 case 0xF2: | |
30 typechar = 'd'; | |
31 break; | |
32 case 0xF4: | |
33 typechar = '.'; | |
34 break; | |
35 default: | |
36 fprintf(stderr, "inode #%x: unexpected type %02X\n", | |
37 ino, inf->type); | |
38 exit(1); | |
39 } | |
40 if (pathname_of_inode(ino, pathname) < 0) | |
41 strcpy(pathname, "-nopath-"); | |
42 printf("reverting #%04X %c %s\n", ino, typechar, pathname); | |
43 } | |
44 | |
45 unlink_inode(oldino, newino, is_sibling) | |
46 { | |
47 struct inode_info *inf = inode + oldino; | |
48 struct inode_flash *fl = inf->flash; | |
49 u16 *flashp; | |
50 | |
51 if (is_sibling) | |
52 flashp = &fl->sibling; | |
53 else | |
54 flashp = &fl->descend; | |
55 if (le16toh(*flashp) != newino) { | |
56 fprintf(stderr, | |
57 "fail: %s pointer of inode #%x does not point to #%x as expected\n", | |
58 is_sibling ? "sibling" : "descend", oldino, newino); | |
59 exit(1); | |
60 } | |
61 /* unprogram it! */ | |
62 *flashp = 0xFFFF; | |
63 } | |
64 | |
65 resurrect_old_ver(oldino, newino) | |
66 { | |
67 struct inode_info *old = inode + oldino; | |
68 struct inode_info *new = inode + newino; | |
69 u8 *typebyte; | |
70 | |
71 if (old->type != new->type || old->parent != new->parent || | |
72 strcmp(old->dataptr, new->dataptr)) { | |
73 fprintf(stderr, "inode #%x replacing #%x: mismatch error\n", | |
74 newino, oldino); | |
75 exit(1); | |
76 } | |
77 /* the item of interest is the old in-flash type byte */ | |
78 typebyte = &old->flash->type; | |
79 if (*typebyte) { | |
80 fprintf(stderr, | |
81 "inode #%x to be resurrected: not in deleted state\n", | |
82 oldino); | |
83 exit(1); | |
84 } | |
85 /* undo the zeroing */ | |
86 *typebyte = old->type; | |
87 } | |
88 | |
89 roll_back_inode(ino) | |
90 { | |
91 struct inode_info *inf = inode + ino; | |
92 | |
93 report_inode(ino); | |
94 if (!inf->flash->type) | |
95 printf("NOTE: object is already in deleted state\n"); | |
96 /* first order of business: unlink it */ | |
97 if (inf->j_unlink_ptr < 0) | |
98 unlink_inode(-inf->j_unlink_ptr, ino, 0); | |
99 else | |
100 unlink_inode(inf->j_unlink_ptr, ino, 1); | |
101 /* resurrect the previous version */ | |
102 if (inf->type != 0xF4) { | |
103 if (inf->j_oldver) | |
104 resurrect_old_ver(inf->j_oldver, ino); | |
105 else | |
106 printf("NOTE: no previous version to resurrect\n"); | |
107 } else if (inf->j_oldver) { | |
108 fprintf(stderr, | |
109 "error: unexpected oldver on inode #%x of type F4\n", | |
110 ino); | |
111 exit(1); | |
112 } | |
113 /* reblank the 3 flash areas programmed with this inode */ | |
114 memset(inf->flash, 0xFF, 16); | |
115 memset(inf->jflash, 0xFF, 16); | |
116 memset(inf->dataptr, 0xFF, inf->len); | |
117 } | |
118 | |
119 write_new_img(outfilename) | |
120 char *outfilename; | |
121 { | |
122 int fd, cc; | |
123 | |
124 fd = open(outfilename, O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
125 if (fd < 0) { | |
126 perror(outfilename); | |
127 exit(1); | |
128 } | |
129 cc = write(fd, image, sizeof image); | |
130 close(fd); | |
131 if (cc != sizeof image) { | |
132 fprintf(stderr, "error writing to %s\n", outfilename); | |
133 exit(1); | |
134 } | |
135 } | |
136 | |
137 main(argc, argv) | |
138 char **argv; | |
139 { | |
140 int ino, keep_ino; | |
141 char *strtoul_endp; | |
142 | |
143 if (argc != 4) { | |
144 usage: fprintf(stderr, | |
145 "usage: %s ffs-image inode-to-keep new-image\n", | |
146 argv[0]); | |
147 exit(1); | |
148 } | |
149 imgfile = argv[1]; | |
150 keep_ino = strtoul(argv[2], &strtoul_endp, 16); | |
151 if (!argv[2][0] || *strtoul_endp) | |
152 goto usage; | |
153 | |
154 read_img_file(); | |
155 read_inodes(); | |
156 walk_tree(); | |
157 check_object_names(); | |
158 parse_journal(); | |
159 check_object_names(); /* rerun for "undeleted" objects */ | |
160 if (keep_ino < journal_start_ino || keep_ino > last_inode) { | |
161 fprintf(stderr, "%s: bad inode number specified\n", argv[0]); | |
162 exit(1); | |
163 } | |
164 for (ino = last_inode; ino > keep_ino; ino--) | |
165 roll_back_inode(ino); | |
166 write_new_img(argv[3]); | |
167 exit(0); | |
168 } |