15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "dat.h"
35e96a66cSDavid du Colombier #include "fns.h"
45e96a66cSDavid du Colombier #include "error.h"
55e96a66cSDavid du Colombier
65e96a66cSDavid du Colombier /*
75e96a66cSDavid du Colombier * integer conversion routines
85e96a66cSDavid du Colombier */
95e96a66cSDavid du Colombier #define U8GET(p) ((p)[0])
105e96a66cSDavid du Colombier #define U16GET(p) (((p)[0]<<8)|(p)[1])
115e96a66cSDavid du Colombier #define U32GET(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
125e96a66cSDavid du Colombier #define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
135e96a66cSDavid du Colombier #define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
145e96a66cSDavid du Colombier
155e96a66cSDavid du Colombier #define U8PUT(p,v) (p)[0]=(v)
165e96a66cSDavid du Colombier #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
175e96a66cSDavid du Colombier #define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
185e96a66cSDavid du Colombier #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
195e96a66cSDavid du Colombier #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
205e96a66cSDavid du Colombier
215e96a66cSDavid du Colombier void
headerPack(Header * h,uchar * p)225e96a66cSDavid du Colombier headerPack(Header *h, uchar *p)
235e96a66cSDavid du Colombier {
245e96a66cSDavid du Colombier memset(p, 0, HeaderSize);
255e96a66cSDavid du Colombier U32PUT(p, HeaderMagic);
265e96a66cSDavid du Colombier U16PUT(p+4, HeaderVersion);
275e96a66cSDavid du Colombier U16PUT(p+6, h->blockSize);
285e96a66cSDavid du Colombier U32PUT(p+8, h->super);
295e96a66cSDavid du Colombier U32PUT(p+12, h->label);
305e96a66cSDavid du Colombier U32PUT(p+16, h->data);
315e96a66cSDavid du Colombier U32PUT(p+20, h->end);
325e96a66cSDavid du Colombier }
335e96a66cSDavid du Colombier
345e96a66cSDavid du Colombier int
headerUnpack(Header * h,uchar * p)355e96a66cSDavid du Colombier headerUnpack(Header *h, uchar *p)
365e96a66cSDavid du Colombier {
375e96a66cSDavid du Colombier if(U32GET(p) != HeaderMagic){
385e96a66cSDavid du Colombier vtSetError("vac header bad magic");
395e96a66cSDavid du Colombier return 0;
405e96a66cSDavid du Colombier }
415e96a66cSDavid du Colombier h->version = U16GET(p+4);
425e96a66cSDavid du Colombier if(h->version != HeaderVersion){
435e96a66cSDavid du Colombier vtSetError("vac header bad version");
445e96a66cSDavid du Colombier return 0;
455e96a66cSDavid du Colombier }
465e96a66cSDavid du Colombier h->blockSize = U16GET(p+6);
475e96a66cSDavid du Colombier h->super = U32GET(p+8);
485e96a66cSDavid du Colombier h->label = U32GET(p+12);
495e96a66cSDavid du Colombier h->data = U32GET(p+16);
505e96a66cSDavid du Colombier h->end = U32GET(p+20);
515e96a66cSDavid du Colombier return 1;
525e96a66cSDavid du Colombier }
535e96a66cSDavid du Colombier
545e96a66cSDavid du Colombier void
labelPack(Label * l,uchar * p,int i)555e96a66cSDavid du Colombier labelPack(Label *l, uchar *p, int i)
565e96a66cSDavid du Colombier {
575e96a66cSDavid du Colombier p += i*LabelSize;
585e96a66cSDavid du Colombier U8PUT(p, l->state);
595e96a66cSDavid du Colombier U8PUT(p+1, l->type);
605e96a66cSDavid du Colombier U32PUT(p+2, l->epoch);
615e96a66cSDavid du Colombier U32PUT(p+6, l->epochClose);
625e96a66cSDavid du Colombier U32PUT(p+10, l->tag);
635e96a66cSDavid du Colombier }
645e96a66cSDavid du Colombier
655e96a66cSDavid du Colombier int
labelUnpack(Label * l,uchar * p,int i)665e96a66cSDavid du Colombier labelUnpack(Label *l, uchar *p, int i)
675e96a66cSDavid du Colombier {
685e96a66cSDavid du Colombier p += i*LabelSize;
695e96a66cSDavid du Colombier l->state = p[0];
705e96a66cSDavid du Colombier l->type = p[1];
715e96a66cSDavid du Colombier l->epoch = U32GET(p+2);
725e96a66cSDavid du Colombier l->epochClose = U32GET(p+6);
735e96a66cSDavid du Colombier l->tag = U32GET(p+10);
745e96a66cSDavid du Colombier
755e96a66cSDavid du Colombier if(l->type > BtMax){
765e96a66cSDavid du Colombier Bad:
775e96a66cSDavid du Colombier vtSetError(EBadLabel);
78*c168f9f3SDavid du Colombier fprint(2, "%s: labelUnpack: bad label: 0x%.2ux 0x%.2ux 0x%.8ux "
79*c168f9f3SDavid du Colombier "0x%.8ux 0x%.8ux\n", argv0, l->state, l->type, l->epoch,
80*c168f9f3SDavid du Colombier l->epochClose, l->tag);
815e96a66cSDavid du Colombier return 0;
825e96a66cSDavid du Colombier }
835e96a66cSDavid du Colombier if(l->state != BsBad && l->state != BsFree){
84*c168f9f3SDavid du Colombier if(!(l->state&BsAlloc) || l->state & ~BsMask)
855e96a66cSDavid du Colombier goto Bad;
865e96a66cSDavid du Colombier if(l->state&BsClosed){
875e96a66cSDavid du Colombier if(l->epochClose == ~(u32int)0)
885e96a66cSDavid du Colombier goto Bad;
895e96a66cSDavid du Colombier }else{
905e96a66cSDavid du Colombier if(l->epochClose != ~(u32int)0)
915e96a66cSDavid du Colombier goto Bad;
925e96a66cSDavid du Colombier }
935e96a66cSDavid du Colombier }
945e96a66cSDavid du Colombier return 1;
955e96a66cSDavid du Colombier }
965e96a66cSDavid du Colombier
975e96a66cSDavid du Colombier u32int
globalToLocal(uchar score[VtScoreSize])985e96a66cSDavid du Colombier globalToLocal(uchar score[VtScoreSize])
995e96a66cSDavid du Colombier {
1005e96a66cSDavid du Colombier int i;
1015e96a66cSDavid du Colombier
1025e96a66cSDavid du Colombier for(i=0; i<VtScoreSize-4; i++)
1035e96a66cSDavid du Colombier if(score[i] != 0)
1045e96a66cSDavid du Colombier return NilBlock;
1055e96a66cSDavid du Colombier
1065e96a66cSDavid du Colombier return U32GET(score+VtScoreSize-4);
1075e96a66cSDavid du Colombier }
1085e96a66cSDavid du Colombier
1095e96a66cSDavid du Colombier void
localToGlobal(u32int addr,uchar score[VtScoreSize])1105e96a66cSDavid du Colombier localToGlobal(u32int addr, uchar score[VtScoreSize])
1115e96a66cSDavid du Colombier {
1125e96a66cSDavid du Colombier memset(score, 0, VtScoreSize-4);
1135e96a66cSDavid du Colombier U32PUT(score+VtScoreSize-4, addr);
1145e96a66cSDavid du Colombier }
1155e96a66cSDavid du Colombier
1165e96a66cSDavid du Colombier void
entryPack(Entry * e,uchar * p,int index)1175e96a66cSDavid du Colombier entryPack(Entry *e, uchar *p, int index)
1185e96a66cSDavid du Colombier {
1195e96a66cSDavid du Colombier ulong t32;
1205e96a66cSDavid du Colombier int flags;
1215e96a66cSDavid du Colombier
1225e96a66cSDavid du Colombier p += index * VtEntrySize;
1235e96a66cSDavid du Colombier
1245e96a66cSDavid du Colombier U32PUT(p, e->gen);
1255e96a66cSDavid du Colombier U16PUT(p+4, e->psize);
1265e96a66cSDavid du Colombier U16PUT(p+6, e->dsize);
1275e96a66cSDavid du Colombier flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
1285e96a66cSDavid du Colombier U8PUT(p+8, flags);
1295e96a66cSDavid du Colombier memset(p+9, 0, 5);
1305e96a66cSDavid du Colombier U48PUT(p+14, e->size, t32);
1315e96a66cSDavid du Colombier
1325e96a66cSDavid du Colombier if(flags & VtEntryLocal){
1335e96a66cSDavid du Colombier if(globalToLocal(e->score) == NilBlock)
1345e96a66cSDavid du Colombier abort();
1355e96a66cSDavid du Colombier memset(p+20, 0, 7);
1365e96a66cSDavid du Colombier U8PUT(p+27, e->archive);
1375e96a66cSDavid du Colombier U32PUT(p+28, e->snap);
1385e96a66cSDavid du Colombier U32PUT(p+32, e->tag);
1395e96a66cSDavid du Colombier memmove(p+36, e->score+16, 4);
1405e96a66cSDavid du Colombier }else
1415e96a66cSDavid du Colombier memmove(p+20, e->score, VtScoreSize);
1425e96a66cSDavid du Colombier }
1435e96a66cSDavid du Colombier
1445e96a66cSDavid du Colombier int
entryUnpack(Entry * e,uchar * p,int index)1455e96a66cSDavid du Colombier entryUnpack(Entry *e, uchar *p, int index)
1465e96a66cSDavid du Colombier {
1475e96a66cSDavid du Colombier p += index * VtEntrySize;
1485e96a66cSDavid du Colombier
1495e96a66cSDavid du Colombier e->gen = U32GET(p);
1505e96a66cSDavid du Colombier e->psize = U16GET(p+4);
1515e96a66cSDavid du Colombier e->dsize = U16GET(p+6);
1525e96a66cSDavid du Colombier e->flags = U8GET(p+8);
1535e96a66cSDavid du Colombier e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
1545e96a66cSDavid du Colombier e->flags &= ~VtEntryDepthMask;
1555e96a66cSDavid du Colombier e->size = U48GET(p+14);
1565e96a66cSDavid du Colombier
1575e96a66cSDavid du Colombier if(e->flags & VtEntryLocal){
1585e96a66cSDavid du Colombier e->archive = p[27];
1595e96a66cSDavid du Colombier e->snap = U32GET(p+28);
1605e96a66cSDavid du Colombier e->tag = U32GET(p+32);
1615e96a66cSDavid du Colombier memset(e->score, 0, 16);
1625e96a66cSDavid du Colombier memmove(e->score+16, p+36, 4);
1635e96a66cSDavid du Colombier }else{
1645e96a66cSDavid du Colombier e->archive = 0;
1655e96a66cSDavid du Colombier e->snap = 0;
1665e96a66cSDavid du Colombier e->tag = 0;
1675e96a66cSDavid du Colombier memmove(e->score, p+20, VtScoreSize);
1685e96a66cSDavid du Colombier }
1695e96a66cSDavid du Colombier
1705e96a66cSDavid du Colombier return 1;
1715e96a66cSDavid du Colombier }
1725e96a66cSDavid du Colombier
1735e96a66cSDavid du Colombier int
entryType(Entry * e)1745e96a66cSDavid du Colombier entryType(Entry *e)
1755e96a66cSDavid du Colombier {
1765e96a66cSDavid du Colombier return (((e->flags & VtEntryDir) != 0) << 3) | e->depth;
1775e96a66cSDavid du Colombier }
1785e96a66cSDavid du Colombier
1795e96a66cSDavid du Colombier
1805e96a66cSDavid du Colombier void
superPack(Super * s,uchar * p)1815e96a66cSDavid du Colombier superPack(Super *s, uchar *p)
1825e96a66cSDavid du Colombier {
1835e96a66cSDavid du Colombier u32int t32;
1845e96a66cSDavid du Colombier
1855e96a66cSDavid du Colombier memset(p, 0, SuperSize);
1865e96a66cSDavid du Colombier U32PUT(p, SuperMagic);
1875e96a66cSDavid du Colombier assert(s->version == SuperVersion);
1885e96a66cSDavid du Colombier U16PUT(p+4, s->version);
1895e96a66cSDavid du Colombier U32PUT(p+6, s->epochLow);
1905e96a66cSDavid du Colombier U32PUT(p+10, s->epochHigh);
1915e96a66cSDavid du Colombier U64PUT(p+14, s->qid, t32);
1925e96a66cSDavid du Colombier U32PUT(p+22, s->active);
1935e96a66cSDavid du Colombier U32PUT(p+26, s->next);
1945e96a66cSDavid du Colombier U32PUT(p+30, s->current);
1955e96a66cSDavid du Colombier memmove(p+34, s->last, VtScoreSize);
1965e96a66cSDavid du Colombier memmove(p+54, s->name, sizeof(s->name));
1975e96a66cSDavid du Colombier }
1985e96a66cSDavid du Colombier
1995e96a66cSDavid du Colombier int
superUnpack(Super * s,uchar * p)2005e96a66cSDavid du Colombier superUnpack(Super *s, uchar *p)
2015e96a66cSDavid du Colombier {
2025e96a66cSDavid du Colombier memset(s, 0, sizeof(*s));
2035e96a66cSDavid du Colombier if(U32GET(p) != SuperMagic)
2045e96a66cSDavid du Colombier goto Err;
2055e96a66cSDavid du Colombier s->version = U16GET(p+4);
2065e96a66cSDavid du Colombier if(s->version != SuperVersion)
2075e96a66cSDavid du Colombier goto Err;
2085e96a66cSDavid du Colombier s->epochLow = U32GET(p+6);
2095e96a66cSDavid du Colombier s->epochHigh = U32GET(p+10);
2105e96a66cSDavid du Colombier s->qid = U64GET(p+14);
2115e96a66cSDavid du Colombier if(s->epochLow == 0 || s->epochLow > s->epochHigh || s->qid == 0)
2125e96a66cSDavid du Colombier goto Err;
2135e96a66cSDavid du Colombier s->active = U32GET(p+22);
2145e96a66cSDavid du Colombier s->next = U32GET(p+26);
2155e96a66cSDavid du Colombier s->current = U32GET(p+30);
2165e96a66cSDavid du Colombier memmove(s->last, p+34, VtScoreSize);
2175e96a66cSDavid du Colombier memmove(s->name, p+54, sizeof(s->name));
2185e96a66cSDavid du Colombier s->name[sizeof(s->name)-1] = 0;
2195e96a66cSDavid du Colombier return 1;
2205e96a66cSDavid du Colombier Err:
2215e96a66cSDavid du Colombier memset(s, 0, sizeof(*s));
2225e96a66cSDavid du Colombier vtSetError(EBadSuper);
2235e96a66cSDavid du Colombier return 0;
2245e96a66cSDavid du Colombier }
2255e96a66cSDavid du Colombier
226