Plan 9 from Bell Labs’s /usr/web/sources/contrib/cinap_lenrek/delorean/delorean.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>

enum 
{
	Qroot,
	Qtime,
	Qbintime,
	Nqid,
};

enum
{
	NUMSIZE = 12,
	VLNUMSIZE = 22,
};

int		bintimefd;
vlong	nsecdiff = 0;

int
fillstat(ulong qid, Dir *d)
{
	memset(d, 0, sizeof(Dir));

	d->uid = "marty";
	d->gid = "mcfly";
	d->muid = "";
	d->qid = (Qid){qid, 0, 0};
	d->atime = time(0);

	switch(qid) {
	case Qroot:
		d->name = "/";
		d->qid.type = QTDIR;
		d->mode = DMDIR|0777;
		break;
	case Qtime:
		d->name = "time";
		d->mode = 0666;
		break;
	case Qbintime:
		d->name = "bintime";
		d->mode = 0666;
		break;
	}
	return 1;
}


int
readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
{
	int i, m, n;
	long pos;
	Dir d;

	n = 0;
	pos = 0;
	for (i = 1; i < Nqid; i++){
		fillstat(i, &d);
		m = convD2M(&d, &buf[n], blen-n);
		if(off <= pos){
			if(m <= BIT16SZ || m > cnt)
				break;
			n += m;
			cnt -= m;
		}
		pos += m;
	}
	return n;
}

static void
fsattach(Req *r)
{
	char *spec;

	spec = r->ifcall.aname;
	if(spec && spec[0]) {
		respond(r, "invalid attach specifier");
		return;
	}

	r->fid->qid = (Qid){Qroot, 0, QTDIR};
	r->ofcall.qid = r->fid->qid;
	respond(r, nil);
}

static void
fsstat(Req *r)
{
	fillstat((ulong)r->fid->qid.path, &r->d);

	r->d.name = estrdup9p(r->d.name);
	r->d.uid = estrdup9p(r->d.uid);
	r->d.gid = estrdup9p(r->d.gid);
	r->d.muid = estrdup9p(r->d.muid);

	respond(r, nil);
}

static char*
fswalk1(Fid *fid, char *name, Qid *qid)
{
	switch((ulong)fid->qid.path) {
	case Qroot:
		if (strcmp(name, "..") == 0) {
			*qid = (Qid){Qroot, 0, QTDIR};
			fid->qid = *qid;
			return nil;
		}
		if (strcmp(name, "time") == 0) {
			*qid = (Qid){Qtime, 0, 0};
			fid->qid = *qid;
			return nil;
		}
		if (strcmp(name, "bintime") == 0) {
			*qid = (Qid){Qbintime, 0, 0};
			fid->qid = *qid;
			return nil;
		}
		return "file not found";
		
	default:
		return "walk in non-directory";
	}
}

static void
fsopen(Req *r)
{
	int omode;
	Fid *fid;
	ulong path;

	fid = r->fid;
	path = (ulong)fid->qid.path;
	omode = r->ifcall.mode;
	
	if(path == Qroot){
		if (omode == OREAD)
			respond(r, nil);
		else
			respond(r, "permission denied");
		return;
	}
	respond(r, nil);
}

static uvlong uvorder = 0x0001020304050607ULL;

static uchar*
le2vlong(vlong *to, uchar *f)
{
	uchar *t, *o;
	int i;

	t = (uchar*)to;
	o = (uchar*)&uvorder;
	for(i = 0; i < sizeof(vlong); i++)
		t[o[i]] = f[i];
	return f+sizeof(vlong);
}

static uchar*
vlong2le(uchar *t, vlong from)
{
	uchar *f, *o;
	int i;

	f = (uchar*)&from;
	o = (uchar*)&uvorder;
	for(i = 0; i < sizeof(vlong); i++)
		t[i] = f[o[i]];
	return t+sizeof(vlong);
}

static void
fsread(Req *r)
{
	uchar *b;
	vlong x, t, h;
	int n, i;
	char str[7*NUMSIZE];
	uchar buf[24];

	if(pread(bintimefd, buf, sizeof(buf), 0) != sizeof(buf)){
		responderror(r);
		return;
	}

	le2vlong(&x, buf);
	le2vlong(&t, buf+8);
	le2vlong(&h, buf+16);

	x -= nsecdiff;

	switch((ulong)r->fid->qid.path) {
	case Qroot:
		r->ofcall.count = readtopdir(r->fid, (void*)r->ofcall.data, r->ifcall.offset,
			r->ifcall.count, r->ifcall.count);
		respond(r, nil);
		return;

	case Qtime:
		snprint(str, sizeof(str), "%*lud %*llud %*llud %*llud ",
			NUMSIZE-1, (long)(x/1000000000LL),
			VLNUMSIZE-1, x,
			VLNUMSIZE-1, t,
			VLNUMSIZE-1, h);
		readstr(r, str);
		respond(r, nil);
		return;

	case Qbintime:
		b = (uchar*)r->ofcall.data;
		n = r->ifcall.count;
		i = 0;
		if(n >= 3*sizeof(uvlong)){
			vlong2le(b+2*sizeof(uvlong), h);
			i += sizeof(uvlong);
		}
		if(n >= 2*sizeof(uvlong)){
			vlong2le(b+sizeof(uvlong), t);
			i += sizeof(uvlong);
		}
		if(n >= 8){
			vlong2le(b, x);
			i += sizeof(vlong);
		}
		r->ofcall.count = i;
		respond(r, nil);
		return;
	}
	respond(r, "fixme");
}

static void
fswrite(Req *r)
{
	char str[13];
	uchar buf[8];
	vlong x, now;
	int n;

	if(pread(bintimefd, buf, sizeof(buf), 0) != sizeof(buf)){
		responderror(r);
		return;
	}
	le2vlong(&now, buf);

	n = r->ifcall.count;
	switch((ulong)r->fid->qid.path) {
	case Qtime:
		if(n >= sizeof(str)){
			respond(r, "bad");
			return;
		}
		strncpy(str, r->ifcall.data, n);
		str[n] = 0;
		x = strtol(str, 0, 0);
		if(x <= 0){
			respond(r, "bad");
			return;
		}
		x = x*1000000000LL;
		nsecdiff = now - x;
		r->ofcall.count = n;
		respond(r, nil);
		return;

	case Qbintime:
		respond(r, "not implemented");
		return;
	}
	respond(r, "fixme");
}


Srv fs = {
	.attach=			fsattach,
	.walk1=			fswalk1,
	.open=			fsopen,
	.read=			fsread,
	.write=			fswrite,
	.stat=			fsstat,
};

void
threadmain(int, char**)
{
	bintimefd = open("/dev/bintime", OREAD);

	threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.