Blame


1 7763a61a 2003-11-23 devnull #include "stdinc.h"
2 7763a61a 2003-11-23 devnull #include "vac.h"
3 7763a61a 2003-11-23 devnull #include "dat.h"
4 7763a61a 2003-11-23 devnull #include "fns.h"
5 7763a61a 2003-11-23 devnull #include "error.h"
6 7763a61a 2003-11-23 devnull
7 7763a61a 2003-11-23 devnull typedef struct MetaChunk MetaChunk;
8 7763a61a 2003-11-23 devnull
9 7763a61a 2003-11-23 devnull struct MetaChunk {
10 7763a61a 2003-11-23 devnull ushort offset;
11 7763a61a 2003-11-23 devnull ushort size;
12 7763a61a 2003-11-23 devnull ushort index;
13 7763a61a 2003-11-23 devnull };
14 7763a61a 2003-11-23 devnull
15 7763a61a 2003-11-23 devnull static int stringUnpack(char **s, uchar **p, int *n);
16 7763a61a 2003-11-23 devnull
17 7763a61a 2003-11-23 devnull /*
18 7763a61a 2003-11-23 devnull * integer conversion routines
19 7763a61a 2003-11-23 devnull */
20 7763a61a 2003-11-23 devnull #define U8GET(p) ((p)[0])
21 7763a61a 2003-11-23 devnull #define U16GET(p) (((p)[0]<<8)|(p)[1])
22 7763a61a 2003-11-23 devnull #define U32GET(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
23 7763a61a 2003-11-23 devnull #define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
24 7763a61a 2003-11-23 devnull #define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
25 7763a61a 2003-11-23 devnull
26 7763a61a 2003-11-23 devnull #define U8PUT(p,v) (p)[0]=(v)
27 7763a61a 2003-11-23 devnull #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
28 7763a61a 2003-11-23 devnull #define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
29 7763a61a 2003-11-23 devnull #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
30 7763a61a 2003-11-23 devnull #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
31 7763a61a 2003-11-23 devnull
32 7763a61a 2003-11-23 devnull static int
33 7763a61a 2003-11-23 devnull stringUnpack(char **s, uchar **p, int *n)
34 7763a61a 2003-11-23 devnull {
35 7763a61a 2003-11-23 devnull int nn;
36 7763a61a 2003-11-23 devnull
37 7763a61a 2003-11-23 devnull if(*n < 2)
38 7763a61a 2003-11-23 devnull return 0;
39 7763a61a 2003-11-23 devnull
40 7763a61a 2003-11-23 devnull nn = U16GET(*p);
41 7763a61a 2003-11-23 devnull *p += 2;
42 7763a61a 2003-11-23 devnull *n -= 2;
43 7763a61a 2003-11-23 devnull if(nn > *n)
44 7763a61a 2003-11-23 devnull return 0;
45 7763a61a 2003-11-23 devnull *s = vtMemAlloc(nn+1);
46 7763a61a 2003-11-23 devnull memmove(*s, *p, nn);
47 7763a61a 2003-11-23 devnull (*s)[nn] = 0;
48 7763a61a 2003-11-23 devnull *p += nn;
49 7763a61a 2003-11-23 devnull *n -= nn;
50 7763a61a 2003-11-23 devnull return 1;
51 7763a61a 2003-11-23 devnull }
52 7763a61a 2003-11-23 devnull
53 7763a61a 2003-11-23 devnull static int
54 7763a61a 2003-11-23 devnull stringPack(char *s, uchar *p)
55 7763a61a 2003-11-23 devnull {
56 7763a61a 2003-11-23 devnull int n;
57 7763a61a 2003-11-23 devnull
58 7763a61a 2003-11-23 devnull n = strlen(s);
59 7763a61a 2003-11-23 devnull U16PUT(p, n);
60 7763a61a 2003-11-23 devnull memmove(p+2, s, n);
61 7763a61a 2003-11-23 devnull return n+2;
62 7763a61a 2003-11-23 devnull }
63 7763a61a 2003-11-23 devnull
64 7763a61a 2003-11-23 devnull
65 7763a61a 2003-11-23 devnull int
66 7763a61a 2003-11-23 devnull mbUnpack(MetaBlock *mb, uchar *p, int n)
67 7763a61a 2003-11-23 devnull {
68 7763a61a 2003-11-23 devnull u32int magic;
69 7763a61a 2003-11-23 devnull
70 7763a61a 2003-11-23 devnull mb->maxsize = n;
71 7763a61a 2003-11-23 devnull mb->buf = p;
72 7763a61a 2003-11-23 devnull
73 7763a61a 2003-11-23 devnull if(n == 0) {
74 7763a61a 2003-11-23 devnull memset(mb, 0, sizeof(MetaBlock));
75 7763a61a 2003-11-23 devnull return 1;
76 7763a61a 2003-11-23 devnull }
77 7763a61a 2003-11-23 devnull
78 7763a61a 2003-11-23 devnull magic = U32GET(p);
79 7763a61a 2003-11-23 devnull if(magic != MetaMagic && magic != MetaMagic+1) {
80 7763a61a 2003-11-23 devnull vtSetError("bad meta block magic");
81 7763a61a 2003-11-23 devnull return 0;
82 7763a61a 2003-11-23 devnull }
83 7763a61a 2003-11-23 devnull mb->size = U16GET(p+4);
84 7763a61a 2003-11-23 devnull mb->free = U16GET(p+6);
85 7763a61a 2003-11-23 devnull mb->maxindex = U16GET(p+8);
86 7763a61a 2003-11-23 devnull mb->nindex = U16GET(p+10);
87 7763a61a 2003-11-23 devnull mb->unbotch = (magic == MetaMagic+1);
88 7763a61a 2003-11-23 devnull
89 7763a61a 2003-11-23 devnull if(mb->size > n) {
90 7763a61a 2003-11-23 devnull vtSetError("bad meta block size");
91 7763a61a 2003-11-23 devnull return 0;
92 7763a61a 2003-11-23 devnull }
93 7763a61a 2003-11-23 devnull p += MetaHeaderSize;
94 7763a61a 2003-11-23 devnull n -= MetaHeaderSize;
95 7763a61a 2003-11-23 devnull
96 7763a61a 2003-11-23 devnull USED(p);
97 7763a61a 2003-11-23 devnull if(n < mb->maxindex*MetaIndexSize) {
98 7763a61a 2003-11-23 devnull vtSetError("truncated meta block 2");
99 7763a61a 2003-11-23 devnull return 0;
100 7763a61a 2003-11-23 devnull }
101 7763a61a 2003-11-23 devnull return 1;
102 7763a61a 2003-11-23 devnull }
103 7763a61a 2003-11-23 devnull
104 7763a61a 2003-11-23 devnull void
105 7763a61a 2003-11-23 devnull mbPack(MetaBlock *mb)
106 7763a61a 2003-11-23 devnull {
107 7763a61a 2003-11-23 devnull uchar *p;
108 7763a61a 2003-11-23 devnull
109 7763a61a 2003-11-23 devnull p = mb->buf;
110 7763a61a 2003-11-23 devnull
111 7763a61a 2003-11-23 devnull U32PUT(p, MetaMagic);
112 7763a61a 2003-11-23 devnull U16PUT(p+4, mb->size);
113 7763a61a 2003-11-23 devnull U16PUT(p+6, mb->free);
114 7763a61a 2003-11-23 devnull U16PUT(p+8, mb->maxindex);
115 7763a61a 2003-11-23 devnull U16PUT(p+10, mb->nindex);
116 7763a61a 2003-11-23 devnull }
117 7763a61a 2003-11-23 devnull
118 7763a61a 2003-11-23 devnull
119 7763a61a 2003-11-23 devnull void
120 7763a61a 2003-11-23 devnull mbDelete(MetaBlock *mb, int i, MetaEntry *me)
121 7763a61a 2003-11-23 devnull {
122 7763a61a 2003-11-23 devnull uchar *p;
123 7763a61a 2003-11-23 devnull int n;
124 7763a61a 2003-11-23 devnull
125 7763a61a 2003-11-23 devnull assert(i < mb->nindex);
126 7763a61a 2003-11-23 devnull
127 7763a61a 2003-11-23 devnull if(me->p - mb->buf + me->size == mb->size)
128 7763a61a 2003-11-23 devnull mb->size -= me->size;
129 7763a61a 2003-11-23 devnull else
130 7763a61a 2003-11-23 devnull mb->free += me->size;
131 7763a61a 2003-11-23 devnull
132 7763a61a 2003-11-23 devnull p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
133 7763a61a 2003-11-23 devnull n = (mb->nindex-i-1)*MetaIndexSize;
134 7763a61a 2003-11-23 devnull memmove(p, p+MetaIndexSize, n);
135 7763a61a 2003-11-23 devnull memset(p+n, 0, MetaIndexSize);
136 7763a61a 2003-11-23 devnull mb->nindex--;
137 7763a61a 2003-11-23 devnull }
138 7763a61a 2003-11-23 devnull
139 7763a61a 2003-11-23 devnull void
140 7763a61a 2003-11-23 devnull mbInsert(MetaBlock *mb, int i, MetaEntry *me)
141 7763a61a 2003-11-23 devnull {
142 7763a61a 2003-11-23 devnull uchar *p;
143 7763a61a 2003-11-23 devnull int o, n;
144 7763a61a 2003-11-23 devnull
145 7763a61a 2003-11-23 devnull assert(mb->nindex < mb->maxindex);
146 7763a61a 2003-11-23 devnull
147 7763a61a 2003-11-23 devnull o = me->p - mb->buf;
148 7763a61a 2003-11-23 devnull n = me->size;
149 7763a61a 2003-11-23 devnull if(o+n > mb->size) {
150 7763a61a 2003-11-23 devnull mb->free -= mb->size - o;
151 7763a61a 2003-11-23 devnull mb->size = o + n;
152 7763a61a 2003-11-23 devnull } else
153 7763a61a 2003-11-23 devnull mb->free -= n;
154 7763a61a 2003-11-23 devnull
155 7763a61a 2003-11-23 devnull p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
156 7763a61a 2003-11-23 devnull n = (mb->nindex-i)*MetaIndexSize;
157 7763a61a 2003-11-23 devnull memmove(p+MetaIndexSize, p, n);
158 7763a61a 2003-11-23 devnull U16PUT(p, me->p - mb->buf);
159 7763a61a 2003-11-23 devnull U16PUT(p+2, me->size);
160 7763a61a 2003-11-23 devnull mb->nindex++;
161 7763a61a 2003-11-23 devnull }
162 7763a61a 2003-11-23 devnull
163 7763a61a 2003-11-23 devnull int
164 7763a61a 2003-11-23 devnull meUnpack(MetaEntry *me, MetaBlock *mb, int i)
165 7763a61a 2003-11-23 devnull {
166 7763a61a 2003-11-23 devnull uchar *p;
167 7763a61a 2003-11-23 devnull int eo, en;
168 7763a61a 2003-11-23 devnull
169 7763a61a 2003-11-23 devnull if(i < 0 || i >= mb->nindex) {
170 7763a61a 2003-11-23 devnull vtSetError("bad meta entry index");
171 7763a61a 2003-11-23 devnull return 0;
172 7763a61a 2003-11-23 devnull }
173 7763a61a 2003-11-23 devnull
174 7763a61a 2003-11-23 devnull p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
175 7763a61a 2003-11-23 devnull eo = U16GET(p);
176 7763a61a 2003-11-23 devnull en = U16GET(p+2);
177 7763a61a 2003-11-23 devnull
178 7763a61a 2003-11-23 devnull if(0)print("eo = %d en = %d\n", eo, en);
179 7763a61a 2003-11-23 devnull if(eo < MetaHeaderSize + mb->maxindex*MetaIndexSize) {
180 7763a61a 2003-11-23 devnull vtSetError("corrupted entry in meta block");
181 7763a61a 2003-11-23 devnull return 0;
182 7763a61a 2003-11-23 devnull }
183 7763a61a 2003-11-23 devnull
184 7763a61a 2003-11-23 devnull if(eo+en > mb->size) {
185 7763a61a 2003-11-23 devnull vtSetError("truncated meta block");
186 7763a61a 2003-11-23 devnull return 0;
187 7763a61a 2003-11-23 devnull }
188 7763a61a 2003-11-23 devnull
189 7763a61a 2003-11-23 devnull p = mb->buf + eo;
190 7763a61a 2003-11-23 devnull
191 7763a61a 2003-11-23 devnull /* make sure entry looks ok and includes an elem name */
192 7763a61a 2003-11-23 devnull if(en < 8 || U32GET(p) != DirMagic || en < 8 + U16GET(p+6)) {
193 7763a61a 2003-11-23 devnull vtSetError("corrupted meta block entry");
194 7763a61a 2003-11-23 devnull return 0;
195 7763a61a 2003-11-23 devnull }
196 7763a61a 2003-11-23 devnull
197 7763a61a 2003-11-23 devnull me->p = p;
198 7763a61a 2003-11-23 devnull me->size = en;
199 7763a61a 2003-11-23 devnull
200 7763a61a 2003-11-23 devnull return 1;
201 7763a61a 2003-11-23 devnull }
202 7763a61a 2003-11-23 devnull
203 7763a61a 2003-11-23 devnull /* assumes a small amount of checking has been done in mbEntry */
204 7763a61a 2003-11-23 devnull int
205 7763a61a 2003-11-23 devnull meCmp(MetaEntry *me, char *s)
206 7763a61a 2003-11-23 devnull {
207 7763a61a 2003-11-23 devnull int n;
208 7763a61a 2003-11-23 devnull uchar *p;
209 7763a61a 2003-11-23 devnull
210 7763a61a 2003-11-23 devnull p = me->p;
211 7763a61a 2003-11-23 devnull
212 7763a61a 2003-11-23 devnull p += 6;
213 7763a61a 2003-11-23 devnull n = U16GET(p);
214 7763a61a 2003-11-23 devnull p += 2;
215 7763a61a 2003-11-23 devnull
216 7763a61a 2003-11-23 devnull assert(n + 8 < me->size);
217 7763a61a 2003-11-23 devnull
218 7763a61a 2003-11-23 devnull while(n > 0) {
219 7763a61a 2003-11-23 devnull if(*s == 0)
220 7763a61a 2003-11-23 devnull return -1;
221 7763a61a 2003-11-23 devnull if(*p < (uchar)*s)
222 7763a61a 2003-11-23 devnull return -1;
223 7763a61a 2003-11-23 devnull if(*p > (uchar)*s)
224 7763a61a 2003-11-23 devnull return 1;
225 7763a61a 2003-11-23 devnull p++;
226 7763a61a 2003-11-23 devnull s++;
227 7763a61a 2003-11-23 devnull n--;
228 7763a61a 2003-11-23 devnull }
229 7763a61a 2003-11-23 devnull return *s != 0;
230 7763a61a 2003-11-23 devnull }
231 7763a61a 2003-11-23 devnull
232 7763a61a 2003-11-23 devnull int
233 7763a61a 2003-11-23 devnull meCmpNew(MetaEntry *me, char *s)
234 7763a61a 2003-11-23 devnull {
235 7763a61a 2003-11-23 devnull int n;
236 7763a61a 2003-11-23 devnull uchar *p;
237 7763a61a 2003-11-23 devnull
238 7763a61a 2003-11-23 devnull p = me->p;
239 7763a61a 2003-11-23 devnull
240 7763a61a 2003-11-23 devnull p += 6;
241 7763a61a 2003-11-23 devnull n = U16GET(p);
242 7763a61a 2003-11-23 devnull p += 2;
243 7763a61a 2003-11-23 devnull
244 7763a61a 2003-11-23 devnull assert(n + 8 < me->size);
245 7763a61a 2003-11-23 devnull
246 7763a61a 2003-11-23 devnull while(n > 0) {
247 7763a61a 2003-11-23 devnull if(*s == 0)
248 7763a61a 2003-11-23 devnull return 1;
249 7763a61a 2003-11-23 devnull if(*p < (uchar)*s)
250 7763a61a 2003-11-23 devnull return -1;
251 7763a61a 2003-11-23 devnull if(*p > (uchar)*s)
252 7763a61a 2003-11-23 devnull return 1;
253 7763a61a 2003-11-23 devnull p++;
254 7763a61a 2003-11-23 devnull s++;
255 7763a61a 2003-11-23 devnull n--;
256 7763a61a 2003-11-23 devnull }
257 7763a61a 2003-11-23 devnull return -(*s != 0);
258 7763a61a 2003-11-23 devnull }
259 7763a61a 2003-11-23 devnull
260 7763a61a 2003-11-23 devnull static int
261 7763a61a 2003-11-23 devnull offsetCmp(void *s0, void *s1)
262 7763a61a 2003-11-23 devnull {
263 7763a61a 2003-11-23 devnull MetaChunk *mc0, *mc1;
264 7763a61a 2003-11-23 devnull
265 7763a61a 2003-11-23 devnull mc0 = s0;
266 7763a61a 2003-11-23 devnull mc1 = s1;
267 7763a61a 2003-11-23 devnull if(mc0->offset < mc1->offset)
268 7763a61a 2003-11-23 devnull return -1;
269 7763a61a 2003-11-23 devnull if(mc0->offset > mc1->offset)
270 7763a61a 2003-11-23 devnull return 1;
271 7763a61a 2003-11-23 devnull return 0;
272 7763a61a 2003-11-23 devnull }
273 7763a61a 2003-11-23 devnull
274 7763a61a 2003-11-23 devnull static MetaChunk *
275 7763a61a 2003-11-23 devnull metaChunks(MetaBlock *mb)
276 7763a61a 2003-11-23 devnull {
277 7763a61a 2003-11-23 devnull MetaChunk *mc;
278 7763a61a 2003-11-23 devnull int oo, o, n, i;
279 7763a61a 2003-11-23 devnull uchar *p;
280 7763a61a 2003-11-23 devnull
281 7763a61a 2003-11-23 devnull mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk));
282 7763a61a 2003-11-23 devnull p = mb->buf + MetaHeaderSize;
283 7763a61a 2003-11-23 devnull for(i = 0; i<mb->nindex; i++) {
284 7763a61a 2003-11-23 devnull mc[i].offset = U16GET(p);
285 7763a61a 2003-11-23 devnull mc[i].size = U16GET(p+2);
286 7763a61a 2003-11-23 devnull mc[i].index = i;
287 7763a61a 2003-11-23 devnull p += MetaIndexSize;
288 7763a61a 2003-11-23 devnull }
289 7763a61a 2003-11-23 devnull
290 7763a61a 2003-11-23 devnull qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);
291 7763a61a 2003-11-23 devnull
292 7763a61a 2003-11-23 devnull /* check block looks ok */
293 7763a61a 2003-11-23 devnull oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
294 7763a61a 2003-11-23 devnull o = oo;
295 7763a61a 2003-11-23 devnull n = 0;
296 7763a61a 2003-11-23 devnull for(i=0; i<mb->nindex; i++) {
297 7763a61a 2003-11-23 devnull o = mc[i].offset;
298 7763a61a 2003-11-23 devnull n = mc[i].size;
299 7763a61a 2003-11-23 devnull if(o < oo)
300 7763a61a 2003-11-23 devnull goto Err;
301 7763a61a 2003-11-23 devnull oo += n;
302 7763a61a 2003-11-23 devnull }
303 7763a61a 2003-11-23 devnull if(o+n <= mb->size)
304 7763a61a 2003-11-23 devnull goto Err;
305 7763a61a 2003-11-23 devnull if(mb->size - oo != mb->free)
306 7763a61a 2003-11-23 devnull goto Err;
307 7763a61a 2003-11-23 devnull
308 7763a61a 2003-11-23 devnull return mc;
309 7763a61a 2003-11-23 devnull Err:
310 7763a61a 2003-11-23 devnull vtMemFree(mc);
311 7763a61a 2003-11-23 devnull return nil;
312 7763a61a 2003-11-23 devnull }
313 7763a61a 2003-11-23 devnull
314 7763a61a 2003-11-23 devnull static void
315 7763a61a 2003-11-23 devnull mbCompact(MetaBlock *mb, MetaChunk *mc)
316 7763a61a 2003-11-23 devnull {
317 7763a61a 2003-11-23 devnull int oo, o, n, i;
318 7763a61a 2003-11-23 devnull
319 7763a61a 2003-11-23 devnull oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
320 7763a61a 2003-11-23 devnull
321 7763a61a 2003-11-23 devnull for(i=0; i<mb->nindex; i++) {
322 7763a61a 2003-11-23 devnull o = mc[i].offset;
323 7763a61a 2003-11-23 devnull n = mc[i].size;
324 7763a61a 2003-11-23 devnull if(o != oo) {
325 7763a61a 2003-11-23 devnull memmove(mb->buf + oo, mb->buf + o, n);
326 7763a61a 2003-11-23 devnull U16PUT(mb->buf + MetaHeaderSize + mc[i].index*MetaIndexSize, oo);
327 7763a61a 2003-11-23 devnull }
328 7763a61a 2003-11-23 devnull oo += n;
329 7763a61a 2003-11-23 devnull }
330 7763a61a 2003-11-23 devnull
331 7763a61a 2003-11-23 devnull mb->size = oo;
332 7763a61a 2003-11-23 devnull mb->free = 0;
333 7763a61a 2003-11-23 devnull }
334 7763a61a 2003-11-23 devnull
335 7763a61a 2003-11-23 devnull uchar *
336 7763a61a 2003-11-23 devnull mbAlloc(MetaBlock *mb, int n)
337 7763a61a 2003-11-23 devnull {
338 7763a61a 2003-11-23 devnull int i, o;
339 7763a61a 2003-11-23 devnull MetaChunk *mc;
340 7763a61a 2003-11-23 devnull
341 7763a61a 2003-11-23 devnull /* off the end */
342 7763a61a 2003-11-23 devnull if(mb->maxsize - mb->size >= n)
343 7763a61a 2003-11-23 devnull return mb->buf + mb->size;
344 7763a61a 2003-11-23 devnull
345 7763a61a 2003-11-23 devnull /* check if possible */
346 7763a61a 2003-11-23 devnull if(mb->maxsize - mb->size + mb->free < n)
347 7763a61a 2003-11-23 devnull return nil;
348 7763a61a 2003-11-23 devnull
349 7763a61a 2003-11-23 devnull mc = metaChunks(mb);
350 7763a61a 2003-11-23 devnull
351 7763a61a 2003-11-23 devnull /* look for hole */
352 7763a61a 2003-11-23 devnull o = MetaHeaderSize + mb->maxindex*MetaIndexSize;
353 7763a61a 2003-11-23 devnull for(i=0; i<mb->nindex; i++) {
354 7763a61a 2003-11-23 devnull if(mc[i].offset - o >= n) {
355 7763a61a 2003-11-23 devnull vtMemFree(mc);
356 7763a61a 2003-11-23 devnull return mb->buf + o;
357 7763a61a 2003-11-23 devnull }
358 7763a61a 2003-11-23 devnull o = mc[i].offset + mc[i].size;
359 7763a61a 2003-11-23 devnull }
360 7763a61a 2003-11-23 devnull
361 7763a61a 2003-11-23 devnull if(mb->maxsize - o >= n) {
362 7763a61a 2003-11-23 devnull vtMemFree(mc);
363 7763a61a 2003-11-23 devnull return mb->buf + o;
364 7763a61a 2003-11-23 devnull }
365 7763a61a 2003-11-23 devnull
366 7763a61a 2003-11-23 devnull /* compact and return off the end */
367 7763a61a 2003-11-23 devnull mbCompact(mb, mc);
368 7763a61a 2003-11-23 devnull vtMemFree(mc);
369 7763a61a 2003-11-23 devnull
370 7763a61a 2003-11-23 devnull assert(mb->maxsize - mb->size >= n);
371 7763a61a 2003-11-23 devnull return mb->buf + mb->size;
372 7763a61a 2003-11-23 devnull }
373 7763a61a 2003-11-23 devnull
374 7763a61a 2003-11-23 devnull int
375 7763a61a 2003-11-23 devnull vdSize(VacDir *dir)
376 7763a61a 2003-11-23 devnull {
377 7763a61a 2003-11-23 devnull int n;
378 7763a61a 2003-11-23 devnull
379 7763a61a 2003-11-23 devnull /* constant part */
380 7763a61a 2003-11-23 devnull
381 7763a61a 2003-11-23 devnull n = 4 + /* magic */
382 7763a61a 2003-11-23 devnull 2 + /* version */
383 7763a61a 2003-11-23 devnull 4 + /* entry */
384 7763a61a 2003-11-23 devnull 4 + /* guid */
385 7763a61a 2003-11-23 devnull 4 + /* mentry */
386 7763a61a 2003-11-23 devnull 4 + /* mgen */
387 7763a61a 2003-11-23 devnull 8 + /* qid */
388 7763a61a 2003-11-23 devnull 4 + /* mtime */
389 7763a61a 2003-11-23 devnull 4 + /* mcount */
390 7763a61a 2003-11-23 devnull 4 + /* ctime */
391 7763a61a 2003-11-23 devnull 4 + /* atime */
392 7763a61a 2003-11-23 devnull 4 + /* mode */
393 7763a61a 2003-11-23 devnull 0;
394 7763a61a 2003-11-23 devnull
395 7763a61a 2003-11-23 devnull /* strings */
396 7763a61a 2003-11-23 devnull n += 2 + strlen(dir->elem);
397 7763a61a 2003-11-23 devnull n += 2 + strlen(dir->uid);
398 7763a61a 2003-11-23 devnull n += 2 + strlen(dir->gid);
399 7763a61a 2003-11-23 devnull n += 2 + strlen(dir->mid);
400 7763a61a 2003-11-23 devnull
401 7763a61a 2003-11-23 devnull /* optional sections */
402 7763a61a 2003-11-23 devnull if(dir->qidSpace) {
403 7763a61a 2003-11-23 devnull n += 3 + /* option header */
404 7763a61a 2003-11-23 devnull 8 + /* qidOffset */
405 7763a61a 2003-11-23 devnull 8; /* qid Max */
406 7763a61a 2003-11-23 devnull }
407 7763a61a 2003-11-23 devnull
408 7763a61a 2003-11-23 devnull return n;
409 7763a61a 2003-11-23 devnull }
410 7763a61a 2003-11-23 devnull
411 7763a61a 2003-11-23 devnull void
412 7763a61a 2003-11-23 devnull vdPack(VacDir *dir, MetaEntry *me)
413 7763a61a 2003-11-23 devnull {
414 7763a61a 2003-11-23 devnull uchar *p;
415 7763a61a 2003-11-23 devnull ulong t32;
416 7763a61a 2003-11-23 devnull
417 7763a61a 2003-11-23 devnull p = me->p;
418 7763a61a 2003-11-23 devnull
419 7763a61a 2003-11-23 devnull U32PUT(p, DirMagic);
420 7763a61a 2003-11-23 devnull U16PUT(p+4, 9); /* version */
421 7763a61a 2003-11-23 devnull p += 6;
422 7763a61a 2003-11-23 devnull
423 7763a61a 2003-11-23 devnull p += stringPack(dir->elem, p);
424 7763a61a 2003-11-23 devnull
425 7763a61a 2003-11-23 devnull U32PUT(p, dir->entry);
426 7763a61a 2003-11-23 devnull U32PUT(p+4, dir->gen);
427 7763a61a 2003-11-23 devnull U32PUT(p+8, dir->mentry);
428 7763a61a 2003-11-23 devnull U32PUT(p+12, dir->mgen);
429 7763a61a 2003-11-23 devnull U64PUT(p+16, dir->qid, t32);
430 7763a61a 2003-11-23 devnull p += 24;
431 7763a61a 2003-11-23 devnull
432 7763a61a 2003-11-23 devnull p += stringPack(dir->uid, p);
433 7763a61a 2003-11-23 devnull p += stringPack(dir->gid, p);
434 7763a61a 2003-11-23 devnull p += stringPack(dir->mid, p);
435 7763a61a 2003-11-23 devnull
436 7763a61a 2003-11-23 devnull U32PUT(p, dir->mtime);
437 7763a61a 2003-11-23 devnull U32PUT(p+4, dir->mcount);
438 7763a61a 2003-11-23 devnull U32PUT(p+8, dir->ctime);
439 7763a61a 2003-11-23 devnull U32PUT(p+12, dir->atime);
440 7763a61a 2003-11-23 devnull U32PUT(p+16, dir->mode);
441 7763a61a 2003-11-23 devnull p += 5*4;
442 7763a61a 2003-11-23 devnull
443 7763a61a 2003-11-23 devnull if(dir->qidSpace) {
444 7763a61a 2003-11-23 devnull U8PUT(p, DirQidSpaceEntry);
445 7763a61a 2003-11-23 devnull U16PUT(p+1, 2*8);
446 7763a61a 2003-11-23 devnull p += 3;
447 7763a61a 2003-11-23 devnull U64PUT(p, dir->qidOffset, t32);
448 7763a61a 2003-11-23 devnull U64PUT(p+8, dir->qidMax, t32);
449 7763a61a 2003-11-23 devnull }
450 7763a61a 2003-11-23 devnull
451 7763a61a 2003-11-23 devnull assert(p == me->p + me->size);
452 7763a61a 2003-11-23 devnull }
453 7763a61a 2003-11-23 devnull
454 7763a61a 2003-11-23 devnull
455 7763a61a 2003-11-23 devnull int
456 7763a61a 2003-11-23 devnull vdUnpack(VacDir *dir, MetaEntry *me)
457 7763a61a 2003-11-23 devnull {
458 7763a61a 2003-11-23 devnull int t, nn, n, version;
459 7763a61a 2003-11-23 devnull uchar *p;
460 7763a61a 2003-11-23 devnull
461 7763a61a 2003-11-23 devnull p = me->p;
462 7763a61a 2003-11-23 devnull n = me->size;
463 7763a61a 2003-11-23 devnull
464 7763a61a 2003-11-23 devnull memset(dir, 0, sizeof(VacDir));
465 7763a61a 2003-11-23 devnull
466 7763a61a 2003-11-23 devnull if(0)print("vdUnpack\n");
467 7763a61a 2003-11-23 devnull /* magic */
468 7763a61a 2003-11-23 devnull if(n < 4 || U32GET(p) != DirMagic)
469 7763a61a 2003-11-23 devnull goto Err;
470 7763a61a 2003-11-23 devnull p += 4;
471 7763a61a 2003-11-23 devnull n -= 4;
472 7763a61a 2003-11-23 devnull
473 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got magic\n");
474 7763a61a 2003-11-23 devnull /* version */
475 7763a61a 2003-11-23 devnull if(n < 2)
476 7763a61a 2003-11-23 devnull goto Err;
477 7763a61a 2003-11-23 devnull version = U16GET(p);
478 7763a61a 2003-11-23 devnull if(version < 7 || version > 9)
479 7763a61a 2003-11-23 devnull goto Err;
480 7763a61a 2003-11-23 devnull p += 2;
481 7763a61a 2003-11-23 devnull n -= 2;
482 7763a61a 2003-11-23 devnull
483 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got version\n");
484 7763a61a 2003-11-23 devnull
485 7763a61a 2003-11-23 devnull /* elem */
486 7763a61a 2003-11-23 devnull if(!stringUnpack(&dir->elem, &p, &n))
487 7763a61a 2003-11-23 devnull goto Err;
488 7763a61a 2003-11-23 devnull
489 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got elem\n");
490 7763a61a 2003-11-23 devnull
491 7763a61a 2003-11-23 devnull /* entry */
492 7763a61a 2003-11-23 devnull if(n < 4)
493 7763a61a 2003-11-23 devnull goto Err;
494 7763a61a 2003-11-23 devnull dir->entry = U32GET(p);
495 7763a61a 2003-11-23 devnull p += 4;
496 7763a61a 2003-11-23 devnull n -= 4;
497 7763a61a 2003-11-23 devnull
498 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got entry\n");
499 7763a61a 2003-11-23 devnull
500 7763a61a 2003-11-23 devnull if(version < 9) {
501 7763a61a 2003-11-23 devnull dir->gen = 0;
502 7763a61a 2003-11-23 devnull dir->mentry = dir->entry+1;
503 7763a61a 2003-11-23 devnull dir->mgen = 0;
504 7763a61a 2003-11-23 devnull } else {
505 7763a61a 2003-11-23 devnull if(n < 3*4)
506 7763a61a 2003-11-23 devnull goto Err;
507 7763a61a 2003-11-23 devnull dir->gen = U32GET(p);
508 7763a61a 2003-11-23 devnull dir->mentry = U32GET(p+4);
509 7763a61a 2003-11-23 devnull dir->mgen = U32GET(p+8);
510 7763a61a 2003-11-23 devnull p += 3*4;
511 7763a61a 2003-11-23 devnull n -= 3*4;
512 7763a61a 2003-11-23 devnull }
513 7763a61a 2003-11-23 devnull
514 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got gen etc\n");
515 7763a61a 2003-11-23 devnull
516 7763a61a 2003-11-23 devnull /* size is gotten from DirEntry */
517 7763a61a 2003-11-23 devnull
518 7763a61a 2003-11-23 devnull /* qid */
519 7763a61a 2003-11-23 devnull if(n < 8)
520 7763a61a 2003-11-23 devnull goto Err;
521 7763a61a 2003-11-23 devnull dir->qid = U64GET(p);
522 7763a61a 2003-11-23 devnull p += 8;
523 7763a61a 2003-11-23 devnull n -= 8;
524 7763a61a 2003-11-23 devnull
525 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got qid\n");
526 7763a61a 2003-11-23 devnull /* skip replacement */
527 7763a61a 2003-11-23 devnull if(version == 7) {
528 7763a61a 2003-11-23 devnull if(n < VtScoreSize)
529 7763a61a 2003-11-23 devnull goto Err;
530 7763a61a 2003-11-23 devnull p += VtScoreSize;
531 7763a61a 2003-11-23 devnull n -= VtScoreSize;
532 7763a61a 2003-11-23 devnull }
533 7763a61a 2003-11-23 devnull
534 7763a61a 2003-11-23 devnull /* uid */
535 7763a61a 2003-11-23 devnull if(!stringUnpack(&dir->uid, &p, &n))
536 7763a61a 2003-11-23 devnull goto Err;
537 7763a61a 2003-11-23 devnull
538 7763a61a 2003-11-23 devnull /* gid */
539 7763a61a 2003-11-23 devnull if(!stringUnpack(&dir->gid, &p, &n))
540 7763a61a 2003-11-23 devnull goto Err;
541 7763a61a 2003-11-23 devnull
542 7763a61a 2003-11-23 devnull /* mid */
543 7763a61a 2003-11-23 devnull if(!stringUnpack(&dir->mid, &p, &n))
544 7763a61a 2003-11-23 devnull goto Err;
545 7763a61a 2003-11-23 devnull
546 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got ids\n");
547 7763a61a 2003-11-23 devnull if(n < 5*4)
548 7763a61a 2003-11-23 devnull goto Err;
549 7763a61a 2003-11-23 devnull dir->mtime = U32GET(p);
550 7763a61a 2003-11-23 devnull dir->mcount = U32GET(p+4);
551 7763a61a 2003-11-23 devnull dir->ctime = U32GET(p+8);
552 7763a61a 2003-11-23 devnull dir->atime = U32GET(p+12);
553 7763a61a 2003-11-23 devnull dir->mode = U32GET(p+16);
554 7763a61a 2003-11-23 devnull p += 5*4;
555 7763a61a 2003-11-23 devnull n -= 5*4;
556 7763a61a 2003-11-23 devnull
557 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got times\n");
558 7763a61a 2003-11-23 devnull /* optional meta data */
559 7763a61a 2003-11-23 devnull while(n > 0) {
560 7763a61a 2003-11-23 devnull if(n < 3)
561 7763a61a 2003-11-23 devnull goto Err;
562 7763a61a 2003-11-23 devnull t = p[0];
563 7763a61a 2003-11-23 devnull nn = U16GET(p+1);
564 7763a61a 2003-11-23 devnull p += 3;
565 7763a61a 2003-11-23 devnull n -= 3;
566 7763a61a 2003-11-23 devnull if(n < nn)
567 7763a61a 2003-11-23 devnull goto Err;
568 7763a61a 2003-11-23 devnull switch(t) {
569 7763a61a 2003-11-23 devnull case DirPlan9Entry:
570 7763a61a 2003-11-23 devnull /* not valid in version >= 9 */
571 7763a61a 2003-11-23 devnull if(version >= 9)
572 7763a61a 2003-11-23 devnull break;
573 7763a61a 2003-11-23 devnull if(dir->plan9 || nn != 12)
574 7763a61a 2003-11-23 devnull goto Err;
575 7763a61a 2003-11-23 devnull dir->plan9 = 1;
576 7763a61a 2003-11-23 devnull dir->p9path = U64GET(p);
577 7763a61a 2003-11-23 devnull dir->p9version = U32GET(p+8);
578 7763a61a 2003-11-23 devnull if(dir->mcount == 0)
579 7763a61a 2003-11-23 devnull dir->mcount = dir->p9version;
580 7763a61a 2003-11-23 devnull break;
581 7763a61a 2003-11-23 devnull case DirGenEntry:
582 7763a61a 2003-11-23 devnull /* not valid in version >= 9 */
583 7763a61a 2003-11-23 devnull if(version >= 9)
584 7763a61a 2003-11-23 devnull break;
585 7763a61a 2003-11-23 devnull break;
586 7763a61a 2003-11-23 devnull case DirQidSpaceEntry:
587 7763a61a 2003-11-23 devnull if(dir->qidSpace || nn != 16)
588 7763a61a 2003-11-23 devnull goto Err;
589 7763a61a 2003-11-23 devnull dir->qidSpace = 1;
590 7763a61a 2003-11-23 devnull dir->qidOffset = U64GET(p);
591 7763a61a 2003-11-23 devnull dir->qidMax = U64GET(p+8);
592 7763a61a 2003-11-23 devnull break;
593 7763a61a 2003-11-23 devnull }
594 7763a61a 2003-11-23 devnull p += nn;
595 7763a61a 2003-11-23 devnull n -= nn;
596 7763a61a 2003-11-23 devnull }
597 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: got options\n");
598 7763a61a 2003-11-23 devnull
599 7763a61a 2003-11-23 devnull if(p != me->p + me->size)
600 7763a61a 2003-11-23 devnull goto Err;
601 7763a61a 2003-11-23 devnull
602 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: correct size\n");
603 7763a61a 2003-11-23 devnull return 1;
604 7763a61a 2003-11-23 devnull Err:
605 7763a61a 2003-11-23 devnull if(0)print("vdUnpack: XXXXXXXXXXXX EbadMeta\n");
606 7763a61a 2003-11-23 devnull vtSetError(EBadMeta);
607 7763a61a 2003-11-23 devnull vdCleanup(dir);
608 7763a61a 2003-11-23 devnull return 0;
609 7763a61a 2003-11-23 devnull }