| #include "stdinc.h" |
| #include "dat.h" |
| #include "fns.h" |
| #include "error.h" |
| |
| /* |
| * integer conversion routines |
| */ |
| #define U8GET(p) ((p)[0]) |
| #define U16GET(p) (((p)[0]<<8)|(p)[1]) |
| #define U32GET(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]) |
| #define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2)) |
| #define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4)) |
| |
| #define U8PUT(p,v) (p)[0]=(v) |
| #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v) |
| #define U32PUT(p,v) (p)[0]=((v)>>24)&0xFF;(p)[1]=((v)>>16)&0xFF;(p)[2]=((v)>>8)&0xFF;(p)[3]=(v)&0xFF |
| #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32) |
| #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32) |
| |
| void |
| headerPack(Header *h, uchar *p) |
| { |
| memset(p, 0, HeaderSize); |
| U32PUT(p, HeaderMagic); |
| U16PUT(p+4, HeaderVersion); |
| U16PUT(p+6, h->blockSize); |
| U32PUT(p+8, h->super); |
| U32PUT(p+12, h->label); |
| U32PUT(p+16, h->data); |
| U32PUT(p+20, h->end); |
| } |
| |
| int |
| headerUnpack(Header *h, uchar *p) |
| { |
| if(U32GET(p) != HeaderMagic){ |
| werrstr("vac header bad magic"); |
| return 0; |
| } |
| h->version = U16GET(p+4); |
| if(h->version != HeaderVersion){ |
| werrstr("vac header bad version"); |
| return 0; |
| } |
| h->blockSize = U16GET(p+6); |
| h->super = U32GET(p+8); |
| h->label = U32GET(p+12); |
| h->data = U32GET(p+16); |
| h->end = U32GET(p+20); |
| return 1; |
| } |
| |
| void |
| labelPack(Label *l, uchar *p, int i) |
| { |
| p += i*LabelSize; |
| U8PUT(p, l->state); |
| U8PUT(p+1, l->type); |
| U32PUT(p+2, l->epoch); |
| U32PUT(p+6, l->epochClose); |
| U32PUT(p+10, l->tag); |
| } |
| |
| int |
| labelUnpack(Label *l, uchar *p, int i) |
| { |
| p += i*LabelSize; |
| l->state = p[0]; |
| l->type = p[1]; |
| l->epoch = U32GET(p+2); |
| l->epochClose = U32GET(p+6); |
| l->tag = U32GET(p+10); |
| |
| if(l->type > BtMax){ |
| Bad: |
| werrstr(EBadLabel); |
| fprint(2, "%s: labelUnpack: bad label: 0x%.2ux 0x%.2ux 0x%.8ux " |
| "0x%.8ux 0x%.8ux\n", argv0, l->state, l->type, l->epoch, |
| l->epochClose, l->tag); |
| return 0; |
| } |
| if(l->state != BsBad && l->state != BsFree){ |
| if(!(l->state&BsAlloc) || l->state & ~BsMask) |
| goto Bad; |
| if(l->state&BsClosed){ |
| if(l->epochClose == ~(u32int)0) |
| goto Bad; |
| }else{ |
| if(l->epochClose != ~(u32int)0) |
| goto Bad; |
| } |
| } |
| return 1; |
| } |
| |
| u32int |
| globalToLocal(uchar score[VtScoreSize]) |
| { |
| int i; |
| |
| for(i=0; i<VtScoreSize-4; i++) |
| if(score[i] != 0) |
| return NilBlock; |
| |
| return U32GET(score+VtScoreSize-4); |
| } |
| |
| void |
| localToGlobal(u32int addr, uchar score[VtScoreSize]) |
| { |
| memset(score, 0, VtScoreSize-4); |
| U32PUT(score+VtScoreSize-4, addr); |
| } |
| |
| void |
| entryPack(Entry *e, uchar *p, int index) |
| { |
| ulong t32; |
| int flags; |
| |
| p += index * VtEntrySize; |
| |
| U32PUT(p, e->gen); |
| U16PUT(p+4, e->psize); |
| U16PUT(p+6, e->dsize); |
| flags = e->flags | ((e->depth << _VtEntryDepthShift) & _VtEntryDepthMask); |
| U8PUT(p+8, flags); |
| memset(p+9, 0, 5); |
| U48PUT(p+14, e->size, t32); |
| |
| if(flags & VtEntryLocal){ |
| if(globalToLocal(e->score) == NilBlock) |
| abort(); |
| memset(p+20, 0, 7); |
| U8PUT(p+27, e->archive); |
| U32PUT(p+28, e->snap); |
| U32PUT(p+32, e->tag); |
| memmove(p+36, e->score+16, 4); |
| }else |
| memmove(p+20, e->score, VtScoreSize); |
| } |
| |
| int |
| entryUnpack(Entry *e, uchar *p, int index) |
| { |
| p += index * VtEntrySize; |
| |
| e->gen = U32GET(p); |
| e->psize = U16GET(p+4); |
| e->dsize = U16GET(p+6); |
| e->flags = U8GET(p+8); |
| e->depth = (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift; |
| e->flags &= ~_VtEntryDepthMask; |
| e->size = U48GET(p+14); |
| |
| if(e->flags & VtEntryLocal){ |
| e->archive = p[27]; |
| e->snap = U32GET(p+28); |
| e->tag = U32GET(p+32); |
| memset(e->score, 0, 16); |
| memmove(e->score+16, p+36, 4); |
| }else{ |
| e->archive = 0; |
| e->snap = 0; |
| e->tag = 0; |
| memmove(e->score, p+20, VtScoreSize); |
| } |
| |
| return 1; |
| } |
| |
| int |
| entryType(Entry *e) |
| { |
| return (((e->flags & _VtEntryDir) != 0) << 3) | e->depth; |
| } |
| |
| |
| void |
| superPack(Super *s, uchar *p) |
| { |
| u32int t32; |
| |
| memset(p, 0, SuperSize); |
| U32PUT(p, SuperMagic); |
| assert(s->version == SuperVersion); |
| U16PUT(p+4, s->version); |
| U32PUT(p+6, s->epochLow); |
| U32PUT(p+10, s->epochHigh); |
| U64PUT(p+14, s->qid, t32); |
| U32PUT(p+22, s->active); |
| U32PUT(p+26, s->next); |
| U32PUT(p+30, s->current); |
| memmove(p+34, s->last, VtScoreSize); |
| memmove(p+54, s->name, sizeof(s->name)); |
| } |
| |
| int |
| superUnpack(Super *s, uchar *p) |
| { |
| memset(s, 0, sizeof(*s)); |
| if(U32GET(p) != SuperMagic) |
| goto Err; |
| s->version = U16GET(p+4); |
| if(s->version != SuperVersion) |
| goto Err; |
| s->epochLow = U32GET(p+6); |
| s->epochHigh = U32GET(p+10); |
| s->qid = U64GET(p+14); |
| if(s->epochLow == 0 || s->epochLow > s->epochHigh || s->qid == 0) |
| goto Err; |
| s->active = U32GET(p+22); |
| s->next = U32GET(p+26); |
| s->current = U32GET(p+30); |
| memmove(s->last, p+34, VtScoreSize); |
| memmove(s->name, p+54, sizeof(s->name)); |
| s->name[sizeof(s->name)-1] = 0; |
| return 1; |
| Err: |
| memset(s, 0, sizeof(*s)); |
| werrstr(EBadSuper); |
| return 0; |
| } |
| |