1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
3 6f4d00ee 2013-09-23 0intro typedef struct MetaChunk MetaChunk;
5 6f4d00ee 2013-09-23 0intro struct MetaChunk {
6 6f4d00ee 2013-09-23 0intro ushort offset;
7 6f4d00ee 2013-09-23 0intro ushort size;
8 6f4d00ee 2013-09-23 0intro ushort index;
11 6f4d00ee 2013-09-23 0intro static int stringUnpack(char **s, uchar **p, int *n);
12 6f4d00ee 2013-09-23 0intro static int meCmp(MetaEntry*, char *s);
13 6f4d00ee 2013-09-23 0intro static int meCmpOld(MetaEntry*, char *s);
17 6f4d00ee 2013-09-23 0intro static char EBadMeta[] = "corrupted meta data";
18 6f4d00ee 2013-09-23 0intro static char ENoFile[] = "file does not exist";
21 6f4d00ee 2013-09-23 0intro * integer conversion routines
23 6f4d00ee 2013-09-23 0intro #define U8GET(p) ((p)[0])
24 6f4d00ee 2013-09-23 0intro #define U16GET(p) (((p)[0]<<8)|(p)[1])
25 6f4d00ee 2013-09-23 0intro #define U32GET(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
26 6f4d00ee 2013-09-23 0intro #define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
27 6f4d00ee 2013-09-23 0intro #define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
29 6f4d00ee 2013-09-23 0intro #define U8PUT(p,v) (p)[0]=(v)
30 6f4d00ee 2013-09-23 0intro #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
31 b29ebaab 2013-10-23 0intro #define U32PUT(p,v) (p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF
32 6f4d00ee 2013-09-23 0intro #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
33 6f4d00ee 2013-09-23 0intro #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
35 6f4d00ee 2013-09-23 0intro static int
36 6f4d00ee 2013-09-23 0intro stringUnpack(char **s, uchar **p, int *n)
40 6f4d00ee 2013-09-23 0intro if(*n < 2)
43 6f4d00ee 2013-09-23 0intro nn = U16GET(*p);
46 6f4d00ee 2013-09-23 0intro if(nn > *n)
48 4b576658 2013-09-23 0intro *s = vtmalloc(nn+1);
49 6f4d00ee 2013-09-23 0intro memmove(*s, *p, nn);
50 6f4d00ee 2013-09-23 0intro (*s)[nn] = 0;
56 6f4d00ee 2013-09-23 0intro static int
57 6f4d00ee 2013-09-23 0intro stringPack(char *s, uchar *p)
61 6f4d00ee 2013-09-23 0intro n = strlen(s);
62 6f4d00ee 2013-09-23 0intro U16PUT(p, n);
63 6f4d00ee 2013-09-23 0intro memmove(p+2, s, n);
64 6f4d00ee 2013-09-23 0intro return n+2;
68 6f4d00ee 2013-09-23 0intro mbSearch(MetaBlock *mb, char *elem, int *ri, MetaEntry *me)
71 6f4d00ee 2013-09-23 0intro int b, t, x;
72 6f4d00ee 2013-09-23 0intro if(0)fprint(2, "mbSearch %s\n", elem);
74 6f4d00ee 2013-09-23 0intro /* binary search within block */
76 6f4d00ee 2013-09-23 0intro t = mb->nindex;
77 6f4d00ee 2013-09-23 0intro while(b < t){
78 6f4d00ee 2013-09-23 0intro i = (b+t)>>1;
79 6f4d00ee 2013-09-23 0intro meUnpack(me, mb, i);
81 6f4d00ee 2013-09-23 0intro if(mb->botch)
82 6f4d00ee 2013-09-23 0intro x = meCmpOld(me, elem);
84 6f4d00ee 2013-09-23 0intro x = meCmp(me, elem);
86 6f4d00ee 2013-09-23 0intro if(x == 0){
93 6f4d00ee 2013-09-23 0intro else /* x > 0 */
97 6f4d00ee 2013-09-23 0intro assert(b == t);
99 6f4d00ee 2013-09-23 0intro *ri = b; /* b is the index to insert this entry */
100 6f4d00ee 2013-09-23 0intro memset(me, 0, sizeof(*me));
102 4b576658 2013-09-23 0intro werrstr(ENoFile);
103 6f4d00ee 2013-09-23 0intro return 0;
107 6f4d00ee 2013-09-23 0intro mbInit(MetaBlock *mb, uchar *p, int n, int ne)
109 6f4d00ee 2013-09-23 0intro memset(p, 0, n);
110 6f4d00ee 2013-09-23 0intro mb->maxsize = n;
111 6f4d00ee 2013-09-23 0intro mb->maxindex = ne;
112 6f4d00ee 2013-09-23 0intro mb->nindex = 0;
113 6f4d00ee 2013-09-23 0intro mb->free = 0;
114 6f4d00ee 2013-09-23 0intro mb->size = MetaHeaderSize + ne*MetaIndexSize;
115 6f4d00ee 2013-09-23 0intro mb->buf = p;
116 6f4d00ee 2013-09-23 0intro mb->botch = 0;
120 6f4d00ee 2013-09-23 0intro mbUnpack(MetaBlock *mb, uchar *p, int n)
122 6f4d00ee 2013-09-23 0intro u32int magic;
124 6f4d00ee 2013-09-23 0intro int eo, en, omin;
125 6f4d00ee 2013-09-23 0intro uchar *q;
127 6f4d00ee 2013-09-23 0intro mb->maxsize = n;
128 6f4d00ee 2013-09-23 0intro mb->buf = p;
130 6f4d00ee 2013-09-23 0intro if(n == 0){
131 6f4d00ee 2013-09-23 0intro memset(mb, 0, sizeof(MetaBlock));
132 6f4d00ee 2013-09-23 0intro return 1;
135 6f4d00ee 2013-09-23 0intro magic = U32GET(p);
136 6f4d00ee 2013-09-23 0intro if(magic != MetaMagic && magic != MetaMagic-1)
137 6f4d00ee 2013-09-23 0intro goto Err;
138 6f4d00ee 2013-09-23 0intro mb->size = U16GET(p+4);
139 6f4d00ee 2013-09-23 0intro mb->free = U16GET(p+6);
140 6f4d00ee 2013-09-23 0intro mb->maxindex = U16GET(p+8);
141 6f4d00ee 2013-09-23 0intro mb->nindex = U16GET(p+10);
142 6f4d00ee 2013-09-23 0intro mb->botch = magic != MetaMagic;
143 6f4d00ee 2013-09-23 0intro if(mb->size > n)
144 6f4d00ee 2013-09-23 0intro goto Err;
146 6f4d00ee 2013-09-23 0intro omin = MetaHeaderSize + mb->maxindex*MetaIndexSize;
147 6f4d00ee 2013-09-23 0intro if(n < omin)
148 6f4d00ee 2013-09-23 0intro goto Err;
151 6f4d00ee 2013-09-23 0intro p += MetaHeaderSize;
153 6f4d00ee 2013-09-23 0intro /* check the index table - ensures that meUnpack and meCmp never fail */
154 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
155 6f4d00ee 2013-09-23 0intro eo = U16GET(p);
156 6f4d00ee 2013-09-23 0intro en = U16GET(p+2);
157 6f4d00ee 2013-09-23 0intro if(eo < omin || eo+en > mb->size || en < 8)
158 6f4d00ee 2013-09-23 0intro goto Err;
159 6f4d00ee 2013-09-23 0intro q = mb->buf + eo;
160 6f4d00ee 2013-09-23 0intro if(U32GET(q) != DirMagic)
161 6f4d00ee 2013-09-23 0intro goto Err;
165 6f4d00ee 2013-09-23 0intro return 1;
167 4b576658 2013-09-23 0intro werrstr(EBadMeta);
168 6f4d00ee 2013-09-23 0intro return 0;
173 6f4d00ee 2013-09-23 0intro mbPack(MetaBlock *mb)
175 6f4d00ee 2013-09-23 0intro uchar *p;
177 6f4d00ee 2013-09-23 0intro p = mb->buf;
179 6f4d00ee 2013-09-23 0intro assert(!mb->botch);
181 6f4d00ee 2013-09-23 0intro U32PUT(p, MetaMagic);
182 6f4d00ee 2013-09-23 0intro U16PUT(p+4, mb->size);
183 6f4d00ee 2013-09-23 0intro U16PUT(p+6, mb->free);
184 6f4d00ee 2013-09-23 0intro U16PUT(p+8, mb->maxindex);
185 6f4d00ee 2013-09-23 0intro U16PUT(p+10, mb->nindex);
190 6f4d00ee 2013-09-23 0intro mbDelete(MetaBlock *mb, int i)
192 6f4d00ee 2013-09-23 0intro uchar *p;
194 6f4d00ee 2013-09-23 0intro MetaEntry me;
196 6f4d00ee 2013-09-23 0intro assert(i < mb->nindex);
197 6f4d00ee 2013-09-23 0intro meUnpack(&me, mb, i);
198 6f4d00ee 2013-09-23 0intro memset(me.p, 0, me.size);
200 6f4d00ee 2013-09-23 0intro if(me.p - mb->buf + me.size == mb->size)
201 6f4d00ee 2013-09-23 0intro mb->size -= me.size;
203 6f4d00ee 2013-09-23 0intro mb->free += me.size;
205 6f4d00ee 2013-09-23 0intro p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
206 6f4d00ee 2013-09-23 0intro n = (mb->nindex-i-1)*MetaIndexSize;
207 6f4d00ee 2013-09-23 0intro memmove(p, p+MetaIndexSize, n);
208 6f4d00ee 2013-09-23 0intro memset(p+n, 0, MetaIndexSize);
209 6f4d00ee 2013-09-23 0intro mb->nindex--;
213 6f4d00ee 2013-09-23 0intro mbInsert(MetaBlock *mb, int i, MetaEntry *me)
215 6f4d00ee 2013-09-23 0intro uchar *p;
216 6f4d00ee 2013-09-23 0intro int o, n;
218 6f4d00ee 2013-09-23 0intro assert(mb->nindex < mb->maxindex);
220 6f4d00ee 2013-09-23 0intro o = me->p - mb->buf;
221 6f4d00ee 2013-09-23 0intro n = me->size;
222 6f4d00ee 2013-09-23 0intro if(o+n > mb->size){
223 6f4d00ee 2013-09-23 0intro mb->free -= mb->size - o;
224 6f4d00ee 2013-09-23 0intro mb->size = o + n;
226 6f4d00ee 2013-09-23 0intro mb->free -= n;
228 6f4d00ee 2013-09-23 0intro p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
229 6f4d00ee 2013-09-23 0intro n = (mb->nindex-i)*MetaIndexSize;
230 6f4d00ee 2013-09-23 0intro memmove(p+MetaIndexSize, p, n);
231 6f4d00ee 2013-09-23 0intro U16PUT(p, me->p - mb->buf);
232 6f4d00ee 2013-09-23 0intro U16PUT(p+2, me->size);
233 6f4d00ee 2013-09-23 0intro mb->nindex++;
237 6f4d00ee 2013-09-23 0intro mbResize(MetaBlock *mb, MetaEntry *me, int n)
239 6f4d00ee 2013-09-23 0intro uchar *p, *ep;
241 6f4d00ee 2013-09-23 0intro /* easy case */
242 6f4d00ee 2013-09-23 0intro if(n <= me->size){
243 6f4d00ee 2013-09-23 0intro me->size = n;
244 6f4d00ee 2013-09-23 0intro return 1;
247 6f4d00ee 2013-09-23 0intro /* try and expand entry */
249 6f4d00ee 2013-09-23 0intro p = me->p + me->size;
250 6f4d00ee 2013-09-23 0intro ep = mb->buf + mb->maxsize;
251 6f4d00ee 2013-09-23 0intro while(p < ep && *p == 0)
253 6f4d00ee 2013-09-23 0intro if(n <= p - me->p){
254 6f4d00ee 2013-09-23 0intro me->size = n;
255 6f4d00ee 2013-09-23 0intro return 1;
258 6f4d00ee 2013-09-23 0intro p = mbAlloc(mb, n);
259 6f4d00ee 2013-09-23 0intro if(p != nil){
260 6f4d00ee 2013-09-23 0intro me->p = p;
261 6f4d00ee 2013-09-23 0intro me->size = n;
262 6f4d00ee 2013-09-23 0intro return 1;
265 6f4d00ee 2013-09-23 0intro return 0;
269 6f4d00ee 2013-09-23 0intro meUnpack(MetaEntry *me, MetaBlock *mb, int i)
271 6f4d00ee 2013-09-23 0intro uchar *p;
272 6f4d00ee 2013-09-23 0intro int eo, en;
274 6f4d00ee 2013-09-23 0intro assert(i >= 0 && i < mb->nindex);
276 6f4d00ee 2013-09-23 0intro p = mb->buf + MetaHeaderSize + i*MetaIndexSize;
277 6f4d00ee 2013-09-23 0intro eo = U16GET(p);
278 6f4d00ee 2013-09-23 0intro en = U16GET(p+2);
280 6f4d00ee 2013-09-23 0intro me->p = mb->buf + eo;
281 6f4d00ee 2013-09-23 0intro me->size = en;
283 6f4d00ee 2013-09-23 0intro /* checked by mbUnpack */
284 6f4d00ee 2013-09-23 0intro assert(me->size >= 8);
287 6f4d00ee 2013-09-23 0intro /* assumes a small amount of checking has been done in mbEntry */
288 6f4d00ee 2013-09-23 0intro static int
289 6f4d00ee 2013-09-23 0intro meCmp(MetaEntry *me, char *s)
292 6f4d00ee 2013-09-23 0intro uchar *p;
294 6f4d00ee 2013-09-23 0intro p = me->p;
296 6f4d00ee 2013-09-23 0intro /* skip magic & version */
298 6f4d00ee 2013-09-23 0intro n = U16GET(p);
301 6f4d00ee 2013-09-23 0intro if(n > me->size - 8)
302 6f4d00ee 2013-09-23 0intro n = me->size - 8;
304 6f4d00ee 2013-09-23 0intro while(n > 0){
305 6f4d00ee 2013-09-23 0intro if(*s == 0)
306 6f4d00ee 2013-09-23 0intro return 1;
307 6f4d00ee 2013-09-23 0intro if(*p < (uchar)*s)
308 6f4d00ee 2013-09-23 0intro return -1;
309 6f4d00ee 2013-09-23 0intro if(*p > (uchar)*s)
310 6f4d00ee 2013-09-23 0intro return 1;
315 6f4d00ee 2013-09-23 0intro return -(*s != 0);
319 6f4d00ee 2013-09-23 0intro * This is the old and broken meCmp.
320 6f4d00ee 2013-09-23 0intro * This cmp routine reverse the sense of the comparison
321 6f4d00ee 2013-09-23 0intro * when one string is a prefix of the other.
322 6f4d00ee 2013-09-23 0intro * In other words, it put "ab" after "abc" rather
323 6f4d00ee 2013-09-23 0intro * than before. This behaviour is ok; binary search
324 6f4d00ee 2013-09-23 0intro * and sort still work. However, it is goes against
325 6f4d00ee 2013-09-23 0intro * the usual convention.
327 6f4d00ee 2013-09-23 0intro static int
328 6f4d00ee 2013-09-23 0intro meCmpOld(MetaEntry *me, char *s)
331 6f4d00ee 2013-09-23 0intro uchar *p;
333 6f4d00ee 2013-09-23 0intro p = me->p;
335 6f4d00ee 2013-09-23 0intro /* skip magic & version */
337 6f4d00ee 2013-09-23 0intro n = U16GET(p);
340 6f4d00ee 2013-09-23 0intro if(n > me->size - 8)
341 6f4d00ee 2013-09-23 0intro n = me->size - 8;
343 6f4d00ee 2013-09-23 0intro while(n > 0){
344 6f4d00ee 2013-09-23 0intro if(*s == 0)
345 6f4d00ee 2013-09-23 0intro return -1;
346 6f4d00ee 2013-09-23 0intro if(*p < (uchar)*s)
347 6f4d00ee 2013-09-23 0intro return -1;
348 6f4d00ee 2013-09-23 0intro if(*p > (uchar)*s)
349 6f4d00ee 2013-09-23 0intro return 1;
354 6f4d00ee 2013-09-23 0intro return *s != 0;
357 6f4d00ee 2013-09-23 0intro static int
358 b29ebaab 2013-10-23 0intro offsetCmp(const void *s0, const void *s1)
360 6f4d00ee 2013-09-23 0intro MetaChunk *mc0, *mc1;
362 b29ebaab 2013-10-23 0intro mc0 = (MetaChunk*)s0;
363 b29ebaab 2013-10-23 0intro mc1 = (MetaChunk*)s1;
364 6f4d00ee 2013-09-23 0intro if(mc0->offset < mc1->offset)
365 6f4d00ee 2013-09-23 0intro return -1;
366 6f4d00ee 2013-09-23 0intro if(mc0->offset > mc1->offset)
367 6f4d00ee 2013-09-23 0intro return 1;
368 6f4d00ee 2013-09-23 0intro return 0;
371 6f4d00ee 2013-09-23 0intro static MetaChunk *
372 6f4d00ee 2013-09-23 0intro metaChunks(MetaBlock *mb)
374 6f4d00ee 2013-09-23 0intro MetaChunk *mc;
375 6f4d00ee 2013-09-23 0intro int oo, o, n, i;
376 6f4d00ee 2013-09-23 0intro uchar *p;
378 4b576658 2013-09-23 0intro mc = vtmalloc(mb->nindex*sizeof(MetaChunk));
379 6f4d00ee 2013-09-23 0intro p = mb->buf + MetaHeaderSize;
380 6f4d00ee 2013-09-23 0intro for(i = 0; i<mb->nindex; i++){
381 6f4d00ee 2013-09-23 0intro mc[i].offset = U16GET(p);
382 6f4d00ee 2013-09-23 0intro mc[i].size = U16GET(p+2);
383 6f4d00ee 2013-09-23 0intro mc[i].index = i;
384 6f4d00ee 2013-09-23 0intro p += MetaIndexSize;
387 6f4d00ee 2013-09-23 0intro qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);
389 6f4d00ee 2013-09-23 0intro /* check block looks ok */
390 6f4d00ee 2013-09-23 0intro oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
393 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
394 6f4d00ee 2013-09-23 0intro o = mc[i].offset;
395 6f4d00ee 2013-09-23 0intro n = mc[i].size;
396 6f4d00ee 2013-09-23 0intro if(o < oo)
397 6f4d00ee 2013-09-23 0intro goto Err;
400 6f4d00ee 2013-09-23 0intro if(o+n > mb->size)
401 6f4d00ee 2013-09-23 0intro goto Err;
402 6f4d00ee 2013-09-23 0intro if(mb->size - oo != mb->free)
403 6f4d00ee 2013-09-23 0intro goto Err;
405 6f4d00ee 2013-09-23 0intro return mc;
407 6f4d00ee 2013-09-23 0intro fprint(2, "metaChunks failed!\n");
408 6f4d00ee 2013-09-23 0intro oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
409 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
410 6f4d00ee 2013-09-23 0intro fprint(2, "\t%d: %d %d\n", i, mc[i].offset, mc[i].offset + mc[i].size);
411 6f4d00ee 2013-09-23 0intro oo += mc[i].size;
413 6f4d00ee 2013-09-23 0intro fprint(2, "\tused=%d size=%d free=%d free2=%d\n", oo, mb->size, mb->free, mb->size - oo);
414 4b576658 2013-09-23 0intro werrstr(EBadMeta);
415 4b576658 2013-09-23 0intro vtfree(mc);
416 6f4d00ee 2013-09-23 0intro return nil;
419 6f4d00ee 2013-09-23 0intro static void
420 6f4d00ee 2013-09-23 0intro mbCompact(MetaBlock *mb, MetaChunk *mc)
422 6f4d00ee 2013-09-23 0intro int oo, o, n, i;
424 6f4d00ee 2013-09-23 0intro oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
426 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
427 6f4d00ee 2013-09-23 0intro o = mc[i].offset;
428 6f4d00ee 2013-09-23 0intro n = mc[i].size;
429 6f4d00ee 2013-09-23 0intro if(o != oo){
430 6f4d00ee 2013-09-23 0intro memmove(mb->buf + oo, mb->buf + o, n);
431 6f4d00ee 2013-09-23 0intro U16PUT(mb->buf + MetaHeaderSize + mc[i].index*MetaIndexSize, oo);
436 6f4d00ee 2013-09-23 0intro mb->size = oo;
437 6f4d00ee 2013-09-23 0intro mb->free = 0;
441 6f4d00ee 2013-09-23 0intro mbAlloc(MetaBlock *mb, int n)
443 6f4d00ee 2013-09-23 0intro int i, o;
444 6f4d00ee 2013-09-23 0intro MetaChunk *mc;
446 6f4d00ee 2013-09-23 0intro /* off the end */
447 6f4d00ee 2013-09-23 0intro if(mb->maxsize - mb->size >= n)
448 6f4d00ee 2013-09-23 0intro return mb->buf + mb->size;
450 6f4d00ee 2013-09-23 0intro /* check if possible */
451 6f4d00ee 2013-09-23 0intro if(mb->maxsize - mb->size + mb->free < n)
452 6f4d00ee 2013-09-23 0intro return nil;
454 6f4d00ee 2013-09-23 0intro mc = metaChunks(mb);
455 6f4d00ee 2013-09-23 0intro if(mc == nil){
456 6f4d00ee 2013-09-23 0intro fprint(2, "mbAlloc: metaChunks failed: %r\n");
457 6f4d00ee 2013-09-23 0intro return nil;
460 6f4d00ee 2013-09-23 0intro /* look for hole */
461 6f4d00ee 2013-09-23 0intro o = MetaHeaderSize + mb->maxindex*MetaIndexSize;
462 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
463 6f4d00ee 2013-09-23 0intro if(mc[i].offset - o >= n){
464 4b576658 2013-09-23 0intro vtfree(mc);
465 6f4d00ee 2013-09-23 0intro return mb->buf + o;
467 6f4d00ee 2013-09-23 0intro o = mc[i].offset + mc[i].size;
470 6f4d00ee 2013-09-23 0intro if(mb->maxsize - o >= n){
471 4b576658 2013-09-23 0intro vtfree(mc);
472 6f4d00ee 2013-09-23 0intro return mb->buf + o;
475 6f4d00ee 2013-09-23 0intro /* compact and return off the end */
476 6f4d00ee 2013-09-23 0intro mbCompact(mb, mc);
477 4b576658 2013-09-23 0intro vtfree(mc);
479 6f4d00ee 2013-09-23 0intro if(mb->maxsize - mb->size < n){
480 4b576658 2013-09-23 0intro werrstr(EBadMeta);
481 6f4d00ee 2013-09-23 0intro return nil;
483 6f4d00ee 2013-09-23 0intro return mb->buf + mb->size;
487 6f4d00ee 2013-09-23 0intro deSize(DirEntry *dir)
491 6f4d00ee 2013-09-23 0intro /* constant part */
493 6f4d00ee 2013-09-23 0intro n = 4 + /* magic */
494 6f4d00ee 2013-09-23 0intro 2 + /* version */
495 6f4d00ee 2013-09-23 0intro 4 + /* entry */
496 6f4d00ee 2013-09-23 0intro 4 + /* guid */
497 6f4d00ee 2013-09-23 0intro 4 + /* mentry */
498 6f4d00ee 2013-09-23 0intro 4 + /* mgen */
499 6f4d00ee 2013-09-23 0intro 8 + /* qid */
500 6f4d00ee 2013-09-23 0intro 4 + /* mtime */
501 6f4d00ee 2013-09-23 0intro 4 + /* mcount */
502 6f4d00ee 2013-09-23 0intro 4 + /* ctime */
503 6f4d00ee 2013-09-23 0intro 4 + /* atime */
504 6f4d00ee 2013-09-23 0intro 4 + /* mode */
507 6f4d00ee 2013-09-23 0intro /* strings */
508 6f4d00ee 2013-09-23 0intro n += 2 + strlen(dir->elem);
509 6f4d00ee 2013-09-23 0intro n += 2 + strlen(dir->uid);
510 6f4d00ee 2013-09-23 0intro n += 2 + strlen(dir->gid);
511 6f4d00ee 2013-09-23 0intro n += 2 + strlen(dir->mid);
513 6f4d00ee 2013-09-23 0intro /* optional sections */
514 6f4d00ee 2013-09-23 0intro if(dir->qidSpace){
515 6f4d00ee 2013-09-23 0intro n += 3 + /* option header */
516 6f4d00ee 2013-09-23 0intro 8 + /* qidOffset */
517 6f4d00ee 2013-09-23 0intro 8; /* qid Max */
520 6f4d00ee 2013-09-23 0intro return n;
524 6f4d00ee 2013-09-23 0intro dePack(DirEntry *dir, MetaEntry *me)
526 6f4d00ee 2013-09-23 0intro uchar *p;
527 6f4d00ee 2013-09-23 0intro ulong t32;
529 6f4d00ee 2013-09-23 0intro p = me->p;
531 6f4d00ee 2013-09-23 0intro U32PUT(p, DirMagic);
532 6f4d00ee 2013-09-23 0intro U16PUT(p+4, 9); /* version */
535 6f4d00ee 2013-09-23 0intro p += stringPack(dir->elem, p);
537 6f4d00ee 2013-09-23 0intro U32PUT(p, dir->entry);
538 6f4d00ee 2013-09-23 0intro U32PUT(p+4, dir->gen);
539 6f4d00ee 2013-09-23 0intro U32PUT(p+8, dir->mentry);
540 6f4d00ee 2013-09-23 0intro U32PUT(p+12, dir->mgen);
541 6f4d00ee 2013-09-23 0intro U64PUT(p+16, dir->qid, t32);
544 6f4d00ee 2013-09-23 0intro p += stringPack(dir->uid, p);
545 6f4d00ee 2013-09-23 0intro p += stringPack(dir->gid, p);
546 6f4d00ee 2013-09-23 0intro p += stringPack(dir->mid, p);
548 6f4d00ee 2013-09-23 0intro U32PUT(p, dir->mtime);
549 6f4d00ee 2013-09-23 0intro U32PUT(p+4, dir->mcount);
550 6f4d00ee 2013-09-23 0intro U32PUT(p+8, dir->ctime);
551 6f4d00ee 2013-09-23 0intro U32PUT(p+12, dir->atime);
552 6f4d00ee 2013-09-23 0intro U32PUT(p+16, dir->mode);
553 6f4d00ee 2013-09-23 0intro p += 5*4;
555 6f4d00ee 2013-09-23 0intro if(dir->qidSpace){
556 6f4d00ee 2013-09-23 0intro U8PUT(p, DeQidSpace);
557 6f4d00ee 2013-09-23 0intro U16PUT(p+1, 2*8);
559 6f4d00ee 2013-09-23 0intro U64PUT(p, dir->qidOffset, t32);
560 6f4d00ee 2013-09-23 0intro U64PUT(p+8, dir->qidMax, t32);
564 6f4d00ee 2013-09-23 0intro assert(p == me->p + me->size);
569 6f4d00ee 2013-09-23 0intro deUnpack(DirEntry *dir, MetaEntry *me)
571 6f4d00ee 2013-09-23 0intro int t, nn, n, version;
572 6f4d00ee 2013-09-23 0intro uchar *p;
574 6f4d00ee 2013-09-23 0intro p = me->p;
575 6f4d00ee 2013-09-23 0intro n = me->size;
577 6f4d00ee 2013-09-23 0intro memset(dir, 0, sizeof(DirEntry));
579 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack\n");
580 6f4d00ee 2013-09-23 0intro /* magic */
581 6f4d00ee 2013-09-23 0intro if(n < 4 || U32GET(p) != DirMagic)
582 6f4d00ee 2013-09-23 0intro goto Err;
586 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got magic\n");
587 6f4d00ee 2013-09-23 0intro /* version */
588 6f4d00ee 2013-09-23 0intro if(n < 2)
589 6f4d00ee 2013-09-23 0intro goto Err;
590 6f4d00ee 2013-09-23 0intro version = U16GET(p);
591 6f4d00ee 2013-09-23 0intro if(version < 7 || version > 9)
592 6f4d00ee 2013-09-23 0intro goto Err;
596 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got version\n");
598 6f4d00ee 2013-09-23 0intro /* elem */
599 6f4d00ee 2013-09-23 0intro if(!stringUnpack(&dir->elem, &p, &n))
600 6f4d00ee 2013-09-23 0intro goto Err;
602 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got elem\n");
604 6f4d00ee 2013-09-23 0intro /* entry */
605 6f4d00ee 2013-09-23 0intro if(n < 4)
606 6f4d00ee 2013-09-23 0intro goto Err;
607 6f4d00ee 2013-09-23 0intro dir->entry = U32GET(p);
611 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got entry\n");
613 6f4d00ee 2013-09-23 0intro if(version < 9){
614 6f4d00ee 2013-09-23 0intro dir->gen = 0;
615 6f4d00ee 2013-09-23 0intro dir->mentry = dir->entry+1;
616 6f4d00ee 2013-09-23 0intro dir->mgen = 0;
618 6f4d00ee 2013-09-23 0intro if(n < 3*4)
619 6f4d00ee 2013-09-23 0intro goto Err;
620 6f4d00ee 2013-09-23 0intro dir->gen = U32GET(p);
621 6f4d00ee 2013-09-23 0intro dir->mentry = U32GET(p+4);
622 6f4d00ee 2013-09-23 0intro dir->mgen = U32GET(p+8);
623 6f4d00ee 2013-09-23 0intro p += 3*4;
624 6f4d00ee 2013-09-23 0intro n -= 3*4;
627 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got gen etc\n");
629 6f4d00ee 2013-09-23 0intro /* size is gotten from VtEntry */
630 6f4d00ee 2013-09-23 0intro dir->size = 0;
632 6f4d00ee 2013-09-23 0intro /* qid */
633 6f4d00ee 2013-09-23 0intro if(n < 8)
634 6f4d00ee 2013-09-23 0intro goto Err;
635 6f4d00ee 2013-09-23 0intro dir->qid = U64GET(p);
639 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got qid\n");
640 6f4d00ee 2013-09-23 0intro /* skip replacement */
641 6f4d00ee 2013-09-23 0intro if(version == 7){
642 6f4d00ee 2013-09-23 0intro if(n < VtScoreSize)
643 6f4d00ee 2013-09-23 0intro goto Err;
644 6f4d00ee 2013-09-23 0intro p += VtScoreSize;
645 6f4d00ee 2013-09-23 0intro n -= VtScoreSize;
648 6f4d00ee 2013-09-23 0intro /* uid */
649 6f4d00ee 2013-09-23 0intro if(!stringUnpack(&dir->uid, &p, &n))
650 6f4d00ee 2013-09-23 0intro goto Err;
652 6f4d00ee 2013-09-23 0intro /* gid */
653 6f4d00ee 2013-09-23 0intro if(!stringUnpack(&dir->gid, &p, &n))
654 6f4d00ee 2013-09-23 0intro goto Err;
656 6f4d00ee 2013-09-23 0intro /* mid */
657 6f4d00ee 2013-09-23 0intro if(!stringUnpack(&dir->mid, &p, &n))
658 6f4d00ee 2013-09-23 0intro goto Err;
660 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got ids\n");
661 6f4d00ee 2013-09-23 0intro if(n < 5*4)
662 6f4d00ee 2013-09-23 0intro goto Err;
663 6f4d00ee 2013-09-23 0intro dir->mtime = U32GET(p);
664 6f4d00ee 2013-09-23 0intro dir->mcount = U32GET(p+4);
665 6f4d00ee 2013-09-23 0intro dir->ctime = U32GET(p+8);
666 6f4d00ee 2013-09-23 0intro dir->atime = U32GET(p+12);
667 6f4d00ee 2013-09-23 0intro dir->mode = U32GET(p+16);
668 6f4d00ee 2013-09-23 0intro p += 5*4;
669 6f4d00ee 2013-09-23 0intro n -= 5*4;
671 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got times\n");
672 6f4d00ee 2013-09-23 0intro /* optional meta data */
673 6f4d00ee 2013-09-23 0intro while(n > 0){
674 6f4d00ee 2013-09-23 0intro if(n < 3)
675 6f4d00ee 2013-09-23 0intro goto Err;
676 6f4d00ee 2013-09-23 0intro t = p[0];
677 6f4d00ee 2013-09-23 0intro nn = U16GET(p+1);
680 6f4d00ee 2013-09-23 0intro if(n < nn)
681 6f4d00ee 2013-09-23 0intro goto Err;
682 6f4d00ee 2013-09-23 0intro switch(t){
683 6f4d00ee 2013-09-23 0intro case DePlan9:
684 6f4d00ee 2013-09-23 0intro /* not valid in version >= 9 */
685 6f4d00ee 2013-09-23 0intro if(version >= 9)
687 6f4d00ee 2013-09-23 0intro if(dir->plan9 || nn != 12)
688 6f4d00ee 2013-09-23 0intro goto Err;
689 6f4d00ee 2013-09-23 0intro dir->plan9 = 1;
690 6f4d00ee 2013-09-23 0intro dir->p9path = U64GET(p);
691 6f4d00ee 2013-09-23 0intro dir->p9version = U32GET(p+8);
692 6f4d00ee 2013-09-23 0intro if(dir->mcount == 0)
693 6f4d00ee 2013-09-23 0intro dir->mcount = dir->p9version;
695 6f4d00ee 2013-09-23 0intro case DeGen:
696 6f4d00ee 2013-09-23 0intro /* not valid in version >= 9 */
697 6f4d00ee 2013-09-23 0intro if(version >= 9)
700 6f4d00ee 2013-09-23 0intro case DeQidSpace:
701 6f4d00ee 2013-09-23 0intro if(dir->qidSpace || nn != 16)
702 6f4d00ee 2013-09-23 0intro goto Err;
703 6f4d00ee 2013-09-23 0intro dir->qidSpace = 1;
704 6f4d00ee 2013-09-23 0intro dir->qidOffset = U64GET(p);
705 6f4d00ee 2013-09-23 0intro dir->qidMax = U64GET(p+8);
711 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: got options\n");
713 6f4d00ee 2013-09-23 0intro if(p != me->p + me->size)
714 6f4d00ee 2013-09-23 0intro goto Err;
716 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: correct size\n");
717 6f4d00ee 2013-09-23 0intro return 1;
719 6f4d00ee 2013-09-23 0intro if(0)print("deUnpack: XXXXXXXXXXXX EBadMeta\n");
720 4b576658 2013-09-23 0intro werrstr(EBadMeta);
721 6f4d00ee 2013-09-23 0intro deCleanup(dir);
722 6f4d00ee 2013-09-23 0intro return 0;
726 6f4d00ee 2013-09-23 0intro deCleanup(DirEntry *dir)
728 4b576658 2013-09-23 0intro vtfree(dir->elem);
729 6f4d00ee 2013-09-23 0intro dir->elem = nil;
730 4b576658 2013-09-23 0intro vtfree(dir->uid);
731 6f4d00ee 2013-09-23 0intro dir->uid = nil;
732 4b576658 2013-09-23 0intro vtfree(dir->gid);
733 6f4d00ee 2013-09-23 0intro dir->gid = nil;
734 4b576658 2013-09-23 0intro vtfree(dir->mid);
735 6f4d00ee 2013-09-23 0intro dir->mid = nil;
739 6f4d00ee 2013-09-23 0intro deCopy(DirEntry *dst, DirEntry *src)
741 6f4d00ee 2013-09-23 0intro *dst = *src;
742 4b576658 2013-09-23 0intro dst->elem = vtstrdup(src->elem);
743 4b576658 2013-09-23 0intro dst->uid = vtstrdup(src->uid);
744 4b576658 2013-09-23 0intro dst->gid = vtstrdup(src->gid);
745 4b576658 2013-09-23 0intro dst->mid = vtstrdup(src->mid);