shithub: gefs

ref: 6b02773727cc3b9c434ef1ce5bbd94dd6b706aef
dir: /pack.c/

View raw version
#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;
}