Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/sys/src/cmd/ramfs.c

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


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

typedef struct Ramfile	Ramfile;

struct Ramfile {
	char*	data;
	int	ndata;
};


static char	Ebad[] = "something bad happened";
static char	Enomem[] = "no memory";
static char*	addr;
static char*	vname;

static void
fsattach(Req* r)
{
	if (r->srv->auth != nil && authattach(r) < 0)
		return;
	respond(r, nil);
}

static void
fsopen(Req* r)
{
	Ramfile*rf;
	File*	file;

	if (r->fid->qid.type&QTAUTH)
		sysfatal("fsopen for an AUTH file. fixme: add respond/return\n");
	file = r->fid->file;
	if (r->ifcall.mode&OTRUNC){
		rf = file->aux;
		if(rf){
			rf->ndata = 0;
			file->length = 0;
		}
	}
	respond(r, nil);
}

static void
fscreate(Req* r)
{
	File *file;
	char* name;
	char* uid;
	int mode;
	Ramfile *rf;
	File* f;

	file = r->fid->file;
	name = r->ifcall.name;
	uid = r->fid->uid;
	mode = r->fid->file->mode & 0x777 & r->ifcall.perm;
	mode |= (r->ifcall.perm & ~0x777);
	if(f = createfile(file, name, uid, mode, 0)){
		rf = emalloc9p(sizeof *rf);
		f->aux = rf;
		closefile(r->fid->file);
		r->fid->file = f;
		r->ofcall.qid = f->qid;
		respond(r, nil);
	} else
		responderror(r);
}

static void
fsread(Req* r)
{
	File* file;
	long count;
	vlong offset;
	Ramfile*rf;

	if (r->fid->qid.type&QTAUTH){
		authread(r);
		return;
	}
	file = r->fid->file;
	rf = file->aux;
	offset = r->ifcall.offset;
	count = r->ifcall.count;
	if (offset >= rf->ndata){
		count = 0;
	} else {
		if(offset+count >= rf->ndata)
			count = rf->ndata - offset;
		memmove(r->ofcall.data, rf->data+offset, count);
	}
	r->ofcall.count = count;
	respond(r, nil);
}

static void
fswrite(Req* r)
{
	File*	file;
	long	count;
	vlong	offset;
	Ramfile*rf;
	void*	v;

	if (r->fid->qid.type&QTAUTH){
		authwrite(r);
		return;
	}
	file = r->fid->file;
	rf = file->aux;
	offset = r->ifcall.offset;
	count = r->ifcall.count;
	if(offset+count >= rf->ndata){
		v = realloc(rf->data, offset+count);
		if(v == nil){
			respond(r, Enomem);
			return;
		} else {
			rf->data = v;
			rf->ndata = offset+count;
			file->length = rf->ndata;
		}
	}
	if (r->ofcall.count = count)
		memmove(rf->data+offset, r->ifcall.data, count);
	respond(r, nil);
}

static void
fswstat(Req* r)
{
	if (r->d.name && r->d.name[0] && strcmp(r->fid->file->name, r->d.name)){
		free(r->fid->file->name);
		r->fid->file->name = estrdup9p(r->d.name);
	}
	if (r->d.uid && r->d.uid[0]){
		free(r->fid->file->uid);
		r->fid->file->uid = estrdup9p(r->d.uid);
	}
	if (r->d.gid && r->d.gid[0]){
		free(r->fid->file->gid);
		r->fid->file->gid = estrdup9p(r->d.gid);
	}
	if (~(ulong)r->d.mode)
		r->fid->file->mode = r->d.mode;
	respond(r, nil);
}

static void
fsclunk(Fid* fid)
{

	if (fid->qid.type&QTAUTH)
		authdestroy(fid);
}

static int
islocal(char* addr)
{
	static char*	l = nil;
	if (addr == nil)
		return 1;
	if (!strncmp(addr, "::", 2) || !strncmp(addr, "127.0.0.1", 8))
		return 1;
	if (l == nil)
		l = getenv("sysaddr");
	if (l && !strncmp(addr, l, strlen(l)))
		return 1;
	return 0;
}

static void
bauth9p(Req* r)
{
	if (islocal(r->srv->addr)) {
		r->srv->auth = nil;	// no auth here any more
		respond(r, "auth no required for local peers");
	} else
		auth9p(r);
}

static Srv sfs=
{
	.auth	=	bauth9p,
	.attach	=	fsattach,
	.open	=	fsopen,
	.create	=	fscreate,
	.read	=	fsread,
	.wstat	=	fswstat,
	.write	=	fswrite,
	.destroyfid = 	fsclunk,
};

static void
freefile(File *f)
{
	Ramfile *rf;

	rf = f->aux;
	if(rf){
		f->aux = nil;
		free(rf->data);
		free(rf);
	}
}

static void
announceproc(void*)
{
	int	afd = -1;
	char*	cnstr;

	cnstr = strchr(vname, ' ');
	if (cnstr)
		*cnstr++ = 0;

	for(;;){
		afd = announcevol(afd, addr, vname, cnstr);
		sleep(10 * 1000);
	}
}

void
usage(void)
{
	fprint(2, "usage: %s [-abcAD] [-s srv] [-m mnt] [-n addr] [-V vol]\n", argv0);
	exits("usage");
}


void
threadmain(int argc, char **argv)
{
	char*	mnt;
	char*	srv;
	int	mflag;

	srv = nil;
	mnt = nil;
	mflag = MREPL|MCREATE;
	ARGBEGIN{
	case 'a':
		mflag = MAFTER|MCREATE;
		break;
	case 'b':
		mflag = MBEFORE|MCREATE;
		break;
	case 'c':
		mflag = MREPL|MCREATE;
		break;
	case 'A':
		sfs.auth = nil;
		break;
	case 'd':
		chatty9p++;
		break;
	case 's':
		srv = EARGF(usage());
		break;
	case 'm':
		mnt = EARGF(usage());
		break;
	case 'n':
		addr = EARGF(usage());
		break;
	case 'V':
		vname = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND;

	if(argc!= 0)
		usage();
	if (getenv("local"))
		sfs.auth = nil;
	if (srv == nil && mnt == nil && addr == nil){
		sfs.auth = nil;
		mnt = "/tmp";
	}
	if (!chatty9p)
		rfork(RFNOTEG);
	sfs.tree =  alloctree(nil, nil, DMDIR|0755, freefile);
	if (addr != nil){
		threadlistensrv(&sfs, addr);
	}
	if (srv != nil || mnt != nil)
		threadpostmountsrv(&sfs, srv, mnt, mflag);
	if (addr != nil && vname != nil)
		proccreate(announceproc, 0, 8*1024);
	threadexits(nil);
}

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.