Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
5 /*
6 * disk structure conversion routines
7 */
8 #define U8GET(p) ((p)[0])
9 #define U16GET(p) (((p)[0]<<8)|(p)[1])
10 #define U32GET(p) ((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
11 #define U64GET(p) (((u64int)U32GET(p)<<32)|(u64int)U32GET((p)+4))
13 #define U8PUT(p,v) (p)[0]=(v)&0xFF
14 #define U16PUT(p,v) (p)[0]=((v)>>8)&0xFF;(p)[1]=(v)&0xFF
15 #define U32PUT(p,v) (p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF
16 #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
18 static struct {
19 u32int m;
20 char *s;
21 } magics[] = {
22 ArenaPartMagic, "ArenaPartMagic",
23 ArenaHeadMagic, "ArenaHeadMagic",
24 ArenaMagic, "ArenaMagic",
25 ISectMagic, "ISectMagic",
26 BloomMagic, "BloomMagic",
27 };
29 static char*
30 fmtmagic(char *s, u32int m)
31 {
32 int i;
34 for(i=0; i<nelem(magics); i++)
35 if(magics[i].m == m)
36 return magics[i].s;
37 sprint(s, "0x%08ux", m);
38 return s;
39 }
41 u32int
42 unpackmagic(u8int *buf)
43 {
44 return U32GET(buf);
45 }
47 void
48 packmagic(u32int magic, u8int *buf)
49 {
50 U32PUT(buf, magic);
51 }
53 int
54 unpackarenapart(ArenaPart *ap, u8int *buf)
55 {
56 u8int *p;
57 u32int m;
58 char fbuf[20];
60 p = buf;
62 m = U32GET(p);
63 if(m != ArenaPartMagic){
64 seterr(ECorrupt, "arena set has wrong magic number: %s expected ArenaPartMagic (%lux)", fmtmagic(fbuf, m), ArenaPartMagic);
65 return -1;
66 }
67 p += U32Size;
68 ap->version = U32GET(p);
69 p += U32Size;
70 ap->blocksize = U32GET(p);
71 p += U32Size;
72 ap->arenabase = U32GET(p);
73 p += U32Size;
75 if(buf + ArenaPartSize != p)
76 sysfatal("unpackarenapart unpacked wrong amount");
78 return 0;
79 }
81 int
82 packarenapart(ArenaPart *ap, u8int *buf)
83 {
84 u8int *p;
86 p = buf;
88 U32PUT(p, ArenaPartMagic);
89 p += U32Size;
90 U32PUT(p, ap->version);
91 p += U32Size;
92 U32PUT(p, ap->blocksize);
93 p += U32Size;
94 U32PUT(p, ap->arenabase);
95 p += U32Size;
97 if(buf + ArenaPartSize != p)
98 sysfatal("packarenapart packed wrong amount");
100 return 0;
103 int
104 unpackarena(Arena *arena, u8int *buf)
106 int sz;
107 u8int *p;
108 u32int m;
109 char fbuf[20];
111 p = buf;
113 m = U32GET(p);
114 if(m != ArenaMagic){
115 seterr(ECorrupt, "arena has wrong magic number: %s expected ArenaMagic (%lux)", fmtmagic(fbuf, m), ArenaMagic);
116 return -1;
118 p += U32Size;
119 arena->version = U32GET(p);
120 p += U32Size;
121 namecp(arena->name, (char*)p);
122 p += ANameSize;
123 arena->diskstats.clumps = U32GET(p);
124 p += U32Size;
125 arena->diskstats.cclumps = U32GET(p);
126 p += U32Size;
127 arena->ctime = U32GET(p);
128 p += U32Size;
129 arena->wtime = U32GET(p);
130 p += U32Size;
131 if(arena->version == ArenaVersion5){
132 arena->clumpmagic = U32GET(p);
133 p += U32Size;
135 arena->diskstats.used = U64GET(p);
136 p += U64Size;
137 arena->diskstats.uncsize = U64GET(p);
138 p += U64Size;
139 arena->diskstats.sealed = U8GET(p);
140 p += U8Size;
142 arena->memstats = arena->diskstats;
144 switch(arena->version){
145 case ArenaVersion4:
146 sz = ArenaSize4;
147 arena->clumpmagic = _ClumpMagic;
148 break;
149 case ArenaVersion5:
150 sz = ArenaSize5;
151 break;
152 default:
153 seterr(ECorrupt, "arena has bad version number %d", arena->version);
154 return -1;
156 if(buf + sz != p)
157 sysfatal("unpackarena unpacked wrong amount");
159 return 0;
162 int
163 packarena(Arena *arena, u8int *buf)
165 int sz;
166 u8int *p;
167 u32int t32;
169 switch(arena->version){
170 case ArenaVersion4:
171 sz = ArenaSize4;
172 if(arena->clumpmagic != _ClumpMagic)
173 fprint(2, "warning: writing old arena tail loses clump magic 0x%lux != 0x%lux\n",
174 (ulong)arena->clumpmagic, (ulong)_ClumpMagic);
175 break;
176 case ArenaVersion5:
177 sz = ArenaSize5;
178 break;
179 default:
180 sysfatal("packarena unknown version %d", arena->version);
181 return -1;
184 p = buf;
186 U32PUT(p, ArenaMagic);
187 p += U32Size;
188 U32PUT(p, arena->version);
189 p += U32Size;
190 namecp((char*)p, arena->name);
191 p += ANameSize;
192 U32PUT(p, arena->diskstats.clumps);
193 p += U32Size;
194 U32PUT(p, arena->diskstats.cclumps);
195 p += U32Size;
196 U32PUT(p, arena->ctime);
197 p += U32Size;
198 U32PUT(p, arena->wtime);
199 p += U32Size;
200 if(arena->version == ArenaVersion5){
201 U32PUT(p, arena->clumpmagic);
202 p += U32Size;
204 U64PUT(p, arena->diskstats.used, t32);
205 p += U64Size;
206 U64PUT(p, arena->diskstats.uncsize, t32);
207 p += U64Size;
208 U8PUT(p, arena->diskstats.sealed);
209 p += U8Size;
211 if(buf + sz != p)
212 sysfatal("packarena packed wrong amount");
214 return 0;
217 int
218 unpackarenahead(ArenaHead *head, u8int *buf)
220 u8int *p;
221 u32int m;
222 int sz;
224 p = buf;
226 m = U32GET(p);
227 /* XXX check magic! */
229 p += U32Size;
230 head->version = U32GET(p);
231 p += U32Size;
232 namecp(head->name, (char*)p);
233 p += ANameSize;
234 head->blocksize = U32GET(p);
235 p += U32Size;
236 head->size = U64GET(p);
237 p += U64Size;
238 if(head->version == ArenaVersion5){
239 head->clumpmagic = U32GET(p);
240 p += U32Size;
243 switch(head->version){
244 case ArenaVersion4:
245 sz = ArenaHeadSize4;
246 head->clumpmagic = _ClumpMagic;
247 break;
248 case ArenaVersion5:
249 sz = ArenaHeadSize5;
250 break;
251 default:
252 seterr(ECorrupt, "arena head has unexpected version %d", head->version);
253 return -1;
256 if(buf + sz != p)
257 sysfatal("unpackarenahead unpacked wrong amount");
259 return 0;
262 int
263 packarenahead(ArenaHead *head, u8int *buf)
265 u8int *p;
266 int sz;
267 u32int t32;
269 switch(head->version){
270 case ArenaVersion4:
271 sz = ArenaHeadSize4;
272 if(head->clumpmagic != _ClumpMagic)
273 fprint(2, "warning: writing old arena header loses clump magic 0x%lux != 0x%lux\n",
274 (ulong)head->clumpmagic, (ulong)_ClumpMagic);
275 break;
276 case ArenaVersion5:
277 sz = ArenaHeadSize5;
278 break;
279 default:
280 sysfatal("packarenahead unknown version %d", head->version);
281 return -1;
284 p = buf;
286 U32PUT(p, ArenaHeadMagic);
287 p += U32Size;
288 U32PUT(p, head->version);
289 p += U32Size;
290 namecp((char*)p, head->name);
291 p += ANameSize;
292 U32PUT(p, head->blocksize);
293 p += U32Size;
294 U64PUT(p, head->size, t32);
295 p += U64Size;
296 if(head->version == ArenaVersion5){
297 U32PUT(p, head->clumpmagic);
298 p += U32Size;
300 if(buf + sz != p)
301 sysfatal("packarenahead packed wrong amount");
303 return 0;
306 static int
307 checkclump(Clump *w)
309 if(w->encoding == ClumpENone){
310 if(w->info.size != w->info.uncsize){
311 seterr(ECorrupt, "uncompressed wad size mismatch");
312 return -1;
314 }else if(w->encoding == ClumpECompress){
315 if(w->info.size >= w->info.uncsize){
316 seterr(ECorrupt, "compressed lump has inconsistent block sizes %d %d", w->info.size, w->info.uncsize);
317 return -1;
319 }else{
320 seterr(ECorrupt, "clump has illegal encoding");
321 return -1;
324 return 0;
327 int
328 unpackclump(Clump *c, u8int *buf, u32int cmagic)
330 u8int *p;
331 u32int magic;
333 p = buf;
334 magic = U32GET(p);
335 if(magic != cmagic){
336 seterr(ECorrupt, "clump has bad magic number=%#8.8ux != %#8.8ux", magic, cmagic);
337 return -1;
339 p += U32Size;
341 c->info.type = vtfromdisktype(U8GET(p));
342 p += U8Size;
343 c->info.size = U16GET(p);
344 p += U16Size;
345 c->info.uncsize = U16GET(p);
346 p += U16Size;
347 scorecp(c->info.score, p);
348 p += VtScoreSize;
350 c->encoding = U8GET(p);
351 p += U8Size;
352 c->creator = U32GET(p);
353 p += U32Size;
354 c->time = U32GET(p);
355 p += U32Size;
357 if(buf + ClumpSize != p)
358 sysfatal("unpackclump unpacked wrong amount");
360 return checkclump(c);
363 int
364 packclump(Clump *c, u8int *buf, u32int magic)
366 u8int *p;
368 p = buf;
369 U32PUT(p, magic);
370 p += U32Size;
372 U8PUT(p, vttodisktype(c->info.type));
373 p += U8Size;
374 U16PUT(p, c->info.size);
375 p += U16Size;
376 U16PUT(p, c->info.uncsize);
377 p += U16Size;
378 scorecp(p, c->info.score);
379 p += VtScoreSize;
381 U8PUT(p, c->encoding);
382 p += U8Size;
383 U32PUT(p, c->creator);
384 p += U32Size;
385 U32PUT(p, c->time);
386 p += U32Size;
388 if(buf + ClumpSize != p)
389 sysfatal("packclump packed wrong amount");
391 return checkclump(c);
394 void
395 unpackclumpinfo(ClumpInfo *ci, u8int *buf)
397 u8int *p;
399 p = buf;
400 ci->type = vtfromdisktype(U8GET(p));
401 p += U8Size;
402 ci->size = U16GET(p);
403 p += U16Size;
404 ci->uncsize = U16GET(p);
405 p += U16Size;
406 scorecp(ci->score, p);
407 p += VtScoreSize;
409 if(buf + ClumpInfoSize != p)
410 sysfatal("unpackclumpinfo unpacked wrong amount");
413 void
414 packclumpinfo(ClumpInfo *ci, u8int *buf)
416 u8int *p;
418 p = buf;
419 U8PUT(p, vttodisktype(ci->type));
420 p += U8Size;
421 U16PUT(p, ci->size);
422 p += U16Size;
423 U16PUT(p, ci->uncsize);
424 p += U16Size;
425 scorecp(p, ci->score);
426 p += VtScoreSize;
428 if(buf + ClumpInfoSize != p)
429 sysfatal("packclumpinfo packed wrong amount");
432 int
433 unpackisect(ISect *is, u8int *buf)
435 u8int *p;
436 u32int m;
437 char fbuf[20];
439 p = buf;
442 m = U32GET(p);
443 if(m != ISectMagic){
444 seterr(ECorrupt, "index section has wrong magic number: %s expected ISectMagic (%lux)",
445 fmtmagic(fbuf, m), ISectMagic);
446 return -1;
448 p += U32Size;
449 is->version = U32GET(p);
450 p += U32Size;
451 namecp(is->name, (char*)p);
452 p += ANameSize;
453 namecp(is->index, (char*)p);
454 p += ANameSize;
455 is->blocksize = U32GET(p);
456 p += U32Size;
457 is->blockbase = U32GET(p);
458 p += U32Size;
459 is->blocks = U32GET(p);
460 p += U32Size;
461 is->start = U32GET(p);
462 p += U32Size;
463 is->stop = U32GET(p);
464 p += U32Size;
465 if(buf + ISectSize1 != p)
466 sysfatal("unpackisect unpacked wrong amount");
467 is->bucketmagic = 0;
468 if(is->version == ISectVersion2){
469 is->bucketmagic = U32GET(p);
470 p += U32Size;
471 if(buf + ISectSize2 != p)
472 sysfatal("unpackisect unpacked wrong amount");
475 return 0;
478 int
479 packisect(ISect *is, u8int *buf)
481 u8int *p;
483 p = buf;
485 U32PUT(p, ISectMagic);
486 p += U32Size;
487 U32PUT(p, is->version);
488 p += U32Size;
489 namecp((char*)p, is->name);
490 p += ANameSize;
491 namecp((char*)p, is->index);
492 p += ANameSize;
493 U32PUT(p, is->blocksize);
494 p += U32Size;
495 U32PUT(p, is->blockbase);
496 p += U32Size;
497 U32PUT(p, is->blocks);
498 p += U32Size;
499 U32PUT(p, is->start);
500 p += U32Size;
501 U32PUT(p, is->stop);
502 p += U32Size;
503 if(buf + ISectSize1 != p)
504 sysfatal("packisect packed wrong amount");
505 if(is->version == ISectVersion2){
506 U32PUT(p, is->bucketmagic);
507 p += U32Size;
508 if(buf + ISectSize2 != p)
509 sysfatal("packisect packed wrong amount");
512 return 0;
515 void
516 unpackientry(IEntry *ie, u8int *buf)
518 u8int *p;
520 p = buf;
522 scorecp(ie->score, p);
523 p += VtScoreSize;
524 ie->wtime = U32GET(p);
525 p += U32Size;
526 ie->train = U16GET(p);
527 p += U16Size;
528 ie->ia.addr = U64GET(p);
529 if(ie->ia.addr>>56) print("%.8H => %llux\n", p, ie->ia.addr);
530 p += U64Size;
531 ie->ia.size = U16GET(p);
532 p += U16Size;
533 if(p - buf != IEntryTypeOff)
534 sysfatal("unpackientry bad IEntryTypeOff amount");
535 ie->ia.type = vtfromdisktype(U8GET(p));
536 p += U8Size;
537 ie->ia.blocks = U8GET(p);
538 p += U8Size;
540 if(p - buf != IEntrySize)
541 sysfatal("unpackientry unpacked wrong amount");
544 void
545 packientry(IEntry *ie, u8int *buf)
547 u32int t32;
548 u8int *p;
550 p = buf;
552 scorecp(p, ie->score);
553 p += VtScoreSize;
554 U32PUT(p, ie->wtime);
555 p += U32Size;
556 U16PUT(p, ie->train);
557 p += U16Size;
558 U64PUT(p, ie->ia.addr, t32);
559 p += U64Size;
560 U16PUT(p, ie->ia.size);
561 p += U16Size;
562 U8PUT(p, vttodisktype(ie->ia.type));
563 p += U8Size;
564 U8PUT(p, ie->ia.blocks);
565 p += U8Size;
567 if(p - buf != IEntrySize)
568 sysfatal("packientry packed wrong amount");
571 void
572 unpackibucket(IBucket *b, u8int *buf, u32int magic)
574 b->n = U16GET(buf);
575 b->data = buf + IBucketSize;
576 if(magic && magic != U32GET(buf+U16Size))
577 b->n = 0;
580 void
581 packibucket(IBucket *b, u8int *buf, u32int magic)
583 U16PUT(buf, b->n);
584 U32PUT(buf+U16Size, magic);
587 void
588 packbloomhead(Bloom *b, u8int *buf)
590 u8int *p;
592 p = buf;
593 U32PUT(p, BloomMagic);
594 U32PUT(p+4, BloomVersion);
595 U32PUT(p+8, b->nhash);
596 U32PUT(p+12, b->size);
599 int
600 unpackbloomhead(Bloom *b, u8int *buf)
602 u8int *p;
603 u32int m;
604 char fbuf[20];
606 p = buf;
608 m = U32GET(p);
609 if(m != BloomMagic){
610 seterr(ECorrupt, "bloom filter has wrong magic number: %s expected BloomMagic (%lux)", fmtmagic(fbuf, m), (ulong)BloomMagic);
611 return -1;
613 p += U32Size;
615 m = U32GET(p);
616 if(m != BloomVersion){
617 seterr(ECorrupt, "bloom filter has wrong version %ud expected %ud", (uint)m, (uint)BloomVersion);
618 return -1;
620 p += U32Size;
622 b->nhash = U32GET(p);
623 p += U32Size;
625 b->size = U32GET(p);
626 p += U32Size;
628 if(buf + BloomHeadSize != p)
629 sysfatal("unpackarena unpacked wrong amount");
631 return 0;