1368c31abSDavid du Colombier #include "stdinc.h"
2368c31abSDavid du Colombier #include "dat.h"
3368c31abSDavid du Colombier #include "fns.h"
4368c31abSDavid du Colombier
5368c31abSDavid du Colombier /*
6368c31abSDavid du Colombier * disk structure conversion routines
7368c31abSDavid du Colombier */
8368c31abSDavid du Colombier #define U8GET(p) ((p)[0])
9368c31abSDavid du Colombier #define U16GET(p) (((p)[0]<<8)|(p)[1])
10368c31abSDavid du Colombier #define U32GET(p) ((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
11368c31abSDavid du Colombier #define U64GET(p) (((u64int)U32GET(p)<<32)|(u64int)U32GET((p)+4))
12368c31abSDavid du Colombier
13368c31abSDavid du Colombier #define U8PUT(p,v) (p)[0]=(v)&0xFF
14368c31abSDavid du Colombier #define U16PUT(p,v) (p)[0]=((v)>>8)&0xFF;(p)[1]=(v)&0xFF
15368c31abSDavid du Colombier #define U32PUT(p,v) (p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF
16368c31abSDavid du Colombier #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
17368c31abSDavid du Colombier
18*b8a11165SDavid du Colombier int debugarena = -1; /* hack to improve error reporting */
19*b8a11165SDavid du Colombier
20368c31abSDavid du Colombier static struct {
21368c31abSDavid du Colombier u32int m;
22368c31abSDavid du Colombier char *s;
23368c31abSDavid du Colombier } magics[] = {
24368c31abSDavid du Colombier ArenaPartMagic, "ArenaPartMagic",
25368c31abSDavid du Colombier ArenaHeadMagic, "ArenaHeadMagic",
26368c31abSDavid du Colombier ArenaMagic, "ArenaMagic",
27368c31abSDavid du Colombier ISectMagic, "ISectMagic",
28368c31abSDavid du Colombier BloomMagic, "BloomMagic",
29368c31abSDavid du Colombier };
30368c31abSDavid du Colombier
31368c31abSDavid du Colombier static char*
fmtmagic(char * s,u32int m)32368c31abSDavid du Colombier fmtmagic(char *s, u32int m)
33368c31abSDavid du Colombier {
34368c31abSDavid du Colombier int i;
35368c31abSDavid du Colombier
36368c31abSDavid du Colombier for(i=0; i<nelem(magics); i++)
37368c31abSDavid du Colombier if(magics[i].m == m)
38368c31abSDavid du Colombier return magics[i].s;
39368c31abSDavid du Colombier sprint(s, "%#08ux", m);
40368c31abSDavid du Colombier return s;
41368c31abSDavid du Colombier }
42368c31abSDavid du Colombier
43368c31abSDavid du Colombier u32int
unpackmagic(u8int * buf)44368c31abSDavid du Colombier unpackmagic(u8int *buf)
45368c31abSDavid du Colombier {
46368c31abSDavid du Colombier return U32GET(buf);
47368c31abSDavid du Colombier }
48368c31abSDavid du Colombier
49368c31abSDavid du Colombier void
packmagic(u32int magic,u8int * buf)50368c31abSDavid du Colombier packmagic(u32int magic, u8int *buf)
51368c31abSDavid du Colombier {
52368c31abSDavid du Colombier U32PUT(buf, magic);
53368c31abSDavid du Colombier }
54368c31abSDavid du Colombier
55368c31abSDavid du Colombier int
unpackarenapart(ArenaPart * ap,u8int * buf)56368c31abSDavid du Colombier unpackarenapart(ArenaPart *ap, u8int *buf)
57368c31abSDavid du Colombier {
58368c31abSDavid du Colombier u8int *p;
59368c31abSDavid du Colombier u32int m;
60368c31abSDavid du Colombier char fbuf[20];
61368c31abSDavid du Colombier
62368c31abSDavid du Colombier p = buf;
63368c31abSDavid du Colombier
64368c31abSDavid du Colombier m = U32GET(p);
65368c31abSDavid du Colombier if(m != ArenaPartMagic){
66368c31abSDavid du Colombier seterr(ECorrupt, "arena set has wrong magic number: %s expected ArenaPartMagic (%#lux)", fmtmagic(fbuf, m), ArenaPartMagic);
67368c31abSDavid du Colombier return -1;
68368c31abSDavid du Colombier }
69368c31abSDavid du Colombier p += U32Size;
70368c31abSDavid du Colombier ap->version = U32GET(p);
71368c31abSDavid du Colombier p += U32Size;
72368c31abSDavid du Colombier ap->blocksize = U32GET(p);
73368c31abSDavid du Colombier p += U32Size;
74368c31abSDavid du Colombier ap->arenabase = U32GET(p);
75368c31abSDavid du Colombier p += U32Size;
76368c31abSDavid du Colombier
77368c31abSDavid du Colombier if(buf + ArenaPartSize != p)
78368c31abSDavid du Colombier sysfatal("unpackarenapart unpacked wrong amount");
79368c31abSDavid du Colombier
80368c31abSDavid du Colombier return 0;
81368c31abSDavid du Colombier }
82368c31abSDavid du Colombier
83368c31abSDavid du Colombier int
packarenapart(ArenaPart * ap,u8int * buf)84368c31abSDavid du Colombier packarenapart(ArenaPart *ap, u8int *buf)
85368c31abSDavid du Colombier {
86368c31abSDavid du Colombier u8int *p;
87368c31abSDavid du Colombier
88368c31abSDavid du Colombier p = buf;
89368c31abSDavid du Colombier
90368c31abSDavid du Colombier U32PUT(p, ArenaPartMagic);
91368c31abSDavid du Colombier p += U32Size;
92368c31abSDavid du Colombier U32PUT(p, ap->version);
93368c31abSDavid du Colombier p += U32Size;
94368c31abSDavid du Colombier U32PUT(p, ap->blocksize);
95368c31abSDavid du Colombier p += U32Size;
96368c31abSDavid du Colombier U32PUT(p, ap->arenabase);
97368c31abSDavid du Colombier p += U32Size;
98368c31abSDavid du Colombier
99368c31abSDavid du Colombier if(buf + ArenaPartSize != p)
100368c31abSDavid du Colombier sysfatal("packarenapart packed wrong amount");
101368c31abSDavid du Colombier
102368c31abSDavid du Colombier return 0;
103368c31abSDavid du Colombier }
104368c31abSDavid du Colombier
105368c31abSDavid du Colombier int
unpackarena(Arena * arena,u8int * buf)106368c31abSDavid du Colombier unpackarena(Arena *arena, u8int *buf)
107368c31abSDavid du Colombier {
108368c31abSDavid du Colombier int sz;
109368c31abSDavid du Colombier u8int *p;
110368c31abSDavid du Colombier u32int m;
111368c31abSDavid du Colombier char fbuf[20];
112368c31abSDavid du Colombier
113368c31abSDavid du Colombier p = buf;
114368c31abSDavid du Colombier
115368c31abSDavid du Colombier m = U32GET(p);
116368c31abSDavid du Colombier if(m != ArenaMagic){
117*b8a11165SDavid du Colombier seterr(ECorrupt, "arena %d has wrong magic number: %s "
118*b8a11165SDavid du Colombier "expected ArenaMagic (%#lux)", debugarena,
119*b8a11165SDavid du Colombier fmtmagic(fbuf, m), ArenaMagic);
120368c31abSDavid du Colombier return -1;
121368c31abSDavid du Colombier }
122368c31abSDavid du Colombier p += U32Size;
123368c31abSDavid du Colombier arena->version = U32GET(p);
124368c31abSDavid du Colombier p += U32Size;
125368c31abSDavid du Colombier namecp(arena->name, (char*)p);
126368c31abSDavid du Colombier p += ANameSize;
127368c31abSDavid du Colombier arena->diskstats.clumps = U32GET(p);
128368c31abSDavid du Colombier p += U32Size;
129368c31abSDavid du Colombier arena->diskstats.cclumps = U32GET(p);
130368c31abSDavid du Colombier p += U32Size;
131368c31abSDavid du Colombier arena->ctime = U32GET(p);
132368c31abSDavid du Colombier p += U32Size;
133368c31abSDavid du Colombier arena->wtime = U32GET(p);
134368c31abSDavid du Colombier p += U32Size;
135368c31abSDavid du Colombier if(arena->version == ArenaVersion5){
136368c31abSDavid du Colombier arena->clumpmagic = U32GET(p);
137368c31abSDavid du Colombier p += U32Size;
138368c31abSDavid du Colombier }
139368c31abSDavid du Colombier arena->diskstats.used = U64GET(p);
140368c31abSDavid du Colombier p += U64Size;
141368c31abSDavid du Colombier arena->diskstats.uncsize = U64GET(p);
142368c31abSDavid du Colombier p += U64Size;
143368c31abSDavid du Colombier arena->diskstats.sealed = U8GET(p);
144368c31abSDavid du Colombier p += U8Size;
145368c31abSDavid du Colombier switch(arena->version){
146368c31abSDavid du Colombier case ArenaVersion4:
147368c31abSDavid du Colombier sz = ArenaSize4;
148368c31abSDavid du Colombier arena->clumpmagic = _ClumpMagic;
149368c31abSDavid du Colombier break;
150368c31abSDavid du Colombier case ArenaVersion5:
151368c31abSDavid du Colombier sz = ArenaSize5;
152368c31abSDavid du Colombier break;
153368c31abSDavid du Colombier default:
154368c31abSDavid du Colombier seterr(ECorrupt, "arena has bad version number %d", arena->version);
155368c31abSDavid du Colombier return -1;
156368c31abSDavid du Colombier }
157368c31abSDavid du Colombier /*
158368c31abSDavid du Colombier * Additional fields for the memstats version of the stats.
159368c31abSDavid du Colombier * Diskstats reflects what is committed to the index.
160368c31abSDavid du Colombier * Memstats reflects what is in the arena. Originally intended
161368c31abSDavid du Colombier * this to be a version 5 extension, but might as well use for
162368c31abSDavid du Colombier * all the existing version 4 arenas too.
163368c31abSDavid du Colombier *
164368c31abSDavid du Colombier * To maintain backwards compatibility with existing venti
165368c31abSDavid du Colombier * installations using the older format, we define that if
166368c31abSDavid du Colombier * memstats == diskstats, then the extension fields are not
167368c31abSDavid du Colombier * included (see packarena below). That is, only partially
168368c31abSDavid du Colombier * indexed arenas have these fields. Fully indexed arenas
169368c31abSDavid du Colombier * (in particular, sealed arenas) do not.
170368c31abSDavid du Colombier */
171368c31abSDavid du Colombier if(U8GET(p) == 1){
172368c31abSDavid du Colombier sz += ArenaSize5a-ArenaSize5;
173368c31abSDavid du Colombier p += U8Size;
174368c31abSDavid du Colombier arena->memstats.clumps = U32GET(p);
175368c31abSDavid du Colombier p += U32Size;
176368c31abSDavid du Colombier arena->memstats.cclumps = U32GET(p);
177368c31abSDavid du Colombier p += U32Size;
178368c31abSDavid du Colombier arena->memstats.used = U64GET(p);
179368c31abSDavid du Colombier p += U64Size;
180368c31abSDavid du Colombier arena->memstats.uncsize = U64GET(p);
181368c31abSDavid du Colombier p += U64Size;
182368c31abSDavid du Colombier arena->memstats.sealed = U8GET(p);
183368c31abSDavid du Colombier p += U8Size;
18461f42feeSDavid du Colombier
18561f42feeSDavid du Colombier /*
18661f42feeSDavid du Colombier * 2008/4/2
18761f42feeSDavid du Colombier * Packarena (below) used to have a bug in which it would
18861f42feeSDavid du Colombier * not zero out any existing extension fields when writing
18961f42feeSDavid du Colombier * the arena metadata. This would manifest itself as arenas
19061f42feeSDavid du Colombier * with arena->diskstats.sealed == 1 but arena->memstats.sealed == 0
19161f42feeSDavid du Colombier * after a server restart. Because arena->memstats.sealed wouldn't
19261f42feeSDavid du Colombier * be set, the server might try to fit another block into the arena
19361f42feeSDavid du Colombier * (and succeed), violating the append-only structure of the log
19461f42feeSDavid du Colombier * and invalidating any already-computed seal on the arena.
19561f42feeSDavid du Colombier *
19661f42feeSDavid du Colombier * It might end up that other fields in arena->memstats end up
19761f42feeSDavid du Colombier * behind arena->diskstats too, but that would be considerably
19861f42feeSDavid du Colombier * more rare, and the bug is fixed now. The case we need to
19961f42feeSDavid du Colombier * handle is just the sealed mismatch.
20061f42feeSDavid du Colombier *
20161f42feeSDavid du Colombier * If we encounter such a bogus arena, fix the sealed field.
20261f42feeSDavid du Colombier */
20361f42feeSDavid du Colombier if(arena->diskstats.sealed)
20461f42feeSDavid du Colombier arena->memstats.sealed = 1;
205368c31abSDavid du Colombier }else
206368c31abSDavid du Colombier arena->memstats = arena->diskstats;
207368c31abSDavid du Colombier if(buf + sz != p)
208368c31abSDavid du Colombier sysfatal("unpackarena unpacked wrong amount");
209368c31abSDavid du Colombier
210368c31abSDavid du Colombier return 0;
211368c31abSDavid du Colombier }
212368c31abSDavid du Colombier
213368c31abSDavid du Colombier int
packarena(Arena * arena,u8int * buf)214368c31abSDavid du Colombier packarena(Arena *arena, u8int *buf)
215368c31abSDavid du Colombier {
216368c31abSDavid du Colombier return _packarena(arena, buf, 0);
217368c31abSDavid du Colombier }
218368c31abSDavid du Colombier
219368c31abSDavid du Colombier int
_packarena(Arena * arena,u8int * buf,int forceext)220368c31abSDavid du Colombier _packarena(Arena *arena, u8int *buf, int forceext)
221368c31abSDavid du Colombier {
222368c31abSDavid du Colombier int sz;
223368c31abSDavid du Colombier u8int *p;
224368c31abSDavid du Colombier u32int t32;
225368c31abSDavid du Colombier
226368c31abSDavid du Colombier switch(arena->version){
227368c31abSDavid du Colombier case ArenaVersion4:
228368c31abSDavid du Colombier sz = ArenaSize4;
229368c31abSDavid du Colombier if(arena->clumpmagic != _ClumpMagic)
230368c31abSDavid du Colombier fprint(2, "warning: writing old arena tail loses clump magic 0x%lux != 0x%lux\n",
231368c31abSDavid du Colombier (ulong)arena->clumpmagic, (ulong)_ClumpMagic);
232368c31abSDavid du Colombier break;
233368c31abSDavid du Colombier case ArenaVersion5:
234368c31abSDavid du Colombier sz = ArenaSize5;
235368c31abSDavid du Colombier break;
236368c31abSDavid du Colombier default:
237368c31abSDavid du Colombier sysfatal("packarena unknown version %d", arena->version);
238368c31abSDavid du Colombier return -1;
239368c31abSDavid du Colombier }
240368c31abSDavid du Colombier
241368c31abSDavid du Colombier p = buf;
242368c31abSDavid du Colombier
243368c31abSDavid du Colombier U32PUT(p, ArenaMagic);
244368c31abSDavid du Colombier p += U32Size;
245368c31abSDavid du Colombier U32PUT(p, arena->version);
246368c31abSDavid du Colombier p += U32Size;
247368c31abSDavid du Colombier namecp((char*)p, arena->name);
248368c31abSDavid du Colombier p += ANameSize;
249368c31abSDavid du Colombier U32PUT(p, arena->diskstats.clumps);
250368c31abSDavid du Colombier p += U32Size;
251368c31abSDavid du Colombier U32PUT(p, arena->diskstats.cclumps);
252368c31abSDavid du Colombier p += U32Size;
253368c31abSDavid du Colombier U32PUT(p, arena->ctime);
254368c31abSDavid du Colombier p += U32Size;
255368c31abSDavid du Colombier U32PUT(p, arena->wtime);
256368c31abSDavid du Colombier p += U32Size;
257368c31abSDavid du Colombier if(arena->version == ArenaVersion5){
258368c31abSDavid du Colombier U32PUT(p, arena->clumpmagic);
259368c31abSDavid du Colombier p += U32Size;
260368c31abSDavid du Colombier }
261368c31abSDavid du Colombier U64PUT(p, arena->diskstats.used, t32);
262368c31abSDavid du Colombier p += U64Size;
263368c31abSDavid du Colombier U64PUT(p, arena->diskstats.uncsize, t32);
264368c31abSDavid du Colombier p += U64Size;
265368c31abSDavid du Colombier U8PUT(p, arena->diskstats.sealed);
266368c31abSDavid du Colombier p += U8Size;
267368c31abSDavid du Colombier
268368c31abSDavid du Colombier /*
269368c31abSDavid du Colombier * Extension fields; see above.
270368c31abSDavid du Colombier */
271368c31abSDavid du Colombier if(forceext
272368c31abSDavid du Colombier || arena->memstats.clumps != arena->diskstats.clumps
273368c31abSDavid du Colombier || arena->memstats.cclumps != arena->diskstats.cclumps
274368c31abSDavid du Colombier || arena->memstats.used != arena->diskstats.used
275368c31abSDavid du Colombier || arena->memstats.uncsize != arena->diskstats.uncsize
276368c31abSDavid du Colombier || arena->memstats.sealed != arena->diskstats.sealed){
277368c31abSDavid du Colombier sz += ArenaSize5a - ArenaSize5;
278368c31abSDavid du Colombier U8PUT(p, 1);
279368c31abSDavid du Colombier p += U8Size;
280368c31abSDavid du Colombier U32PUT(p, arena->memstats.clumps);
281368c31abSDavid du Colombier p += U32Size;
282368c31abSDavid du Colombier U32PUT(p, arena->memstats.cclumps);
283368c31abSDavid du Colombier p += U32Size;
284368c31abSDavid du Colombier U64PUT(p, arena->memstats.used, t32);
285368c31abSDavid du Colombier p += U64Size;
286368c31abSDavid du Colombier U64PUT(p, arena->memstats.uncsize, t32);
287368c31abSDavid du Colombier p += U64Size;
288368c31abSDavid du Colombier U8PUT(p, arena->memstats.sealed);
289368c31abSDavid du Colombier p += U8Size;
29061f42feeSDavid du Colombier }else{
29161f42feeSDavid du Colombier /* Clear any extension fields already on disk. */
29261f42feeSDavid du Colombier memset(p, 0, ArenaSize5a - ArenaSize5);
29361f42feeSDavid du Colombier p += ArenaSize5a - ArenaSize5;
29461f42feeSDavid du Colombier sz += ArenaSize5a - ArenaSize5;
295368c31abSDavid du Colombier }
296368c31abSDavid du Colombier
297368c31abSDavid du Colombier if(buf + sz != p)
298368c31abSDavid du Colombier sysfatal("packarena packed wrong amount");
299368c31abSDavid du Colombier
300368c31abSDavid du Colombier return 0;
301368c31abSDavid du Colombier }
302368c31abSDavid du Colombier
303368c31abSDavid du Colombier int
unpackarenahead(ArenaHead * head,u8int * buf)304368c31abSDavid du Colombier unpackarenahead(ArenaHead *head, u8int *buf)
305368c31abSDavid du Colombier {
306368c31abSDavid du Colombier u8int *p;
307368c31abSDavid du Colombier u32int m;
308368c31abSDavid du Colombier int sz;
309368c31abSDavid du Colombier char fbuf[20];
310368c31abSDavid du Colombier
311368c31abSDavid du Colombier p = buf;
312368c31abSDavid du Colombier
313368c31abSDavid du Colombier m = U32GET(p);
314368c31abSDavid du Colombier if(m != ArenaHeadMagic){
315*b8a11165SDavid du Colombier seterr(ECorrupt, "arena %d head has wrong magic number: %s "
316*b8a11165SDavid du Colombier "expected ArenaHeadMagic (%#lux)", debugarena,
317*b8a11165SDavid du Colombier fmtmagic(fbuf, m), ArenaHeadMagic);
318368c31abSDavid du Colombier return -1;
319368c31abSDavid du Colombier }
320368c31abSDavid du Colombier
321368c31abSDavid du Colombier p += U32Size;
322368c31abSDavid du Colombier head->version = U32GET(p);
323368c31abSDavid du Colombier p += U32Size;
324368c31abSDavid du Colombier namecp(head->name, (char*)p);
325368c31abSDavid du Colombier p += ANameSize;
326368c31abSDavid du Colombier head->blocksize = U32GET(p);
327368c31abSDavid du Colombier p += U32Size;
328368c31abSDavid du Colombier head->size = U64GET(p);
329368c31abSDavid du Colombier p += U64Size;
330368c31abSDavid du Colombier if(head->version == ArenaVersion5){
331368c31abSDavid du Colombier head->clumpmagic = U32GET(p);
332368c31abSDavid du Colombier p += U32Size;
333368c31abSDavid du Colombier }
334368c31abSDavid du Colombier
335368c31abSDavid du Colombier switch(head->version){
336368c31abSDavid du Colombier case ArenaVersion4:
337368c31abSDavid du Colombier sz = ArenaHeadSize4;
338368c31abSDavid du Colombier head->clumpmagic = _ClumpMagic;
339368c31abSDavid du Colombier break;
340368c31abSDavid du Colombier case ArenaVersion5:
341368c31abSDavid du Colombier sz = ArenaHeadSize5;
342368c31abSDavid du Colombier break;
343368c31abSDavid du Colombier default:
344368c31abSDavid du Colombier seterr(ECorrupt, "arena head has unexpected version %d", head->version);
345368c31abSDavid du Colombier return -1;
346368c31abSDavid du Colombier }
347368c31abSDavid du Colombier
348368c31abSDavid du Colombier if(buf + sz != p)
349368c31abSDavid du Colombier sysfatal("unpackarenahead unpacked wrong amount");
350368c31abSDavid du Colombier
351368c31abSDavid du Colombier return 0;
352368c31abSDavid du Colombier }
353368c31abSDavid du Colombier
354368c31abSDavid du Colombier int
packarenahead(ArenaHead * head,u8int * buf)355368c31abSDavid du Colombier packarenahead(ArenaHead *head, u8int *buf)
356368c31abSDavid du Colombier {
357368c31abSDavid du Colombier u8int *p;
358368c31abSDavid du Colombier int sz;
359368c31abSDavid du Colombier u32int t32;
360368c31abSDavid du Colombier
361368c31abSDavid du Colombier switch(head->version){
362368c31abSDavid du Colombier case ArenaVersion4:
363368c31abSDavid du Colombier sz = ArenaHeadSize4;
364368c31abSDavid du Colombier if(head->clumpmagic != _ClumpMagic)
365368c31abSDavid du Colombier fprint(2, "warning: writing old arena header loses clump magic 0x%lux != 0x%lux\n",
366368c31abSDavid du Colombier (ulong)head->clumpmagic, (ulong)_ClumpMagic);
367368c31abSDavid du Colombier break;
368368c31abSDavid du Colombier case ArenaVersion5:
369368c31abSDavid du Colombier sz = ArenaHeadSize5;
370368c31abSDavid du Colombier break;
371368c31abSDavid du Colombier default:
372368c31abSDavid du Colombier sysfatal("packarenahead unknown version %d", head->version);
373368c31abSDavid du Colombier return -1;
374368c31abSDavid du Colombier }
375368c31abSDavid du Colombier
376368c31abSDavid du Colombier p = buf;
377368c31abSDavid du Colombier
378368c31abSDavid du Colombier U32PUT(p, ArenaHeadMagic);
379368c31abSDavid du Colombier p += U32Size;
380368c31abSDavid du Colombier U32PUT(p, head->version);
381368c31abSDavid du Colombier p += U32Size;
382368c31abSDavid du Colombier namecp((char*)p, head->name);
383368c31abSDavid du Colombier p += ANameSize;
384368c31abSDavid du Colombier U32PUT(p, head->blocksize);
385368c31abSDavid du Colombier p += U32Size;
386368c31abSDavid du Colombier U64PUT(p, head->size, t32);
387368c31abSDavid du Colombier p += U64Size;
388368c31abSDavid du Colombier if(head->version == ArenaVersion5){
389368c31abSDavid du Colombier U32PUT(p, head->clumpmagic);
390368c31abSDavid du Colombier p += U32Size;
391368c31abSDavid du Colombier }
392368c31abSDavid du Colombier if(buf + sz != p)
393368c31abSDavid du Colombier sysfatal("packarenahead packed wrong amount");
394368c31abSDavid du Colombier
395368c31abSDavid du Colombier return 0;
396368c31abSDavid du Colombier }
397368c31abSDavid du Colombier
398368c31abSDavid du Colombier static int
checkclump(Clump * w)399368c31abSDavid du Colombier checkclump(Clump *w)
400368c31abSDavid du Colombier {
401368c31abSDavid du Colombier if(w->encoding == ClumpENone){
402368c31abSDavid du Colombier if(w->info.size != w->info.uncsize){
403368c31abSDavid du Colombier seterr(ECorrupt, "uncompressed wad size mismatch");
404368c31abSDavid du Colombier return -1;
405368c31abSDavid du Colombier }
406368c31abSDavid du Colombier }else if(w->encoding == ClumpECompress){
407368c31abSDavid du Colombier if(w->info.size >= w->info.uncsize){
408368c31abSDavid du Colombier seterr(ECorrupt, "compressed lump has inconsistent block sizes %d %d", w->info.size, w->info.uncsize);
409368c31abSDavid du Colombier return -1;
410368c31abSDavid du Colombier }
411368c31abSDavid du Colombier }else{
412368c31abSDavid du Colombier seterr(ECorrupt, "clump has illegal encoding");
413368c31abSDavid du Colombier return -1;
414368c31abSDavid du Colombier }
415368c31abSDavid du Colombier
416368c31abSDavid du Colombier return 0;
417368c31abSDavid du Colombier }
418368c31abSDavid du Colombier
419368c31abSDavid du Colombier int
unpackclump(Clump * c,u8int * buf,u32int cmagic)420368c31abSDavid du Colombier unpackclump(Clump *c, u8int *buf, u32int cmagic)
421368c31abSDavid du Colombier {
422368c31abSDavid du Colombier u8int *p;
423368c31abSDavid du Colombier u32int magic;
424368c31abSDavid du Colombier
425368c31abSDavid du Colombier p = buf;
426368c31abSDavid du Colombier magic = U32GET(p);
427368c31abSDavid du Colombier if(magic != cmagic){
428368c31abSDavid du Colombier seterr(ECorrupt, "clump has bad magic number=%#8.8ux != %#8.8ux", magic, cmagic);
429368c31abSDavid du Colombier return -1;
430368c31abSDavid du Colombier }
431368c31abSDavid du Colombier p += U32Size;
432368c31abSDavid du Colombier
433368c31abSDavid du Colombier c->info.type = vtfromdisktype(U8GET(p));
434368c31abSDavid du Colombier p += U8Size;
435368c31abSDavid du Colombier c->info.size = U16GET(p);
436368c31abSDavid du Colombier p += U16Size;
437368c31abSDavid du Colombier c->info.uncsize = U16GET(p);
438368c31abSDavid du Colombier p += U16Size;
439368c31abSDavid du Colombier scorecp(c->info.score, p);
440368c31abSDavid du Colombier p += VtScoreSize;
441368c31abSDavid du Colombier
442368c31abSDavid du Colombier c->encoding = U8GET(p);
443368c31abSDavid du Colombier p += U8Size;
444368c31abSDavid du Colombier c->creator = U32GET(p);
445368c31abSDavid du Colombier p += U32Size;
446368c31abSDavid du Colombier c->time = U32GET(p);
447368c31abSDavid du Colombier p += U32Size;
448368c31abSDavid du Colombier
449368c31abSDavid du Colombier if(buf + ClumpSize != p)
450368c31abSDavid du Colombier sysfatal("unpackclump unpacked wrong amount");
451368c31abSDavid du Colombier
452368c31abSDavid du Colombier return checkclump(c);
453368c31abSDavid du Colombier }
454368c31abSDavid du Colombier
455368c31abSDavid du Colombier int
packclump(Clump * c,u8int * buf,u32int magic)456368c31abSDavid du Colombier packclump(Clump *c, u8int *buf, u32int magic)
457368c31abSDavid du Colombier {
458368c31abSDavid du Colombier u8int *p;
459368c31abSDavid du Colombier
460368c31abSDavid du Colombier p = buf;
461368c31abSDavid du Colombier U32PUT(p, magic);
462368c31abSDavid du Colombier p += U32Size;
463368c31abSDavid du Colombier
464368c31abSDavid du Colombier U8PUT(p, vttodisktype(c->info.type));
465368c31abSDavid du Colombier p += U8Size;
466368c31abSDavid du Colombier U16PUT(p, c->info.size);
467368c31abSDavid du Colombier p += U16Size;
468368c31abSDavid du Colombier U16PUT(p, c->info.uncsize);
469368c31abSDavid du Colombier p += U16Size;
470368c31abSDavid du Colombier scorecp(p, c->info.score);
471368c31abSDavid du Colombier p += VtScoreSize;
472368c31abSDavid du Colombier
473368c31abSDavid du Colombier U8PUT(p, c->encoding);
474368c31abSDavid du Colombier p += U8Size;
475368c31abSDavid du Colombier U32PUT(p, c->creator);
476368c31abSDavid du Colombier p += U32Size;
477368c31abSDavid du Colombier U32PUT(p, c->time);
478368c31abSDavid du Colombier p += U32Size;
479368c31abSDavid du Colombier
480368c31abSDavid du Colombier if(buf + ClumpSize != p)
481368c31abSDavid du Colombier sysfatal("packclump packed wrong amount");
482368c31abSDavid du Colombier
483368c31abSDavid du Colombier return checkclump(c);
484368c31abSDavid du Colombier }
485368c31abSDavid du Colombier
486368c31abSDavid du Colombier void
unpackclumpinfo(ClumpInfo * ci,u8int * buf)487368c31abSDavid du Colombier unpackclumpinfo(ClumpInfo *ci, u8int *buf)
488368c31abSDavid du Colombier {
489368c31abSDavid du Colombier u8int *p;
490368c31abSDavid du Colombier
491368c31abSDavid du Colombier p = buf;
492368c31abSDavid du Colombier ci->type = vtfromdisktype(U8GET(p));
493368c31abSDavid du Colombier p += U8Size;
494368c31abSDavid du Colombier ci->size = U16GET(p);
495368c31abSDavid du Colombier p += U16Size;
496368c31abSDavid du Colombier ci->uncsize = U16GET(p);
497368c31abSDavid du Colombier p += U16Size;
498368c31abSDavid du Colombier scorecp(ci->score, p);
499368c31abSDavid du Colombier p += VtScoreSize;
500368c31abSDavid du Colombier
501368c31abSDavid du Colombier if(buf + ClumpInfoSize != p)
502368c31abSDavid du Colombier sysfatal("unpackclumpinfo unpacked wrong amount");
503368c31abSDavid du Colombier }
504368c31abSDavid du Colombier
505368c31abSDavid du Colombier void
packclumpinfo(ClumpInfo * ci,u8int * buf)506368c31abSDavid du Colombier packclumpinfo(ClumpInfo *ci, u8int *buf)
507368c31abSDavid du Colombier {
508368c31abSDavid du Colombier u8int *p;
509368c31abSDavid du Colombier
510368c31abSDavid du Colombier p = buf;
511368c31abSDavid du Colombier U8PUT(p, vttodisktype(ci->type));
512368c31abSDavid du Colombier p += U8Size;
513368c31abSDavid du Colombier U16PUT(p, ci->size);
514368c31abSDavid du Colombier p += U16Size;
515368c31abSDavid du Colombier U16PUT(p, ci->uncsize);
516368c31abSDavid du Colombier p += U16Size;
517368c31abSDavid du Colombier scorecp(p, ci->score);
518368c31abSDavid du Colombier p += VtScoreSize;
519368c31abSDavid du Colombier
520368c31abSDavid du Colombier if(buf + ClumpInfoSize != p)
521368c31abSDavid du Colombier sysfatal("packclumpinfo packed wrong amount");
522368c31abSDavid du Colombier }
523368c31abSDavid du Colombier
524368c31abSDavid du Colombier int
unpackisect(ISect * is,u8int * buf)525368c31abSDavid du Colombier unpackisect(ISect *is, u8int *buf)
526368c31abSDavid du Colombier {
527368c31abSDavid du Colombier u8int *p;
528368c31abSDavid du Colombier u32int m;
529368c31abSDavid du Colombier char fbuf[20];
530368c31abSDavid du Colombier
531368c31abSDavid du Colombier p = buf;
532368c31abSDavid du Colombier
533368c31abSDavid du Colombier
534368c31abSDavid du Colombier m = U32GET(p);
535368c31abSDavid du Colombier if(m != ISectMagic){
536368c31abSDavid du Colombier seterr(ECorrupt, "index section has wrong magic number: %s expected ISectMagic (%#lux)",
537368c31abSDavid du Colombier fmtmagic(fbuf, m), ISectMagic);
538368c31abSDavid du Colombier return -1;
539368c31abSDavid du Colombier }
540368c31abSDavid du Colombier p += U32Size;
541368c31abSDavid du Colombier is->version = U32GET(p);
542368c31abSDavid du Colombier p += U32Size;
543368c31abSDavid du Colombier namecp(is->name, (char*)p);
544368c31abSDavid du Colombier p += ANameSize;
545368c31abSDavid du Colombier namecp(is->index, (char*)p);
546368c31abSDavid du Colombier p += ANameSize;
547368c31abSDavid du Colombier is->blocksize = U32GET(p);
548368c31abSDavid du Colombier p += U32Size;
549368c31abSDavid du Colombier is->blockbase = U32GET(p);
550368c31abSDavid du Colombier p += U32Size;
551368c31abSDavid du Colombier is->blocks = U32GET(p);
552368c31abSDavid du Colombier p += U32Size;
553368c31abSDavid du Colombier is->start = U32GET(p);
554368c31abSDavid du Colombier p += U32Size;
555368c31abSDavid du Colombier is->stop = U32GET(p);
556368c31abSDavid du Colombier p += U32Size;
557368c31abSDavid du Colombier if(buf + ISectSize1 != p)
558368c31abSDavid du Colombier sysfatal("unpackisect unpacked wrong amount");
559368c31abSDavid du Colombier is->bucketmagic = 0;
560368c31abSDavid du Colombier if(is->version == ISectVersion2){
561368c31abSDavid du Colombier is->bucketmagic = U32GET(p);
562368c31abSDavid du Colombier p += U32Size;
563368c31abSDavid du Colombier if(buf + ISectSize2 != p)
564368c31abSDavid du Colombier sysfatal("unpackisect unpacked wrong amount");
565368c31abSDavid du Colombier }
566368c31abSDavid du Colombier
567368c31abSDavid du Colombier return 0;
568368c31abSDavid du Colombier }
569368c31abSDavid du Colombier
570368c31abSDavid du Colombier int
packisect(ISect * is,u8int * buf)571368c31abSDavid du Colombier packisect(ISect *is, u8int *buf)
572368c31abSDavid du Colombier {
573368c31abSDavid du Colombier u8int *p;
574368c31abSDavid du Colombier
575368c31abSDavid du Colombier p = buf;
576368c31abSDavid du Colombier
577368c31abSDavid du Colombier U32PUT(p, ISectMagic);
578368c31abSDavid du Colombier p += U32Size;
579368c31abSDavid du Colombier U32PUT(p, is->version);
580368c31abSDavid du Colombier p += U32Size;
581368c31abSDavid du Colombier namecp((char*)p, is->name);
582368c31abSDavid du Colombier p += ANameSize;
583368c31abSDavid du Colombier namecp((char*)p, is->index);
584368c31abSDavid du Colombier p += ANameSize;
585368c31abSDavid du Colombier U32PUT(p, is->blocksize);
586368c31abSDavid du Colombier p += U32Size;
587368c31abSDavid du Colombier U32PUT(p, is->blockbase);
588368c31abSDavid du Colombier p += U32Size;
589368c31abSDavid du Colombier U32PUT(p, is->blocks);
590368c31abSDavid du Colombier p += U32Size;
591368c31abSDavid du Colombier U32PUT(p, is->start);
592368c31abSDavid du Colombier p += U32Size;
593368c31abSDavid du Colombier U32PUT(p, is->stop);
594368c31abSDavid du Colombier p += U32Size;
595368c31abSDavid du Colombier if(buf + ISectSize1 != p)
596368c31abSDavid du Colombier sysfatal("packisect packed wrong amount");
597368c31abSDavid du Colombier if(is->version == ISectVersion2){
598368c31abSDavid du Colombier U32PUT(p, is->bucketmagic);
599368c31abSDavid du Colombier p += U32Size;
600368c31abSDavid du Colombier if(buf + ISectSize2 != p)
601368c31abSDavid du Colombier sysfatal("packisect packed wrong amount");
602368c31abSDavid du Colombier }
603368c31abSDavid du Colombier
604368c31abSDavid du Colombier return 0;
605368c31abSDavid du Colombier }
606368c31abSDavid du Colombier
607368c31abSDavid du Colombier void
unpackientry(IEntry * ie,u8int * buf)608368c31abSDavid du Colombier unpackientry(IEntry *ie, u8int *buf)
609368c31abSDavid du Colombier {
610368c31abSDavid du Colombier u8int *p;
611368c31abSDavid du Colombier
612368c31abSDavid du Colombier p = buf;
613368c31abSDavid du Colombier
614368c31abSDavid du Colombier scorecp(ie->score, p);
615368c31abSDavid du Colombier p += VtScoreSize;
616f9e1cf08SDavid du Colombier /* ie->wtime = U32GET(p); */
617368c31abSDavid du Colombier p += U32Size;
618f9e1cf08SDavid du Colombier /* ie->train = U16GET(p); */
619368c31abSDavid du Colombier p += U16Size;
620368c31abSDavid du Colombier if(p - buf != IEntryAddrOff)
621368c31abSDavid du Colombier sysfatal("unpackentry bad IEntryAddrOff amount");
622368c31abSDavid du Colombier ie->ia.addr = U64GET(p);
623368c31abSDavid du Colombier if(ie->ia.addr>>56) print("%.8H => %llux\n", p, ie->ia.addr);
624368c31abSDavid du Colombier p += U64Size;
625368c31abSDavid du Colombier ie->ia.size = U16GET(p);
626368c31abSDavid du Colombier p += U16Size;
627368c31abSDavid du Colombier if(p - buf != IEntryTypeOff)
628368c31abSDavid du Colombier sysfatal("unpackientry bad IEntryTypeOff amount");
629368c31abSDavid du Colombier ie->ia.type = vtfromdisktype(U8GET(p));
630368c31abSDavid du Colombier p += U8Size;
631368c31abSDavid du Colombier ie->ia.blocks = U8GET(p);
632368c31abSDavid du Colombier p += U8Size;
633368c31abSDavid du Colombier
634368c31abSDavid du Colombier if(p - buf != IEntrySize)
635368c31abSDavid du Colombier sysfatal("unpackientry unpacked wrong amount");
636368c31abSDavid du Colombier }
637368c31abSDavid du Colombier
638368c31abSDavid du Colombier void
packientry(IEntry * ie,u8int * buf)639368c31abSDavid du Colombier packientry(IEntry *ie, u8int *buf)
640368c31abSDavid du Colombier {
641368c31abSDavid du Colombier u32int t32;
642368c31abSDavid du Colombier u8int *p;
643368c31abSDavid du Colombier
644368c31abSDavid du Colombier p = buf;
645368c31abSDavid du Colombier
646368c31abSDavid du Colombier scorecp(p, ie->score);
647368c31abSDavid du Colombier p += VtScoreSize;
648f9e1cf08SDavid du Colombier U32PUT(p, 0); /* wtime */
649368c31abSDavid du Colombier p += U32Size;
650f9e1cf08SDavid du Colombier U16PUT(p, 0); /* train */
651368c31abSDavid du Colombier p += U16Size;
652368c31abSDavid du Colombier U64PUT(p, ie->ia.addr, t32);
653368c31abSDavid du Colombier p += U64Size;
654368c31abSDavid du Colombier U16PUT(p, ie->ia.size);
655368c31abSDavid du Colombier p += U16Size;
656368c31abSDavid du Colombier U8PUT(p, vttodisktype(ie->ia.type));
657368c31abSDavid du Colombier p += U8Size;
658368c31abSDavid du Colombier U8PUT(p, ie->ia.blocks);
659368c31abSDavid du Colombier p += U8Size;
660368c31abSDavid du Colombier
661368c31abSDavid du Colombier if(p - buf != IEntrySize)
662368c31abSDavid du Colombier sysfatal("packientry packed wrong amount");
663368c31abSDavid du Colombier }
664368c31abSDavid du Colombier
665368c31abSDavid du Colombier void
unpackibucket(IBucket * b,u8int * buf,u32int magic)666368c31abSDavid du Colombier unpackibucket(IBucket *b, u8int *buf, u32int magic)
667368c31abSDavid du Colombier {
668368c31abSDavid du Colombier b->n = U16GET(buf);
669368c31abSDavid du Colombier b->data = buf + IBucketSize;
670368c31abSDavid du Colombier if(magic && magic != U32GET(buf+U16Size))
671368c31abSDavid du Colombier b->n = 0;
672368c31abSDavid du Colombier }
673368c31abSDavid du Colombier
674368c31abSDavid du Colombier void
packibucket(IBucket * b,u8int * buf,u32int magic)675368c31abSDavid du Colombier packibucket(IBucket *b, u8int *buf, u32int magic)
676368c31abSDavid du Colombier {
677368c31abSDavid du Colombier U16PUT(buf, b->n);
678368c31abSDavid du Colombier U32PUT(buf+U16Size, magic);
679368c31abSDavid du Colombier }
680368c31abSDavid du Colombier
681368c31abSDavid du Colombier void
packbloomhead(Bloom * b,u8int * buf)682368c31abSDavid du Colombier packbloomhead(Bloom *b, u8int *buf)
683368c31abSDavid du Colombier {
684368c31abSDavid du Colombier u8int *p;
685368c31abSDavid du Colombier
686368c31abSDavid du Colombier p = buf;
687368c31abSDavid du Colombier U32PUT(p, BloomMagic);
688368c31abSDavid du Colombier U32PUT(p+4, BloomVersion);
689368c31abSDavid du Colombier U32PUT(p+8, b->nhash);
690368c31abSDavid du Colombier U32PUT(p+12, b->size);
691368c31abSDavid du Colombier }
692368c31abSDavid du Colombier
693368c31abSDavid du Colombier int
unpackbloomhead(Bloom * b,u8int * buf)694368c31abSDavid du Colombier unpackbloomhead(Bloom *b, u8int *buf)
695368c31abSDavid du Colombier {
696368c31abSDavid du Colombier u8int *p;
697368c31abSDavid du Colombier u32int m;
698368c31abSDavid du Colombier char fbuf[20];
699368c31abSDavid du Colombier
700368c31abSDavid du Colombier p = buf;
701368c31abSDavid du Colombier
702368c31abSDavid du Colombier m = U32GET(p);
703368c31abSDavid du Colombier if(m != BloomMagic){
704368c31abSDavid du Colombier seterr(ECorrupt, "bloom filter has wrong magic number: %s expected BloomMagic (%#lux)", fmtmagic(fbuf, m), (ulong)BloomMagic);
705368c31abSDavid du Colombier return -1;
706368c31abSDavid du Colombier }
707368c31abSDavid du Colombier p += U32Size;
708368c31abSDavid du Colombier
709368c31abSDavid du Colombier m = U32GET(p);
710368c31abSDavid du Colombier if(m != BloomVersion){
711368c31abSDavid du Colombier seterr(ECorrupt, "bloom filter has wrong version %ud expected %ud", (uint)m, (uint)BloomVersion);
712368c31abSDavid du Colombier return -1;
713368c31abSDavid du Colombier }
714368c31abSDavid du Colombier p += U32Size;
715368c31abSDavid du Colombier
716368c31abSDavid du Colombier b->nhash = U32GET(p);
717368c31abSDavid du Colombier p += U32Size;
718368c31abSDavid du Colombier
719368c31abSDavid du Colombier b->size = U32GET(p);
720368c31abSDavid du Colombier p += U32Size;
721368c31abSDavid du Colombier if(b->size < BloomHeadSize || b->size > MaxBloomSize || (b->size&(b->size-1))){
722368c31abSDavid du Colombier seterr(ECorrupt, "bloom filter has invalid size %#lux", b->size);
723368c31abSDavid du Colombier return -1;
724368c31abSDavid du Colombier }
725368c31abSDavid du Colombier
726368c31abSDavid du Colombier if(buf + BloomHeadSize != p)
727368c31abSDavid du Colombier sysfatal("unpackarena unpacked wrong amount");
728368c31abSDavid du Colombier
729368c31abSDavid du Colombier return 0;
730368c31abSDavid du Colombier }
731