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