xref: /plan9-contrib/sys/src/cmd/fossil/pack.c (revision 5e96a66c77eb9140492ca53f857cbbf108e128ed)
1*5e96a66cSDavid du Colombier #include "stdinc.h"
2*5e96a66cSDavid du Colombier #include "dat.h"
3*5e96a66cSDavid du Colombier #include "fns.h"
4*5e96a66cSDavid du Colombier #include "error.h"
5*5e96a66cSDavid du Colombier 
6*5e96a66cSDavid du Colombier /*
7*5e96a66cSDavid du Colombier  * integer conversion routines
8*5e96a66cSDavid du Colombier  */
9*5e96a66cSDavid du Colombier #define	U8GET(p)	((p)[0])
10*5e96a66cSDavid du Colombier #define	U16GET(p)	(((p)[0]<<8)|(p)[1])
11*5e96a66cSDavid du Colombier #define	U32GET(p)	(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
12*5e96a66cSDavid du Colombier #define	U48GET(p)	(((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
13*5e96a66cSDavid du Colombier #define	U64GET(p)	(((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
14*5e96a66cSDavid du Colombier 
15*5e96a66cSDavid du Colombier #define	U8PUT(p,v)	(p)[0]=(v)
16*5e96a66cSDavid du Colombier #define	U16PUT(p,v)	(p)[0]=(v)>>8;(p)[1]=(v)
17*5e96a66cSDavid du Colombier #define	U32PUT(p,v)	(p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
18*5e96a66cSDavid du Colombier #define	U48PUT(p,v,t32)	t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
19*5e96a66cSDavid du Colombier #define	U64PUT(p,v,t32)	t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
20*5e96a66cSDavid du Colombier 
21*5e96a66cSDavid du Colombier void
22*5e96a66cSDavid du Colombier headerPack(Header *h, uchar *p)
23*5e96a66cSDavid du Colombier {
24*5e96a66cSDavid du Colombier 	memset(p, 0, HeaderSize);
25*5e96a66cSDavid du Colombier 	U32PUT(p, HeaderMagic);
26*5e96a66cSDavid du Colombier 	U16PUT(p+4, HeaderVersion);
27*5e96a66cSDavid du Colombier 	U16PUT(p+6, h->blockSize);
28*5e96a66cSDavid du Colombier 	U32PUT(p+8, h->super);
29*5e96a66cSDavid du Colombier 	U32PUT(p+12, h->label);
30*5e96a66cSDavid du Colombier 	U32PUT(p+16, h->data);
31*5e96a66cSDavid du Colombier 	U32PUT(p+20, h->end);
32*5e96a66cSDavid du Colombier }
33*5e96a66cSDavid du Colombier 
34*5e96a66cSDavid du Colombier int
35*5e96a66cSDavid du Colombier headerUnpack(Header *h, uchar *p)
36*5e96a66cSDavid du Colombier {
37*5e96a66cSDavid du Colombier 	if(U32GET(p) != HeaderMagic){
38*5e96a66cSDavid du Colombier 		vtSetError("vac header bad magic");
39*5e96a66cSDavid du Colombier 		return 0;
40*5e96a66cSDavid du Colombier 	}
41*5e96a66cSDavid du Colombier 	h->version = U16GET(p+4);
42*5e96a66cSDavid du Colombier 	if(h->version != HeaderVersion){
43*5e96a66cSDavid du Colombier 		vtSetError("vac header bad version");
44*5e96a66cSDavid du Colombier 		return 0;
45*5e96a66cSDavid du Colombier 	}
46*5e96a66cSDavid du Colombier 	h->blockSize = U16GET(p+6);
47*5e96a66cSDavid du Colombier 	h->super = U32GET(p+8);
48*5e96a66cSDavid du Colombier 	h->label = U32GET(p+12);
49*5e96a66cSDavid du Colombier 	h->data = U32GET(p+16);
50*5e96a66cSDavid du Colombier 	h->end = U32GET(p+20);
51*5e96a66cSDavid du Colombier 	return 1;
52*5e96a66cSDavid du Colombier }
53*5e96a66cSDavid du Colombier 
54*5e96a66cSDavid du Colombier void
55*5e96a66cSDavid du Colombier labelPack(Label *l, uchar *p, int i)
56*5e96a66cSDavid du Colombier {
57*5e96a66cSDavid du Colombier 	p += i*LabelSize;
58*5e96a66cSDavid du Colombier 	U8PUT(p, l->state);
59*5e96a66cSDavid du Colombier 	U8PUT(p+1, l->type);
60*5e96a66cSDavid du Colombier 	U32PUT(p+2, l->epoch);
61*5e96a66cSDavid du Colombier 	U32PUT(p+6, l->epochClose);
62*5e96a66cSDavid du Colombier 	U32PUT(p+10, l->tag);
63*5e96a66cSDavid du Colombier }
64*5e96a66cSDavid du Colombier 
65*5e96a66cSDavid du Colombier int
66*5e96a66cSDavid du Colombier labelUnpack(Label *l, uchar *p, int i)
67*5e96a66cSDavid du Colombier {
68*5e96a66cSDavid du Colombier 	p += i*LabelSize;
69*5e96a66cSDavid du Colombier 	l->state = p[0];
70*5e96a66cSDavid du Colombier 	l->type = p[1];
71*5e96a66cSDavid du Colombier 	l->epoch = U32GET(p+2);
72*5e96a66cSDavid du Colombier 	l->epochClose = U32GET(p+6);
73*5e96a66cSDavid du Colombier 	l->tag = U32GET(p+10);
74*5e96a66cSDavid du Colombier 
75*5e96a66cSDavid du Colombier 	if(l->type > BtMax){
76*5e96a66cSDavid du Colombier 	Bad:
77*5e96a66cSDavid du Colombier 		vtSetError(EBadLabel);
78*5e96a66cSDavid du Colombier fprint(2, "labelUnpack %.2ux %.2ux %.8ux %.8ux %.8ux\n",
79*5e96a66cSDavid du Colombier 	l->state, l->type, l->epoch, l->epochClose, l->tag);
80*5e96a66cSDavid du Colombier 		return 0;
81*5e96a66cSDavid du Colombier 	}
82*5e96a66cSDavid du Colombier 	if(l->state != BsBad && l->state != BsFree){
83*5e96a66cSDavid du Colombier 		if(!(l->state&BsAlloc))
84*5e96a66cSDavid du Colombier 			goto Bad;
85*5e96a66cSDavid du Colombier 		if(l->state&~BsMask)
86*5e96a66cSDavid du Colombier 			goto Bad;
87*5e96a66cSDavid du Colombier 		if(l->state&BsClosed){
88*5e96a66cSDavid du Colombier 			if(l->epochClose == ~(u32int)0)
89*5e96a66cSDavid du Colombier 				goto Bad;
90*5e96a66cSDavid du Colombier 		}else{
91*5e96a66cSDavid du Colombier 			if(l->epochClose != ~(u32int)0)
92*5e96a66cSDavid du Colombier 				goto Bad;
93*5e96a66cSDavid du Colombier 		}
94*5e96a66cSDavid du Colombier 	}
95*5e96a66cSDavid du Colombier 	return 1;
96*5e96a66cSDavid du Colombier }
97*5e96a66cSDavid du Colombier 
98*5e96a66cSDavid du Colombier u32int
99*5e96a66cSDavid du Colombier globalToLocal(uchar score[VtScoreSize])
100*5e96a66cSDavid du Colombier {
101*5e96a66cSDavid du Colombier 	int i;
102*5e96a66cSDavid du Colombier 
103*5e96a66cSDavid du Colombier 	for(i=0; i<VtScoreSize-4; i++)
104*5e96a66cSDavid du Colombier 		if(score[i] != 0)
105*5e96a66cSDavid du Colombier 			return NilBlock;
106*5e96a66cSDavid du Colombier 
107*5e96a66cSDavid du Colombier 	return U32GET(score+VtScoreSize-4);
108*5e96a66cSDavid du Colombier }
109*5e96a66cSDavid du Colombier 
110*5e96a66cSDavid du Colombier void
111*5e96a66cSDavid du Colombier localToGlobal(u32int addr, uchar score[VtScoreSize])
112*5e96a66cSDavid du Colombier {
113*5e96a66cSDavid du Colombier 	memset(score, 0, VtScoreSize-4);
114*5e96a66cSDavid du Colombier 	U32PUT(score+VtScoreSize-4, addr);
115*5e96a66cSDavid du Colombier }
116*5e96a66cSDavid du Colombier 
117*5e96a66cSDavid du Colombier void
118*5e96a66cSDavid du Colombier entryPack(Entry *e, uchar *p, int index)
119*5e96a66cSDavid du Colombier {
120*5e96a66cSDavid du Colombier 	ulong t32;
121*5e96a66cSDavid du Colombier 	int flags;
122*5e96a66cSDavid du Colombier 
123*5e96a66cSDavid du Colombier 	p += index * VtEntrySize;
124*5e96a66cSDavid du Colombier 
125*5e96a66cSDavid du Colombier 	U32PUT(p, e->gen);
126*5e96a66cSDavid du Colombier 	U16PUT(p+4, e->psize);
127*5e96a66cSDavid du Colombier 	U16PUT(p+6, e->dsize);
128*5e96a66cSDavid du Colombier 	flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
129*5e96a66cSDavid du Colombier 	U8PUT(p+8, flags);
130*5e96a66cSDavid du Colombier 	memset(p+9, 0, 5);
131*5e96a66cSDavid du Colombier 	U48PUT(p+14, e->size, t32);
132*5e96a66cSDavid du Colombier 
133*5e96a66cSDavid du Colombier 	if(flags & VtEntryLocal){
134*5e96a66cSDavid du Colombier 		if(globalToLocal(e->score) == NilBlock)
135*5e96a66cSDavid du Colombier 			abort();
136*5e96a66cSDavid du Colombier 		memset(p+20, 0, 7);
137*5e96a66cSDavid du Colombier 		U8PUT(p+27, e->archive);
138*5e96a66cSDavid du Colombier 		U32PUT(p+28, e->snap);
139*5e96a66cSDavid du Colombier 		U32PUT(p+32, e->tag);
140*5e96a66cSDavid du Colombier 		memmove(p+36, e->score+16, 4);
141*5e96a66cSDavid du Colombier 	}else
142*5e96a66cSDavid du Colombier 		memmove(p+20, e->score, VtScoreSize);
143*5e96a66cSDavid du Colombier }
144*5e96a66cSDavid du Colombier 
145*5e96a66cSDavid du Colombier int
146*5e96a66cSDavid du Colombier entryUnpack(Entry *e, uchar *p, int index)
147*5e96a66cSDavid du Colombier {
148*5e96a66cSDavid du Colombier 	p += index * VtEntrySize;
149*5e96a66cSDavid du Colombier 
150*5e96a66cSDavid du Colombier 	e->gen = U32GET(p);
151*5e96a66cSDavid du Colombier 	e->psize = U16GET(p+4);
152*5e96a66cSDavid du Colombier 	e->dsize = U16GET(p+6);
153*5e96a66cSDavid du Colombier 	e->flags = U8GET(p+8);
154*5e96a66cSDavid du Colombier 	e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
155*5e96a66cSDavid du Colombier 	e->flags &= ~VtEntryDepthMask;
156*5e96a66cSDavid du Colombier 	e->size = U48GET(p+14);
157*5e96a66cSDavid du Colombier 
158*5e96a66cSDavid du Colombier 	if(e->flags & VtEntryLocal){
159*5e96a66cSDavid du Colombier 		e->archive = p[27];
160*5e96a66cSDavid du Colombier 		e->snap = U32GET(p+28);
161*5e96a66cSDavid du Colombier 		e->tag = U32GET(p+32);
162*5e96a66cSDavid du Colombier 		memset(e->score, 0, 16);
163*5e96a66cSDavid du Colombier 		memmove(e->score+16, p+36, 4);
164*5e96a66cSDavid du Colombier 	}else{
165*5e96a66cSDavid du Colombier 		e->archive = 0;
166*5e96a66cSDavid du Colombier 		e->snap = 0;
167*5e96a66cSDavid du Colombier 		e->tag = 0;
168*5e96a66cSDavid du Colombier 		memmove(e->score, p+20, VtScoreSize);
169*5e96a66cSDavid du Colombier 	}
170*5e96a66cSDavid du Colombier 
171*5e96a66cSDavid du Colombier 	return 1;
172*5e96a66cSDavid du Colombier }
173*5e96a66cSDavid du Colombier 
174*5e96a66cSDavid du Colombier int
175*5e96a66cSDavid du Colombier entryType(Entry *e)
176*5e96a66cSDavid du Colombier {
177*5e96a66cSDavid du Colombier 	return (((e->flags & VtEntryDir) != 0) << 3) | e->depth;
178*5e96a66cSDavid du Colombier }
179*5e96a66cSDavid du Colombier 
180*5e96a66cSDavid du Colombier 
181*5e96a66cSDavid du Colombier void
182*5e96a66cSDavid du Colombier superPack(Super *s, uchar *p)
183*5e96a66cSDavid du Colombier {
184*5e96a66cSDavid du Colombier 	u32int t32;
185*5e96a66cSDavid du Colombier 
186*5e96a66cSDavid du Colombier 	memset(p, 0, SuperSize);
187*5e96a66cSDavid du Colombier 	U32PUT(p, SuperMagic);
188*5e96a66cSDavid du Colombier 	assert(s->version == SuperVersion);
189*5e96a66cSDavid du Colombier 	U16PUT(p+4, s->version);
190*5e96a66cSDavid du Colombier 	U32PUT(p+6, s->epochLow);
191*5e96a66cSDavid du Colombier 	U32PUT(p+10, s->epochHigh);
192*5e96a66cSDavid du Colombier 	U64PUT(p+14, s->qid, t32);
193*5e96a66cSDavid du Colombier 	U32PUT(p+22, s->active);
194*5e96a66cSDavid du Colombier 	U32PUT(p+26, s->next);
195*5e96a66cSDavid du Colombier 	U32PUT(p+30, s->current);
196*5e96a66cSDavid du Colombier 	memmove(p+34, s->last, VtScoreSize);
197*5e96a66cSDavid du Colombier 	memmove(p+54, s->name, sizeof(s->name));
198*5e96a66cSDavid du Colombier }
199*5e96a66cSDavid du Colombier 
200*5e96a66cSDavid du Colombier int
201*5e96a66cSDavid du Colombier superUnpack(Super *s, uchar *p)
202*5e96a66cSDavid du Colombier {
203*5e96a66cSDavid du Colombier 	memset(s, 0, sizeof(*s));
204*5e96a66cSDavid du Colombier 	if(U32GET(p) != SuperMagic)
205*5e96a66cSDavid du Colombier 		goto Err;
206*5e96a66cSDavid du Colombier 	s->version = U16GET(p+4);
207*5e96a66cSDavid du Colombier 	if(s->version != SuperVersion)
208*5e96a66cSDavid du Colombier 		goto Err;
209*5e96a66cSDavid du Colombier 	s->epochLow = U32GET(p+6);
210*5e96a66cSDavid du Colombier 	s->epochHigh = U32GET(p+10);
211*5e96a66cSDavid du Colombier 	s->qid = U64GET(p+14);
212*5e96a66cSDavid du Colombier 	if(s->epochLow == 0 || s->epochLow > s->epochHigh || s->qid == 0)
213*5e96a66cSDavid du Colombier 		goto Err;
214*5e96a66cSDavid du Colombier 	s->active = U32GET(p+22);
215*5e96a66cSDavid du Colombier 	s->next = U32GET(p+26);
216*5e96a66cSDavid du Colombier 	s->current = U32GET(p+30);
217*5e96a66cSDavid du Colombier 	memmove(s->last, p+34, VtScoreSize);
218*5e96a66cSDavid du Colombier 	memmove(s->name, p+54, sizeof(s->name));
219*5e96a66cSDavid du Colombier 	s->name[sizeof(s->name)-1] = 0;
220*5e96a66cSDavid du Colombier 	return 1;
221*5e96a66cSDavid du Colombier Err:
222*5e96a66cSDavid du Colombier 	memset(s, 0, sizeof(*s));
223*5e96a66cSDavid du Colombier 	vtSetError(EBadSuper);
224*5e96a66cSDavid du Colombier 	return 0;
225*5e96a66cSDavid du Colombier }
226*5e96a66cSDavid du Colombier 
227