aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/fossil/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/fossil/pack.c')
-rw-r--r--src/cmd/fossil/pack.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/cmd/fossil/pack.c b/src/cmd/fossil/pack.c
new file mode 100644
index 00000000..9fd2070c
--- /dev/null
+++ b/src/cmd/fossil/pack.c
@@ -0,0 +1,225 @@
+#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;
+}
+