Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
4 #include "cvt.h"
6 static int
7 checksize(int n)
8 {
9 if(n < 256) {
10 werrstr("bad block size %#ux", n);
11 return -1;
12 }
13 return 0;
14 }
16 // _VtEntryBig integer format is floating-point:
17 // (n>>5) << (n&31).
18 // Convert this number; must be exact or return -1.
19 int
20 vttobig(ulong n)
21 {
22 int shift;
23 ulong n0;
25 n0 = n;
26 shift = 0;
27 while(n >= (1<<(16 - 5))) {
28 if(n & 1)
29 return -1;
30 shift++;
31 n >>= 1;
32 }
34 n = (n<<5) | shift;
35 if(((n>>5)<<(n&31)) != n0)
36 sysfatal("vttobig %#lux => %#lux failed", n0, n);
37 return n;
38 }
40 void
41 vtentrypack(VtEntry *e, uchar *p, int index)
42 {
43 ulong t32;
44 int flags;
45 uchar *op;
46 int depth;
47 int psize, dsize;
49 p += index * VtEntrySize;
50 op = p;
52 depth = e->type&VtTypeDepthMask;
53 flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask));
54 flags |= depth << _VtEntryDepthShift;
55 if(e->type - depth == VtDirType)
56 flags |= _VtEntryDir;
57 U32PUT(p, e->gen);
58 p += 4;
59 psize = e->psize;
60 dsize = e->dsize;
61 if(psize >= (1<<16) || dsize >= (1<<16)) {
62 flags |= _VtEntryBig;
63 psize = vttobig(psize);
64 dsize = vttobig(dsize);
65 if(psize < 0 || dsize < 0)
66 sysfatal("invalid entry psize/dsize: %ld/%ld", e->psize, e->dsize);
67 }
68 U16PUT(p, psize);
69 p += 2;
70 U16PUT(p, dsize);
71 p += 2;
72 U8PUT(p, flags);
73 p++;
74 memset(p, 0, 5);
75 p += 5;
76 U48PUT(p, e->size, t32);
77 p += 6;
78 memmove(p, e->score, VtScoreSize);
79 p += VtScoreSize;
81 assert(p-op == VtEntrySize);
82 }
84 int
85 vtentryunpack(VtEntry *e, uchar *p, int index)
86 {
87 uchar *op;
89 p += index * VtEntrySize;
90 op = p;
92 e->gen = U32GET(p);
93 p += 4;
94 e->psize = U16GET(p);
95 p += 2;
96 e->dsize = U16GET(p);
97 p += 2;
98 e->flags = U8GET(p);
99 p++;
100 if(e->flags & _VtEntryBig) {
101 e->psize = (e->psize>>5)<<(e->psize & 31);
102 e->dsize = (e->dsize>>5)<<(e->dsize & 31);
104 e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType;
105 e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift;
106 e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig);
107 p += 5;
108 e->size = U48GET(p);
109 p += 6;
110 memmove(e->score, p, VtScoreSize);
111 p += VtScoreSize;
113 assert(p-op == VtEntrySize);
115 if(!(e->flags & VtEntryActive))
116 return 0;
118 /*
119 * Some old vac files use psize==0 and dsize==0 when the
120 * file itself has size 0 or is zeros. Just to make programs not
121 * have to figure out what block sizes of 0 means, rewrite them.
122 */
123 if(e->psize == 0 && e->dsize == 0
124 && memcmp(e->score, vtzeroscore, VtScoreSize) == 0){
125 e->psize = 4096;
126 e->dsize = 4096;
128 if(checksize(e->psize) < 0 || checksize(e->dsize) < 0)
129 return -1;
131 return 0;