ref: f0563cbdbce1777d5672fee507acac7ab0d6dbc0
dir: /pack.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <avl.h> #include <bio.h> #include "dat.h" #include "fns.h" char* unpack8(int *err, char *p, char *e, void *v) { if (e - p < 1 || *err){ *err = 1; return p; } *(uchar*)v = p[0]; return p+1; } char* unpack16(int *err, char *p, char *e, void *v) { if (e - p < 2 || *err){ *err = 1; return p; } *(ushort*)v = GBIT16(p); return p+2; } char* unpack32(int *err, char *p, char *e, void *v) { if (e - p < 4 || *err){ *err = 1; return p; } *(uint*)v = GBIT32(p); return p+4; } char* unpack64(int *err, char *p, char *e, void *v) { if (e - p < 8 || *err){ *err = 1; return p; } *(uvlong*)v = GBIT64(p); return p+8; } /* Terminated so we can use them directly in C */ char* unpackstr(int *err, char *p, char *e, char **s) { int n; if (e - p < 3 || *err){ *err = 1; return p; } n = GBIT16(p); if(e - p < n + 3 || p[n+2] != 0){ *err = 1; return p; } *s = p+2; return p+3+n; } char* pack8(int *err, char *p, char *e, uchar v) { if (e - p < 1 || *err){ *err = 1; return p; } p[0] = v; return p+1; } char* pack16(int *err, char *p, char *e, ushort v) { if (e - p < 2 || *err){ *err = 1; return p; } PBIT16(p, v); return p+2; } char* pack32(int *err, char *p, char *e, uint v) { if (e - p < 4 || *err){ *err = 1; return p; } PBIT32(p, v); return p+4; } char* pack64(int *err, char *p, char *e, uvlong v) { if (e - p < 8 || *err){ *err = 1; return p; } PBIT64(p, v); return p+8; } /* Terminated so we can use them directly in C */ char* packstr(int *err, char *p, char *e, char *s) { int n; n = strlen(s); if (e - p < n+3 || *err){ *err = 1; return p; } PBIT16(p+0, n); memcpy(p+2, s, n); p[2+n] = 0; return p+3+n; } int dir2kv(vlong up, Dir *d, Kvp *kv, char *buf, int nbuf) { char *k, *ek, *v, *ev, *eb; int err; err = 0; k = buf; ek = buf; eb = buf + nbuf; ek = pack8(&err, ek, eb, Kent); ek = pack64(&err, ek, eb, up); ek = packstr(&err, ek, eb, d->name); v = ek; ev = ek; ev = pack64(&err, ev, eb, d->qid.path); ev = pack32(&err, ev, eb, d->qid.vers); ev = pack8(&err, ev, eb, d->qid.type); ev = pack32(&err, ev, eb, d->mode); ev = pack64(&err, ev, eb, d->atime*Nsec); ev = pack64(&err, ev, eb, d->mtime*Nsec); ev = pack64(&err, ev, eb, d->length); ev = packstr(&err, ev, eb, d->uid); ev = packstr(&err, ev, eb, d->gid); ev = packstr(&err, ev, eb, d->muid); if(err){ werrstr("stat too big: %.*s...", 32, d->name); return -1; } kv->type = Vinl; kv->k = k; kv->nk = ek - k; kv->v = v; kv->nv = ev - v; return 0; } int name2dkey(vlong up, char *name, Key *k, char *buf, int nbuf) { char *ek, *eb; int err; err = 0; ek = buf; eb = buf + nbuf; ek = pack8(&err, ek, eb, Kent); ek = pack64(&err, ek, eb, up); ek = packstr(&err, ek, eb, name); if(err) return -1; k->k = buf; k->nk = ek - buf; return k->nk; } int kv2dir(Kvp *kv, Dir *d) { char *k, *ek, *v, *ev; vlong atime, mtime; int err; err = 0; k = kv->k + 9; ek = kv->k + kv->nk; dprint("unpacking... [%d %d]\n", k[0], k[1]); k = unpackstr(&err, k, ek, &d->name); v = kv->v; ev = v + kv->nv; v = unpack64(&err, v, ev, &d->qid.path); v = unpack32(&err, v, ev, &d->qid.vers); v = unpack8(&err, v, ev, &d->qid.type); v = unpack32(&err, v, ev, &d->mode); v = unpack64(&err, v, ev, &atime); v = unpack64(&err, v, ev, &mtime); v = unpack64(&err, v, ev, &d->length); v = unpackstr(&err, v, ev, &d->uid); v = unpackstr(&err, v, ev, &d->gid); v = unpackstr(&err, v, ev, &d->muid); if(err){ werrstr("kv too small"); return -1; } if(k != ek){ werrstr("invalid path"); return -1; } if(v != ev){ werrstr("stat full of fuck"); return -1; } d->atime = (atime+Nsec/2)/Nsec; d->mtime = (mtime+Nsec/2)/Nsec; return 0; } int kv2statbuf(Kvp *kv, char *buf, int nbuf) { Dir d; int n; if(kv2dir(kv, &d) == -1) return -1; dprint("have %d bytes to pack into\n", nbuf); if((n = convD2M(&d, (uchar*)buf, nbuf)) <= BIT16SZ){ fprint(2, "here...failed convert??, needed %d\n", GBIT16(buf)); return -1; } return n; } int kv2qid(Kvp *kv, Qid *q) { char *v, *ev; int err; err = 0; v = kv->v; ev = v + kv->nv; v = unpack64(&err, v, ev, &q->path); v = unpack32(&err, v, ev, &q->vers); unpack8(&err, v, ev, &q->type); if(err){ werrstr("kv too small"); return -1; } return 0; }