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