Plan 9 from Bell Labs’s /usr/web/sources/contrib/axel/substfs/9lib/substfs.c

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


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

ulong	messagesize = IOHDRSZ+8192;
int subfd;

int	old9p = -1;
uchar*	rxbuf;
uchar*	txbuf;

void
usage(void)
{
	fprint(2, "usage: substfs [...] /srv/service | -c command | -n networkaddress\n");
	exits("usage");
}

void*
emalloc(ulong n)
{
	void *p;

	p = malloc(n);
	if(p == 0)
		sysfatal("malloc(%ld) fails", (long)n);
	memset(p, 0, n);
	return p;
}

void
getfcallnew(int fd, Fcall *fc, int have)
{
	int len;

	if(have > BIT32SZ)
		sysfatal("cannot happen: %r");

	if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have)
		sysfatal("couldn't read message: %r");

	len = GBIT32(rxbuf);
	if(len <= BIT32SZ)
		sysfatal("bogus message");

	len -= BIT32SZ;
	if(readn(fd, rxbuf+BIT32SZ, len) != len)
		sysfatal("short message: %r");

	if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ)
		sysfatal("badly sized message type %d: %r", rxbuf[0]);
}

void
putfcallnew(int wfd, Fcall *tx)
{
	ulong n;

	if((n = convS2M(tx, txbuf, messagesize)) == 0)
		sysfatal("couldn't format message type %d: %r", tx->type);
	fprint(2, "substfs: %F\n", tx);
	if(write(wfd, txbuf, n) != n)
		sysfatal("couldn't send message: %r");
}

void
getfcall(int fd, Fcall *fc)
{
	//getfcallnew(fd, fc, 0);

	int res;
	res = read9pmsg(fd, rxbuf, messagesize);
	if (res < 0) {
		fprint(2, "%s", rxbuf);
		sysfatal("couldn't read message: %r");
	}
	if (res == 0)
		sysfatal("end of file on fd");

	if(convM2S(rxbuf, messagesize, fc) == 0)
		sysfatal("badly sized message type %d: %r", rxbuf[0]);
	fprint(2, "substfs: %F\n", fc);

}



static
void
handle(Req* r)
{
	fprint(2, "substfs: putfcallnew...\n");
	putfcallnew(subfd, &r->ifcall);
	fprint(2, "substfs: putfcallnew... done\n");
	fprint(2, "substfs: getfcall... \n");
	getfcall(subfd, &r->ofcall);
	fprint(2, "substfs: getfcall... done\n");
	if(r->ofcall.type == Rerror)
		respond(r, r->ofcall.ename);
	else if (r->ofcall.type == Rstat) {
		if(convM2D(r->ofcall.stat, r->ofcall.nstat, &r->d, (char*)r->ofcall.stat) != r->ofcall.nstat)
			respond(r, "error bad dir");
		else {
			// hack to avoid too much freeing
			r->d.name = strdup(r->d.name);
			r->d.uid = strdup(r->d.uid);
			r->d.gid = strdup(r->d.gid);
			r->d.muid = strdup(r->d.muid);
			if(r->d.mode & DMDIR)
				r->fid->qid.type |= QTDIR;
			if(r->d.mode & DMAPPEND)
				r->fid->qid.type |= QTAPPEND;
			if(r->d.mode & DMEXCL)
				r->fid->qid.type |= QTEXCL;
			respond(r, nil);
		}
	} else
		respond(r, nil);
	
}

Srv substsrv = {
//.destroyfid = won't work because we need the req!
.attach=	handle,
.auth=	handle,
.open=	handle,
.create=	handle,
.read=	handle,
.write=	handle,
.remove=	handle,
.flush=	handle,
.stat=	handle,
.wstat=	handle,
.walk=	handle,
};

int
connectcmd(char *cmd)
{
	int p[2];

	if(pipe(p) < 0)
		return -1;
	switch(fork()){
	case -1:
		fprint(2, "fork failed: %r\n");
		_exits("exec");
	case 0:
		dup(p[0], 0);
		dup(p[0], 1);
		close(p[1]);
		execl("/bin/rc", "rc", "-c", cmd, nil);
		fprint(2, "exec failed: %r\n");
		_exits("exec");
	default:
		close(p[0]);
		return p[1];
	}
}

void
main(int argc, char **argv)
{
	char *mtpt, *service;
	int cmd, net;
	int sfd[2];

	mtpt = nil;
	service = nil;
	cmd = 0;
	net = 0;
	ARGBEGIN{
	case 'D':
		chatty9p++;
		break;
	case 's':
		service = EARGF(usage());
		break;
	case 'm':
		mtpt = EARGF(usage());
		break;
	case 'c':
		cmd = 1;
		break;
	case 'n':
		net = 1;
		break;
	default:
		usage();
	}ARGEND

	if(argc != 1)
		usage();

	fmtinstall('F', fcallfmt);

	rxbuf = emalloc(messagesize);
	txbuf = emalloc(messagesize);

	if(cmd && net)
		usage();

	if(cmd)
		subfd = connectcmd(argv[0]);
	else if(net){
		subfd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0);
		if(subfd < 0)
			sysfatal("dial: %r");
	}else{
		subfd = open(argv[0], ORDWR);
		if(subfd < 0)
			sysfatal("open: %r");
	}

	//postmountsrv(&substsrv, service, mtpt, MREPL);
	//exits(nil);

	if(pipe(sfd) < 0)
		sysfatal("pipe: %r");
	if(service)
		if(postfd(service, sfd[0]) < 0)
			sysfatal("postfd %s: %r", service);
	substsrv.infd = sfd[1];
	substsrv.outfd = sfd[1];
	srv(&substsrv);
	
}


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.