#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;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)#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) voidheaderPack(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);} intheaderUnpack(Header *h, uchar *p){ if(U32GET(p) != HeaderMagic){ vtSetError("vac header bad magic"); return 0; } h->version = U16GET(p+4); if(h->version != HeaderVersion){ vtSetError("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;} voidlabelPack(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);} intlabelUnpack(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: vtSetError(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;} u32intglobalToLocal(uchar score[VtScoreSize]){ int i; for(i=0; i<VtScoreSize-4; i++) if(score[i] != 0) return NilBlock; return U32GET(score+VtScoreSize-4);} voidlocalToGlobal(u32int addr, uchar score[VtScoreSize]){ memset(score, 0, VtScoreSize-4); U32PUT(score+VtScoreSize-4, addr);} voidentryPack(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);} intentryUnpack(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;} intentryType(Entry *e){ return (((e->flags & VtEntryDir) != 0) << 3) | e->depth;} voidsuperPack(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));} intsuperUnpack(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)); vtSetError(EBadSuper); return 0;}
#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;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
#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){
vtSetError("vac header bad magic");
return 0;
}
h->version = U16GET(p+4);
if(h->version != HeaderVersion){
vtSetError("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:
vtSetError(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));
vtSetError(EBadSuper);
return 0;
}