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

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


/*
 * 9P file server for the control file system.
 * This provides a control file system with just
 * a vol file to get/set status for volumes.
 *
 * BUG: there is no way (yet) to update constraints.
 * This requires the addition of a "set" command.
 */

#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <auth.h>
#include <ip.h>
#include "names.h"
#include "vols.h"

Fs	ctlfs;
uvlong	Ctldirqid=	0x000000008c000001ULL;
uvlong	Ctlqid=		0x000000008d000000ULL;

static Dir*
ctldirstat(int isdir)
{
	Dir*	d;
	char*	s;
	char*	n;

	d = emalloc(sizeof(Dir)+ 4 + 4 + 4 + 4);
	memset(d, 0, sizeof(Dir));
	s = (char*)d;
	n = s + sizeof(Dir);
	d->name = n;	strcpy(n, "vol");	n += 4;
	d->uid = n;	strcpy(n, "sys");	n += 4;
	d->gid = n;	strcpy(n, "sys");	n += 4;
	d->muid = n;	strcpy(n, "sys");

	// depends on the qid.
	if (isdir){
		d->qid.type = QTDIR;
		d->qid.path = Ctldirqid;
		d->mode = DMDIR|0555;
	} else {
		d->qid.type = 0;
		d->qid.path = Ctlqid;
		d->qid.vers = epoch.ref;
		d->mode = 0660;
	}
	return d;
}

static int
statop(Fs* , Frpc* fop)
{
	
	fop->r.tag = fop->f.tag;
	fop->r.type= Rstat;
	fop->d = ctldirstat(fop->fid->qid.type&QTDIR);
	return 1;
}

static char*
volsmprint(void)
{
	static char buf[16*1024];
	int	i;
	char*	s;
	Vol*	v;

	qlock(&volslck);
	s = buf;
	*s = 0;
	for (i = 0; i < nvols; i++){
		v = vols[i];
		if (v->dead && !v->disabled)
			continue;
		if (v->dead || v->disabled)
			s = seprint(s, buf+sizeof(buf), "#%V ", v);
		else
			s = seprint(s, buf+sizeof(buf), "%V ", v);
		if (vols[i]->disabled)
			s = seprint(s, buf+sizeof(buf), "# disabled");
		else if (vols[i]->dead)
			s = seprint(s, buf+sizeof(buf), "# dead");
		s = seprint(s, buf+sizeof(buf), "\n");
	}
	qunlock(&volslck);
	qlock(&mvolslck);
	for (i = 0; i < nmvols; i++)
		if (mvols[i])
			s = seprint(s, buf+sizeof(buf), "# %W\n", mvols[i]);
	qunlock(&mvolslck);
	return estrdup(buf);
}

static int
openop(Fs*, Frpc* fop)
{
	Fid*	fid;
	static Dir* root;

	if (root == nil)
		root = ctldirstat(0);

	fid = fop->fid;
	fop->r.tag= fop->f.tag;
	if (fid->qid.type&QTDIR){
		if ((fop->f.mode&3) != OREAD){
			rpcerr(fop, Eperm);
			return -1;
		}
		if (fid->ureadbuf == nil){
			fid->ureadbuf = emalloc(128);
			fid->ureadlen = convD2M(root, (uchar*)fid->ureadbuf, 128);
		}
	} else {
		fid->ureadbuf = volsmprint();
		fid->ureadlen = strlen(fid->ureadbuf);
	}
	fop->r.type= Ropen;
	fop->r.qid = fid->qid;
	fop->r.iounit = 8*1024;
	return 0;
}

static int
readop(Fs* , Frpc* m)
{
	long	off, len;

	m->r.tag = m->f.tag;
	m->r.type= Rread;
	m->r.data= (char*)m->buf;
	m->r.count = 0;
	off = m->f.offset;
	len = m->fid->ureadlen;
	if (off >= len || !m->f.count)
		return 0;
	if (m->fid->qid.type&QTDIR){
		if (m->f.count >= len && off == 0){
			memmove(m->r.data, m->fid->ureadbuf, len);
			m->r.count = len;
		}
	} else {
		if (off + m->f.count > len)
			m->f.count = len - off;
		m->r.count = m->f.count;
		memmove(m->r.data, m->fid->ureadbuf+off, m->r.count);
	}
	return m->r.count;
}

static int
writeop(Fs* fs, Frpc* fop)
{
	int	n;

	if (fop->fid->qid.type&QTDIR)
		return noop(fs, fop);
	fop->r.tag = fop->f.tag;
	fop->r.type= Rwrite;
	n = fop->f.count;
	if (n < 0)
		n = 0;
	if (n > 1024)
		n = 1024;
	fop->r.count = n;
	fop->f.data[n] = 0;
	cmdline(fop->f.data, "/dev/vol", 0);
	return n;
}

static int
walkop(Fs* , Frpc* m)
{
	int	dir;
	int	i;

	dir = (m->fid->qid.type&QTDIR);
	m->r.tag = m->f.tag;
	m->r.type = Rwalk;
	m->r.nwqid = 0;
	for(i = 0; i < m->f.nwname && i < MAXWELEM; i++)
		if(strcmp(m->f.wname[i], "..") == 0){
			dir = 1;
			m->r.wqid[m->r.nwqid].path = Ctldirqid;
			m->r.wqid[m->r.nwqid++].type = QTDIR;
		} else if (dir && !strcmp(m->f.wname[i], "vol")){
			dir = 0;
			m->r.wqid[m->r.nwqid].path = Ctlqid;
			m->r.wqid[m->r.nwqid++].type = 0;
		} else
			break;
	if (!m->f.nwname || m->r.nwqid > 0)
		return 1;
	rpcerr(m, Enotexist);
	return 0;
}

static int
clunkop(Fs*, Frpc* fop)
{
	free(fop->fid->ureadbuf);
	fop->fid->ureadbuf = nil;
	fop->r.tag = fop->f.tag;
	fop->r.type= Rclunk;
	return 0;
}

static int
flushop(Fs*, Frpc* fop)
{
	fop->r.tag = fop->f.tag;
	fop->r.type= Rflush;
	return 0;
}

typedef int (*Frpcf)(Fs*, Frpc*);
Frpcf	ctlfsops[Tmax] = {
	[Topen]		openop,
	[Twalk]		walkop,
	[Tcreate]	noop,
	[Tclunk]	clunkop,
	[Tread]		readop,
	[Twrite]	writeop,
	[Tremove]	noop,
	[Tstat]		statop,
	[Twstat]	noop,
	[Tflush]	flushop,
};

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.