1 43b99cd9 2007-04-21 devnull #include "stdinc.h"
2 43b99cd9 2007-04-21 devnull #include "dat.h"
3 43b99cd9 2007-04-21 devnull #include "fns.h"
5 43b99cd9 2007-04-21 devnull static uchar *data;
6 43b99cd9 2007-04-21 devnull static uchar *data1;
7 43b99cd9 2007-04-21 devnull static int blocksize;
8 43b99cd9 2007-04-21 devnull static int sleepms;
9 9f8a101a 2008-04-16 rsc static int fd;
10 9f8a101a 2008-04-16 rsc static int force;
11 9f8a101a 2008-04-16 rsc static vlong offset0;
14 43b99cd9 2007-04-21 devnull usage(void)
16 9f8a101a 2008-04-16 rsc fprint(2, "usage: reseal [-f] [-b blocksize] [-s ms] arenapart1 [name...]]\n");
17 43b99cd9 2007-04-21 devnull threadexitsall(0);
20 43b99cd9 2007-04-21 devnull static int
21 9f8a101a 2008-04-16 rsc pwriteblock(uchar *buf, int n, vlong off)
23 43b99cd9 2007-04-21 devnull int nr, m;
25 43b99cd9 2007-04-21 devnull for(nr = 0; nr < n; nr += m){
26 43b99cd9 2007-04-21 devnull m = n - nr;
27 9f8a101a 2008-04-16 rsc m = pwrite(fd, &buf[nr], m, offset0+off+nr);
28 43b99cd9 2007-04-21 devnull if(m <= 0)
29 43b99cd9 2007-04-21 devnull return -1;
31 43b99cd9 2007-04-21 devnull return 0;
34 43b99cd9 2007-04-21 devnull static int
35 9f8a101a 2008-04-16 rsc preadblock(uchar *buf, int n, vlong off)
37 43b99cd9 2007-04-21 devnull int nr, m;
39 43b99cd9 2007-04-21 devnull for(nr = 0; nr < n; nr += m){
40 43b99cd9 2007-04-21 devnull m = n - nr;
41 9f8a101a 2008-04-16 rsc m = pread(fd, &buf[nr], m, offset0+off+nr);
42 43b99cd9 2007-04-21 devnull if(m <= 0){
43 43b99cd9 2007-04-21 devnull if(m == 0)
44 43b99cd9 2007-04-21 devnull werrstr("early eof");
45 43b99cd9 2007-04-21 devnull return -1;
48 43b99cd9 2007-04-21 devnull return 0;
51 43b99cd9 2007-04-21 devnull static int
52 9f8a101a 2008-04-16 rsc loadheader(char *name, ArenaHead *head, Arena *arena, vlong off)
54 9f8a101a 2008-04-16 rsc if(preadblock(data, head->blocksize, off + head->size - head->blocksize) < 0){
55 43b99cd9 2007-04-21 devnull fprint(2, "%s: reading arena tail: %r\n", name);
56 43b99cd9 2007-04-21 devnull return -1;
59 43b99cd9 2007-04-21 devnull memset(arena, 0, sizeof *arena);
60 43b99cd9 2007-04-21 devnull if(unpackarena(arena, data) < 0){
61 43b99cd9 2007-04-21 devnull fprint(2, "%s: unpack arena tail: %r\n", name);
62 43b99cd9 2007-04-21 devnull return -1;
64 43b99cd9 2007-04-21 devnull arena->blocksize = head->blocksize;
65 43b99cd9 2007-04-21 devnull arena->base = off + head->blocksize;
66 43b99cd9 2007-04-21 devnull arena->clumpmax = arena->blocksize / ClumpInfoSize;
67 43b99cd9 2007-04-21 devnull arena->size = head->size - 2*head->blocksize;
69 43b99cd9 2007-04-21 devnull if(arena->diskstats.sealed)
70 43b99cd9 2007-04-21 devnull scorecp(arena->score, data + head->blocksize - VtScoreSize);
71 43b99cd9 2007-04-21 devnull return 0;
74 43b99cd9 2007-04-21 devnull uchar zero[VtScoreSize];
76 43b99cd9 2007-04-21 devnull static int
77 9f8a101a 2008-04-16 rsc verify(Arena *arena, void *data, uchar *newscore)
79 43b99cd9 2007-04-21 devnull vlong e, bs, n, o;
80 43b99cd9 2007-04-21 devnull DigestState ds, ds1;
81 43b99cd9 2007-04-21 devnull uchar score[VtScoreSize];
84 43b99cd9 2007-04-21 devnull * now we know how much to read
85 43b99cd9 2007-04-21 devnull * read everything but the last block, which is special
87 43b99cd9 2007-04-21 devnull e = arena->size + arena->blocksize;
88 43b99cd9 2007-04-21 devnull o = arena->base - arena->blocksize;
89 43b99cd9 2007-04-21 devnull bs = arena->blocksize;
90 43b99cd9 2007-04-21 devnull memset(&ds, 0, sizeof ds);
91 43b99cd9 2007-04-21 devnull for(n = 0; n < e; n += bs){
92 9f8a101a 2008-04-16 rsc if(preadblock(data, bs, o + n) < 0){
93 43b99cd9 2007-04-21 devnull werrstr("read: %r");
94 43b99cd9 2007-04-21 devnull return -1;
96 43b99cd9 2007-04-21 devnull if(n + bs > e)
97 43b99cd9 2007-04-21 devnull bs = e - n;
98 43b99cd9 2007-04-21 devnull sha1(data, bs, nil, &ds);
101 43b99cd9 2007-04-21 devnull /* last block */
102 9f8a101a 2008-04-16 rsc if(preadblock(data, arena->blocksize, o + e) < 0){
103 43b99cd9 2007-04-21 devnull werrstr("read: %r");
104 43b99cd9 2007-04-21 devnull return -1;
106 43b99cd9 2007-04-21 devnull ds1 = ds;
107 43b99cd9 2007-04-21 devnull sha1(data, bs - VtScoreSize, nil, &ds);
108 43b99cd9 2007-04-21 devnull sha1(zero, VtScoreSize, score, &ds);
109 43b99cd9 2007-04-21 devnull if(scorecmp(score, arena->score) != 0){
111 9f8a101a 2008-04-16 rsc werrstr("score mismatch: %V != %V", score, arena->score);
114 9f8a101a 2008-04-16 rsc fprint(2, "warning: score mismatch %V != %V\n", score, arena->score);
117 43b99cd9 2007-04-21 devnull /* prepare new last block */
118 43b99cd9 2007-04-21 devnull memset(data, 0, arena->blocksize);
119 43b99cd9 2007-04-21 devnull packarena(arena, data);
120 43b99cd9 2007-04-21 devnull sha1(data, bs, newscore, &ds1);
121 43b99cd9 2007-04-21 devnull scorecp((uchar*)data + arena->blocksize - VtScoreSize, newscore);
123 43b99cd9 2007-04-21 devnull return 0;
126 43b99cd9 2007-04-21 devnull static void
127 43b99cd9 2007-04-21 devnull resealarena(char *name, vlong len)
129 43b99cd9 2007-04-21 devnull ArenaHead head;
130 43b99cd9 2007-04-21 devnull Arena arena;
131 43b99cd9 2007-04-21 devnull DigestState s;
132 43b99cd9 2007-04-21 devnull u64int off;
133 43b99cd9 2007-04-21 devnull uchar newscore[VtScoreSize];
135 43b99cd9 2007-04-21 devnull fprint(2, "%s: begin reseal\n", name);
137 43b99cd9 2007-04-21 devnull memset(&s, 0, sizeof s);
139 43b99cd9 2007-04-21 devnull off = seek(fd, 0, 1);
142 43b99cd9 2007-04-21 devnull * read a little bit, which will include the header
144 9f8a101a 2008-04-16 rsc if(preadblock(data, HeadSize, off) < 0){
145 43b99cd9 2007-04-21 devnull fprint(2, "%s: reading header: %r\n", name);
148 43b99cd9 2007-04-21 devnull if(unpackarenahead(&head, data) < 0){
149 43b99cd9 2007-04-21 devnull fprint(2, "%s: corrupt arena header: %r\n", name);
152 43b99cd9 2007-04-21 devnull if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
153 43b99cd9 2007-04-21 devnull fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
154 43b99cd9 2007-04-21 devnull if(len != 0 && len != head.size)
155 43b99cd9 2007-04-21 devnull fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
156 43b99cd9 2007-04-21 devnull if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
157 43b99cd9 2007-04-21 devnull fprint(2, "%s: warning: unexpected name %s\n", name, head.name);
159 9f8a101a 2008-04-16 rsc if(loadheader(name, &head, &arena, off) < 0)
162 43b99cd9 2007-04-21 devnull if(!arena.diskstats.sealed){
163 43b99cd9 2007-04-21 devnull fprint(2, "%s: not sealed\n", name);
167 9f8a101a 2008-04-16 rsc if(verify(&arena, data, newscore) < 0){
168 43b99cd9 2007-04-21 devnull fprint(2, "%s: failed to verify before reseal: %r\n", name);
172 9f8a101a 2008-04-16 rsc if(pwriteblock(data, arena.blocksize, arena.base + arena.size) < 0){
173 43b99cd9 2007-04-21 devnull fprint(2, "%s: writing new tail: %r\n", name);
176 43b99cd9 2007-04-21 devnull scorecp(arena.score, newscore);
177 43b99cd9 2007-04-21 devnull fprint(2, "%s: resealed: %V\n", name, newscore);
179 9f8a101a 2008-04-16 rsc if(verify(&arena, data, newscore) < 0){
180 43b99cd9 2007-04-21 devnull fprint(2, "%s: failed to verify after reseal!: %r\n", name);
184 43b99cd9 2007-04-21 devnull fprint(2, "%s: verified: %V\n", name, newscore);
187 43b99cd9 2007-04-21 devnull static int
188 43b99cd9 2007-04-21 devnull shouldcheck(char *name, char **s, int n)
192 43b99cd9 2007-04-21 devnull if(n == 0)
193 43b99cd9 2007-04-21 devnull return 1;
195 43b99cd9 2007-04-21 devnull for(i=0; i<n; i++){
196 43b99cd9 2007-04-21 devnull if(s[i] && strcmp(name, s[i]) == 0){
197 43b99cd9 2007-04-21 devnull s[i] = nil;
198 43b99cd9 2007-04-21 devnull return 1;
201 43b99cd9 2007-04-21 devnull return 0;
205 9f8a101a 2008-04-16 rsc readap(ArenaPart *ap)
207 43b99cd9 2007-04-21 devnull char *table;
209 9f8a101a 2008-04-16 rsc if(preadblock(data, 8192, PartBlank) < 0)
210 43b99cd9 2007-04-21 devnull sysfatal("read arena part header: %r");
211 43b99cd9 2007-04-21 devnull if(unpackarenapart(ap, data) < 0)
212 43b99cd9 2007-04-21 devnull sysfatal("corrupted arena part header: %r");
213 43b99cd9 2007-04-21 devnull fprint(2, "# arena part version=%d blocksize=%d arenabase=%d\n",
214 43b99cd9 2007-04-21 devnull ap->version, ap->blocksize, ap->arenabase);
215 43b99cd9 2007-04-21 devnull ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1);
216 43b99cd9 2007-04-21 devnull ap->tabsize = ap->arenabase - ap->tabbase;
217 43b99cd9 2007-04-21 devnull table = malloc(ap->tabsize+1);
218 9f8a101a 2008-04-16 rsc if(preadblock((uchar*)table, ap->tabsize, ap->tabbase) < 0)
219 43b99cd9 2007-04-21 devnull sysfatal("reading arena part directory: %r");
220 43b99cd9 2007-04-21 devnull table[ap->tabsize] = 0;
221 43b99cd9 2007-04-21 devnull return table;
225 43b99cd9 2007-04-21 devnull threadmain(int argc, char *argv[])
227 43b99cd9 2007-04-21 devnull int i, nline;
228 43b99cd9 2007-04-21 devnull char *p, *q, *table, *f[10], line[256];
229 43b99cd9 2007-04-21 devnull vlong start, stop;
230 43b99cd9 2007-04-21 devnull ArenaPart ap;
233 43b99cd9 2007-04-21 devnull ventifmtinstall();
234 43b99cd9 2007-04-21 devnull blocksize = MaxIoSize;
235 43b99cd9 2007-04-21 devnull ARGBEGIN{
236 43b99cd9 2007-04-21 devnull case 'b':
237 43b99cd9 2007-04-21 devnull blocksize = unittoull(EARGF(usage()));
242 43b99cd9 2007-04-21 devnull case 's':
243 43b99cd9 2007-04-21 devnull sleepms = atoi(EARGF(usage()));
245 43b99cd9 2007-04-21 devnull default:
246 43b99cd9 2007-04-21 devnull usage();
250 43b99cd9 2007-04-21 devnull if(argc < 2)
251 43b99cd9 2007-04-21 devnull usage();
253 43b99cd9 2007-04-21 devnull data = vtmalloc(blocksize);
254 9f8a101a 2008-04-16 rsc if((part = initpart(argv[0], ORDWR)) == nil)
255 9f8a101a 2008-04-16 rsc sysfatal("open partition %s: %r", argv[0]);
256 9f8a101a 2008-04-16 rsc fd = part->fd;
257 9f8a101a 2008-04-16 rsc offset0 = part->offset;
259 9f8a101a 2008-04-16 rsc table = readap(&ap);
261 43b99cd9 2007-04-21 devnull nline = atoi(table);
262 43b99cd9 2007-04-21 devnull p = strchr(table, '\n');
265 43b99cd9 2007-04-21 devnull for(i=0; i<nline; i++){
266 43b99cd9 2007-04-21 devnull if(p == nil){
267 43b99cd9 2007-04-21 devnull fprint(2, "warning: unexpected arena table end\n");
270 43b99cd9 2007-04-21 devnull q = strchr(p, '\n');
272 43b99cd9 2007-04-21 devnull *q++ = 0;
273 43b99cd9 2007-04-21 devnull if(strlen(p) >= sizeof line){
274 43b99cd9 2007-04-21 devnull fprint(2, "warning: long arena table line: %s\n", p);
276 43b99cd9 2007-04-21 devnull continue;
278 43b99cd9 2007-04-21 devnull strcpy(line, p);
279 43b99cd9 2007-04-21 devnull memset(f, 0, sizeof f);
280 43b99cd9 2007-04-21 devnull if(tokenize(line, f, nelem(f)) < 3){
281 43b99cd9 2007-04-21 devnull fprint(2, "warning: bad arena table line: %s\n", p);
283 43b99cd9 2007-04-21 devnull continue;
286 43b99cd9 2007-04-21 devnull if(shouldcheck(f[0], argv+1, argc-1)){
287 43b99cd9 2007-04-21 devnull start = strtoull(f[1], 0, 0);
288 43b99cd9 2007-04-21 devnull stop = strtoull(f[2], 0, 0);
289 43b99cd9 2007-04-21 devnull if(stop <= start){
290 43b99cd9 2007-04-21 devnull fprint(2, "%s: bad start,stop %lld,%lld\n", f[0], stop, start);
291 43b99cd9 2007-04-21 devnull continue;
293 43b99cd9 2007-04-21 devnull if(seek(fd, start, 0) < 0)
294 43b99cd9 2007-04-21 devnull fprint(2, "%s: seek to start: %r\n", f[0]);
295 43b99cd9 2007-04-21 devnull resealarena(f[0], stop - start);
298 43b99cd9 2007-04-21 devnull for(i=2; i<argc; i++)
299 43b99cd9 2007-04-21 devnull if(argv[i] != 0)
300 43b99cd9 2007-04-21 devnull fprint(2, "%s: did not find arena\n", argv[i]);
302 43b99cd9 2007-04-21 devnull threadexitsall(nil);