ref: 1b09060f468f530af2f4ef75441a40084e912e54
dir: /sys/src/cmd/gefs/pack.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <avl.h> #include "dat.h" #include "fns.h" /* Terminated so we can use them directly in C */ char* unpackstr(char *p, char *e, char **s) { int n; assert(e - p >= 3); n = UNPACK16(p); if(e - p < n + 3 || p[n+2] != 0) broke(Efs); *s = p+2; return p+3+n; } /* Terminated so we can use them directly in C */ char* packstr(char *p, char *e, char *s) { int n; n = strlen(s); assert(e - p >= n+3); PACK16(p, n); p += 2; memmove(p, s, n); p += n; *p = 0; p += 1; return p; } void dir2kv(vlong up, Xdir *d, Kvp *kv, char *buf, int nbuf) { char *ek, *ev, *eb; ek = packdkey(buf, nbuf, up, d->name); kv->k = buf; kv->nk = ek - buf; eb = buf + nbuf; ev = packdval(ek, eb - ek, d); kv->v = ek; kv->nv = ev - ek; } char* packdkey(char *p, int sz, vlong up, char *name) { char *ep; ep = p + sz; PACK8(p, Kent); p += 1; PACK64(p, up); p += 8; if(name != nil) p = packstr(p, ep, name); return p; } char* unpackdkey(char *p, int sz, vlong *up) { char key, *ep, *name; ep = p + sz; assert(sz > 9); key = UNPACK8(p); p += 1; *up = UNPACK64(p); p += 8; assert(key == Kent); p = unpackstr(p, ep, &name); assert(p <= ep); return name; } char* packsuper(char *p, int sz, vlong up) { char *ep; ep = p+sz; PACK8(p, Kup); p += 1; PACK64(p, up); p += 8; assert(p <= ep); return p; } char* packdval(char *p, int sz, Xdir *d) { char *e; e = p + sz; PACK64(p, d->flag); p += 8; PACK64(p, d->qid.path); p += 8; PACK32(p, d->qid.vers); p += 4; PACK8(p, d->qid.type); p += 1; PACK32(p, d->mode); p += 4; PACK64(p, d->atime); p += 8; PACK64(p, d->mtime); p += 8; PACK64(p, d->length); p += 8; PACK32(p, d->uid); p += 4; PACK32(p, d->gid); p += 4; PACK32(p, d->muid); p += 4; assert(p <= e); return p; } void kv2dir(Kvp *kv, Xdir *d) { char *k, *ek, *v, *ev; memset(d, 0, sizeof(Xdir)); k = kv->k + 9; ek = kv->k + kv->nk; k = unpackstr(k, ek, &d->name); v = kv->v; ev = v + kv->nv; d->flag = UNPACK64(v); v += 8; d->qid.path = UNPACK64(v); v += 8; d->qid.vers = UNPACK32(v); v += 4; d->qid.type = UNPACK8(v); v += 1; d->mode = UNPACK32(v); v += 4; d->atime = UNPACK64(v); v += 8; d->mtime = UNPACK64(v); v += 8; d->length = UNPACK64(v); v += 8; d->uid = UNPACK32(v); v += 4; d->gid = UNPACK32(v); v += 4; d->muid = UNPACK32(v); v += 4; assert(v <= ev); if(k != ek) broke(Efs); if(v != ev) broke(Efs); } int dir2statbuf(Xdir *d, char *buf, int nbuf) { int sz, nn, nu, ng, nm; vlong atime, mtime; User *u, *g, *m; char *p; rlock(&fs->userlk); if((u = uid2user(d->uid)) == nil) u = uid2user(noneid); if((g = uid2user(d->gid)) == nil) u = uid2user(nogroupid); if((m = uid2user(d->muid)) == nil) m = uid2user(noneid); if(u == nil || g == nil || m == nil) error(Eperm); p = buf; nn = strlen(d->name); nu = strlen(u->name); ng = strlen(g->name); nm = strlen(m->name); atime = (d->atime+Nsec/2)/Nsec; mtime = (d->mtime+Nsec/2)/Nsec; sz = STATFIXLEN + nn + nu + ng + nm; if(sz > nbuf){ runlock(&fs->userlk); return -1; } PBIT16(p, sz-2); p += 2; PBIT16(p, -1 /*type*/); p += 2; PBIT32(p, -1 /*dev*/); p += 4; PBIT8(p, d->qid.type); p += 1; PBIT32(p, d->qid.vers); p += 4; PBIT64(p, d->qid.path); p += 8; PBIT32(p, d->mode); p += 4; PBIT32(p, atime); p += 4; PBIT32(p, mtime); p += 4; PBIT64(p, d->length); p += 8; PBIT16(p, nn); p += 2; memcpy(p, d->name, nn); p += nn; PBIT16(p, nu); p += 2; memcpy(p, u->name, nu); p += nu; PBIT16(p, ng); p += 2; memcpy(p, g->name, ng); p += ng; PBIT16(p, nm); p += 2; memcpy(p, m->name, nm); p += nm; assert(p - buf == sz); runlock(&fs->userlk); return sz; } int kv2statbuf(Kvp *kv, char *buf, int nbuf) { Xdir d; kv2dir(kv, &d); return dir2statbuf(&d, buf, nbuf); } void kv2qid(Kvp *kv, Qid *q) { char *v, *e; v = kv->v; e = v + kv->nv; q->path = UNPACK64(v); v += 8; q->vers = UNPACK64(v); v += 8; assert(v <= e); } void kv2dlist(Kvp *kv, Dlist *dl) { char *p, *e; p = kv->k; e = p + kv->nk; p++; dl->gen = UNPACK64(p); p += 8; dl->bgen = UNPACK64(p); p += 8; assert(p <= e); p = kv->v; e = p + kv->nv; dl->hd = unpackbp(p, e-p); p += Ptrsz; dl->tl = unpackbp(p, e-p); p += Ptrsz; assert(p <= e); } void dlist2kv(Dlist *dl, Kvp *kv, char *buf, int nbuf) { char *p, *e; assert(nbuf >= Dlkvpsz); p = buf; e = buf+nbuf; kv->k = p; *p++ = Kdlist; PACK64(p, dl->gen); p += 8; PACK64(p, dl->bgen); p += 8; kv->nk = (p - kv->k); kv->v = p; p = packbp(p, e-p, &dl->hd); p = packbp(p, e-p, &dl->tl); kv->nv = (p - kv->v); } void tree2kv(Tree *t, Kvp *kv, char *buf, int nbuf) { char *p, *e; p = buf; e = buf+nbuf; kv->k = p; if((p = packsnap(p, e-p, t->gen)) == nil) abort(); kv->nk = p - kv->k; kv->v = p; if((p = packtree(p, e-p, t)) == nil) abort(); kv->nv = p - kv->v; } void retag2kv(vlong gen, vlong link, int dlbl, int dref, Kvp *kv, char *buf, int nbuf) { char *p; assert(nbuf >= 8+1+1); kv->k = buf; if((p = packsnap(buf, nbuf, gen)) == nil) abort(); kv->nk = p - buf; kv->v = p; PACK64(p, link); p += 8; *p = dlbl; p += 1; *p = dref; p += 1; kv->nv = p - kv->v; } void lbl2kv(char *lbl, vlong gen, uint flg, Kvp *kv, char *buf, int nbuf) { char *p; int n; n = strlen(lbl); assert(nbuf >= 1+n + 1+8+4); p = buf; kv->k = p; p[0] = Klabel; p += 1; memcpy(p, lbl, n); p += n; kv->nk = p - kv->k; kv->v = p; p[0] = Ksnap; p += 1; PACK64(p, gen); p += 8; PACK32(p, flg); p += 4; kv->nv = p - kv->v; } char* packlbl(char *p, int sz, char *name) { int n; n = strlen(name); assert(sz >= n+1); p[0] = Klabel; p += 1; memcpy(p, name, n); p += n; return p; } char* packsnap(char *p, int sz, vlong id) { assert(sz >= Snapsz); p[0] = Ksnap; p += 1; PACK64(p, id); p += 8; return p; } char* packbp(char *p, int sz, Bptr *bp) { assert(sz >= Ptrsz); PACK64(p, bp->addr); p += 8; PACK64(p, bp->hash); p += 8; PACK64(p, bp->gen); p += 8; return p; } Bptr unpackbp(char *p, int sz) { Bptr bp; assert(sz >= Ptrsz); bp.addr = UNPACK64(p); p += 8; bp.hash = UNPACK64(p); p += 8; bp.gen = UNPACK64(p); return bp; } Tree* unpacktree(Tree *t, char *p, int sz) { assert(sz >= Treesz); memset(t, 0, sizeof(Tree)); t->nref = UNPACK32(p); p += 4; t->nlbl = UNPACK32(p); p += 4; t->ht = UNPACK32(p); p += 4; t->flag = UNPACK32(p); p += 4; t->gen = UNPACK64(p); p += 8; t->pred = UNPACK64(p); p += 8; t->succ = UNPACK64(p); p += 8; t->base = UNPACK64(p); p += 8; t->bp.addr = UNPACK64(p); p += 8; t->bp.hash = UNPACK64(p); p += 8; t->bp.gen = UNPACK64(p); //p += 8; return t; } char* packtree(char *p, int sz, Tree *t) { assert(sz >= Treesz); PACK32(p, t->nref); p += 4; PACK32(p, t->nlbl); p += 4; PACK32(p, t->ht); p += 4; PACK32(p, t->flag); p += 4; PACK64(p, t->gen); p += 8; PACK64(p, t->pred); p += 8; PACK64(p, t->succ); p += 8; PACK64(p, t->base); p += 8; PACK64(p, t->bp.addr); p += 8; PACK64(p, t->bp.hash); p += 8; PACK64(p, t->bp.gen); p += 8; return p; } char* packarena(char *p, int sz, Arena *a) { char *e; assert(sz >= Arenasz); e = p + Arenasz; PACK64(p, a->loghd.addr); p += 8; /* freelist addr */ PACK64(p, a->loghd.hash); p += 8; /* freelist hash */ PACK64(p, a->size); p += 8; /* arena size */ PACK64(p, a->used); p += 8; /* arena used */ assert(p <= e); return p; } char* unpackarena(Arena *a, char *p, int sz) { char *e; assert(sz >= Arenasz); memset(a, 0, sizeof(*a)); e = p + Arenasz; a->loghd.addr = UNPACK64(p); p += 8; a->loghd.hash = UNPACK64(p); p += 8; a->loghd.gen = -1; p += 0; a->size = UNPACK64(p); p += 8; a->used = UNPACK64(p); p += 8; a->logtl = nil; assert(p <= e); return p; } char* packsb(char *p0, int sz, Gefs *fi) { uvlong h; char *p; int i; assert(sz == Blksz); assert(fi->narena < 512); p = p0; memcpy(p, "gefs9.00", 8); p += 8; PACK32(p, Blksz); p += 4; PACK32(p, Bufspc); p += 4; PACK32(p, fi->narena); p += 4; PACK32(p, fi->snap.ht); p += 4; PACK64(p, fi->snap.bp.addr); p += 8; PACK64(p, fi->snap.bp.hash); p += 8; PACK64(p, fi->snapdl.hd.addr); p += 8; PACK64(p, fi->snapdl.hd.hash); p += 8; PACK64(p, fi->snapdl.tl.addr); p += 8; PACK64(p, fi->snapdl.tl.hash); p += 8; PACK64(p, fi->flag); p += 8; PACK64(p, fi->nextqid); p += 8; PACK64(p, fi->nextgen); p += 8; PACK64(p, fi->qgen); p += 8; for(i = 0; i < fi->narena; i++){ PACK64(p, fi->arenabp[i].addr); p += 8; PACK64(p, fi->arenabp[i].hash); p += 8; } h = bufhash(p0, p - p0); PACK64(p, h); p += 8; return p; } char* unpacksb(Gefs *fi, char *p0, int sz) { uvlong dh, xh; char *p; int i; assert(sz == Blksz); p = p0; if(memcmp(p, "gefs9.00", 8) != 0) error("%s %.8s", Efsvers, p); p += 8; fi->blksz = UNPACK32(p); p += 4; fi->bufspc = UNPACK32(p); p += 4; fi->narena = UNPACK32(p); p += 4; fi->snap.ht = UNPACK32(p); p += 4; fi->snap.bp.addr = UNPACK64(p); p += 8; fi->snap.bp.hash = UNPACK64(p); p += 8; fi->snap.bp.gen = -1; p += 0; fi->snapdl.hd.addr = UNPACK64(p); p += 8; fi->snapdl.hd.hash = UNPACK64(p); p += 8; fi->snapdl.hd.gen = -1; p += 0; fi->snapdl.gen = -1; p += 0; fi->snapdl.tl.addr = UNPACK64(p); p += 8; fi->snapdl.tl.hash = UNPACK64(p); p += 8; fi->snapdl.hd.gen = -1; p += 0; fi->snapdl.gen = -1; p += 0; fi->flag = UNPACK64(p); p += 8; fi->nextqid = UNPACK64(p); p += 8; fi->nextgen = UNPACK64(p); p += 8; fi->qgen = UNPACK64(p); p += 8; fi->arenabp = emalloc(fi->narena * sizeof(Bptr), 0); for(i = 0; i < fi->narena; i++){ fi->arenabp[i].addr = UNPACK64(p); p += 8; fi->arenabp[i].hash = UNPACK64(p); p += 8; fi->arenabp[i].gen = -1; } xh = bufhash(p0, p - p0); dh = UNPACK64(p); p += 8; if(dh != xh) error("corrupt superblock: %llx != %llx", dh, xh); assert(fi->narena < 256); /* should be more than anyone needs */ return p; }