entry.c (2550B)
1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 #include "cvt.h" 5 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 } 15 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; 24 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 } 33 34 n = (n<<5) | shift; 35 if(((n>>5)<<(n&31)) != n0) 36 sysfatal("vttobig %#lux => %#lux failed", n0, n); 37 return n; 38 } 39 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; 48 49 p += index * VtEntrySize; 50 op = p; 51 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; 80 81 assert(p-op == VtEntrySize); 82 } 83 84 int 85 vtentryunpack(VtEntry *e, uchar *p, int index) 86 { 87 uchar *op; 88 89 p += index * VtEntrySize; 90 op = p; 91 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); 103 } 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; 112 113 assert(p-op == VtEntrySize); 114 115 if(!(e->flags & VtEntryActive)) 116 return 0; 117 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; 127 } 128 if(checksize(e->psize) < 0 || checksize(e->dsize) < 0) 129 return -1; 130 131 return 0; 132 }