Commits

Jeff Sickel  committed ef9c17c

add recent Plan 9 version of cmd/exportfs diffs

  • Participants
  • Parent commits 8549fde

Comments (0)

Files changed (4)

File exportfs/exportfs.c

 #include <libc.h>
 #include <fcall.h>
 #include <libsec.h>
-#include "drawterm.h"
 #define Extern
 #include "exportfs.h"
 
 #define QIDPATH	((((vlong)1)<<48)-1)
 vlong newqid = 0;
 
-void (*fcalls[256])(Fsrpc*);
+enum {
+	Encnone,
+	Encssl,
+	Enctls,
+};
+
+#pragma clang diagnostic ignored "-Wgnu-designator"
+
+void (*fcalls[])(Fsrpc*) =
+{
+	[Tversion]	Xversion,
+	[Tauth]	Xauth,
+	[Tflush]	Xflush,
+	[Tattach]	Xattach,
+	[Twalk]		Xwalk,
+	[Topen]		slave,
+	[Tcreate]	Xcreate,
+	[Tclunk]	Xclunk,
+	[Tread]		slave,
+	[Twrite]	slave,
+	[Tremove]	Xremove,
+	[Tstat]		Xstat,
+	[Twstat]	Xwstat,
+};
 
 /* accounting and debugging counters */
 int	filecnt;
 int	qidcnt;
 int	qfreecnt;
 int	ncollision;
-int	netfd;
+
+int	netfd;				/* initially stdin */
+int	srvfd = -1;
 
 int
 exportfs(int fd, int msgsz)
 reply(Fcall *r, Fcall *t, char *err)
 {
 	uchar *data;
-	int m, n;
+	int n;
 
 	t->tag = r->tag;
 	t->fid = r->fid;
 	if(data == nil)
 		fatal(Enomem);
 	n = convS2M(t, data, messagesize);
-	if((m=write(netfd, data, n))!=n){
-		iprint("wrote %d got %d (%r)\n", n, m);
+	if(write(netfd, data, n)!=n){
+		iprint("exportfs short write: %r\n");
 		fatal("write");
 	}
 	free(data);
 				freefile(f->f);
 				f->f = nil;
 			}
+			if(f->dir){
+				free(f->dir);
+				f->dir = nil;
+			}
 			*l = f->next;
 			f->next = fidfree;
 			fidfree = f;
 {
 	char buf[ERRMAX];
 	va_list arg;
+	Proc *m;
 
 	if (s) {
 		va_start(arg, s);
 	}
 
 	/* Clear away the slave children */
-//	for(m = Proclist; m; m = m->next)
-//		postnote(PNPROC, m->pid, "kill");
+	for(m = Proclist; m; m = m->next)
+		postnote(PNPROC, m->pid, "kill");
 
 	DEBUG(DFD, "%s\n", buf);
 	if (s) 
-		sysfatal(buf);
+		sysfatal("%s", buf);	/* caution: buf could contain '%' */
 	else
-		sysfatal("");
+		exits(nil);
 }
 
+void*
+emallocz(uint n)
+{
+	void *p;
+
+	p = mallocz(n, 1);
+	if(p == nil)
+		fatal(Enomem);
+	return p;
+}
+
+char*
+estrdup(char *s)
+{
+	char *t;
+
+	t = strdup(s);
+	if(t == nil)
+		fatal(Enomem);
+	return t;
+}

File exportfs/exportfs.h

 
 #define Proc	Exproc
 
-
 typedef struct Fsrpc Fsrpc;
 typedef struct Fid Fid;
 typedef struct File File;
 struct Fsrpc
 {
 	int	busy;		/* Work buffer has pending rpc to service */
-	int	pid;		/* Pid of slave process executing the rpc */
+	uintptr	pid;		/* Pid of slave process executing the rpc */
 	int	canint;		/* Interrupt gate */
 	int	flushtag;	/* Tag on which to reply to flush */
-	Fcall work;		/* Plan 9 incoming Fcall */
-	uchar	*buf;	/* Data buffer */
+	Fcall	work;		/* Plan 9 incoming Fcall */
+	uchar	*buf;		/* Data buffer */
 };
 
 struct Fid
 	int	nr;		/* fid number */
 	int	mid;		/* Mount id */
 	Fid	*next;		/* hash link */
+
+	/* for preaddir -- ARRGH! */
+	Dir	*dir;		/* buffer for reading directories */
+	int	ndir;		/* number of entries in dir */
+	int	cdir;		/* number of consumed entries in dir */
+	int	gdir;		/* glue index */
+	vlong	offset;		/* offset in virtual directory */
 };
 
 struct File
 
 struct Proc
 {
-	int	pid;
+	uintptr	pid;
 	int	busy;
 	Proc	*next;
 };
 };
 
 #define Enomem Exenomem
-#define Ebadfix Exebadfid
 #define Enotdir Exenotdir
-#define Edupfid Exedupfid
-#define Eopen Exeopen
-#define Exmnt Exexmnt
-#define Emip Exemip
-#define Enopsmt Exenopsmt
 
 extern char Ebadfid[];
 extern char Enotdir[];
 Extern char	psmap[Npsmpt];
 Extern Qidtab	*qidtab[Nqidtab];
 Extern ulong	messagesize;
-Extern int		srvfd;
+Extern int	srvfd;
 
 /* File system protocol service procedures */
 void Xattach(Fsrpc*);
 void	freeqid(Qidtab*);
 char*	estrdup(char*);
 void*	emallocz(uint);
-int		readmessage(int, char*, int);
+int	readmessage(int, char*, int);
+void	exclusions(void);
+int	excludefile(char*);
+int	preaddir(Fid*, uchar*, int, vlong);
 
+/* these should be picked up in additional kern files, if a 9vx merge takes place */
 #define notify(x)
 #define noted(x)
 #define exits(x)

File exportfs/exportsrv.c

 #include <u.h>
 #include <libc.h>
+#include <auth.h>
 #include <fcall.h>
 #define Extern	extern
 #include "exportfs.h"
 
+extern char *netdir, *local, *remote;
+
 char Ebadfid[] = "Bad fid";
 char Enotdir[] = "Not a directory";
 char Edupfid[] = "Fid already in use";
 char Enopsmt[] = "Out of pseudo mount points";
 char Enomem[] = "No memory";
 char Eversion[] = "Bad 9P2000 version";
+char Ereadonly[] = "File system read only";
 
-int iounit(int x)
-{
-	return 8*8192+IOHDRSZ;
-}
-
-void*
-emallocz(ulong n)
-{
-	void *v;
-
-	v = mallocz(n, 1);
-	if(v == nil)
-		panic("out of memory");
-	return v;
-}
-
+ulong messagesize;
+int readonly;
 
 void
 Xversion(Fsrpc *t)
 
 	for(w = Workq; w < e; w++) {
 		if(w->work.tag == t->work.oldtag) {
-			DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint);
+			DEBUG(DFD, "\tQ busy %d pid %p can %d\n", w->busy, w->pid, w->canint);
 			if(w->busy && w->pid) {
 				w->flushtag = t->work.tag;
 				DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
 void
 Xattach(Fsrpc *t)
 {
+	int i, nfd;
 	Fcall rhdr;
 	Fid *f;
+	char buf[128];
 
 	f = newfid(t->work.fid);
 	if(f == 0) {
 	Fid *f;
 	File *nf;
 
+	if(readonly) {
+		reply(&t->work, &rhdr, Ereadonly);
+		t->busy = 0;
+		return;
+	}
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
 	Fcall rhdr;
 	Fid *f;
 
+	if(readonly) {
+		reply(&t->work, &rhdr, Ereadonly);
+		t->busy = 0;
+		return;
+	}
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
 	char *strings;
 	Dir d;
 
+	if(readonly) {
+		reply(&t->work, &rhdr, Ereadonly);
+		t->busy = 0;
+		return;
+	}
 	f = getfid(t->work.fid);
 	if(f == 0) {
 		reply(&t->work, &rhdr, Ebadfid);
 	t->busy = 0;
 }
 
+/*
+ * based on libthread's threadsetname, but drags in less library code.
+ * actually just sets the arguments displayed.
+ */
+void
+procsetname(char *fmt, ...)
+{
+	int fd;
+	char *cmdname;
+	char buf[128];
+	va_list arg;
+
+	va_start(arg, fmt);
+	cmdname = vsmprint(fmt, arg);
+	va_end(arg);
+	if (cmdname == nil)
+		return;
+	snprint(buf, sizeof buf, "#p/%d/args", getpid());
+	if((fd = open(buf, OWRITE)) >= 0){
+		write(fd, cmdname, strlen(cmdname)+1);
+		close(fd);
+	}
+	free(cmdname);
+}
+
 void
 slave(Fsrpc *f)
 {
 	Proc *p;
-	int pid;
+	uintptr pid;
+	Fcall rhdr;
 	static int nproc;
 
+	if(readonly){
+		switch(f->work.type){
+		case Twrite:
+			reply(&f->work, &rhdr, Ereadonly);
+			f->busy = 0;
+			return;
+		case Topen:
+		  	if((f->work.mode&3) == OWRITE || (f->work.mode&OTRUNC)){
+				reply(&f->work, &rhdr, Ereadonly);
+				f->busy = 0;
+				return;
+			}
+		}
+	}
 	for(;;) {
 		for(p = Proclist; p; p = p->next) {
 			if(p->busy == 0) {
 				f->pid = p->pid;
 				p->busy = 1;
-				pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f);
+				pid = (uintptr)rendezvous((void*)p->pid, f);
 				if(pid != p->pid)
 					fatal("rendezvous sync fail");
 				return;
 		Proclist = p;
 
 DEBUG(DFD, "parent %d rendez\n", pid);
-		rendezvous((void*)(uintptr)pid, p);
+		rendezvous((void*)pid, p);
 DEBUG(DFD, "parent %d went\n", pid);
 	}
 }
 	Fsrpc *p;
 	Fcall rhdr;
 	Proc *m;
-	int pid;
+	uintptr pid;
 
 	USED(x);
-
 	notify(flushaction);
 
 	pid = getpid();
 
 DEBUG(DFD, "blockingslave %d rendez\n", pid);
-	m = (Proc*)rendezvous((void*)(uintptr)pid, 0);
+	m = (Proc*)rendezvous((void*)pid, 0);
 DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m);
 	
 	for(;;) {
-		p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid);
-		if((uintptr)p == ~(uintptr)0)			/* Interrupted */
+		p = rendezvous((void*)pid, (void*)pid);
+		if(p == (void*)~0)			/* Interrupted */
 			continue;
 
-		DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
+		DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);
 		if(p->flushtag != NOTAG)
 			goto flushme;
 
 
 	DEBUG(DFD, "\topen: fd %d\n", f->fid);
 	f->mode = work->mode;
+	f->offset = 0;
 	rhdr.iounit = getiounit(f->fid);
 	rhdr.qid = f->f->qid;
 	reply(work, &rhdr, 0);

File exportfs/pattern.c

+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#undef long					/* strip out define from lib.h */
+#include <bio.h>
+#include <regexp.h>
+#define Extern
+#include "exportfs.h"
+
+Reprog	**exclude, **include;
+char	*patternfile;
+
+void
+exclusions(void)
+{
+	Biobuf *f;
+	int ni, nmaxi, ne, nmaxe;
+	char *line;
+
+	if(patternfile == nil)
+		return;
+
+	f = Bopen(patternfile, OREAD);
+	if(f == nil)
+		fatal("cannot open patternfile");
+	ni = 0;
+	nmaxi = 100;
+	include = malloc(nmaxi*sizeof(*include));
+	if(include == nil)
+		fatal("out of memory");
+	include[0] = nil;
+	ne = 0;
+	nmaxe = 100;
+	exclude = malloc(nmaxe*sizeof(*exclude));
+	if(exclude == nil)
+		fatal("out of memory");
+	exclude[0] = nil;
+	while((line = Brdline(f, '\n'))){
+		line[Blinelen(f) - 1] = 0;
+		if(strlen(line) < 2 || line[1] != ' ')
+			continue;
+		switch(line[0]){
+		case '+':
+			if(ni+1 >= nmaxi){
+				nmaxi = 2*nmaxi;
+				include = realloc(include, nmaxi*sizeof(*include));
+				if(include == nil)
+					fatal("out of memory");
+			}
+			DEBUG(DFD, "\tinclude %s\n", line+2);
+			include[ni] = regcomp(line+2);
+			include[++ni] = nil;
+			break;
+		case '-':
+			if(ne+1 >= nmaxe){
+				nmaxe = 2*nmaxe;
+				exclude = realloc(exclude, nmaxe*sizeof(*exclude));
+				if(exclude == nil)
+					fatal("out of memory");
+			}
+			DEBUG(DFD, "\texclude %s\n", line+2);
+			exclude[ne] = regcomp(line+2);
+			exclude[++ne] = nil;
+			break;
+		default:
+			DEBUG(DFD, "ignoring pattern %s\n", line);
+			break;
+		}
+	}
+	Bterm(f);
+}
+
+int
+excludefile(char *path)
+{
+	Reprog **re;
+	char *p;
+
+	if(*(path+1) == 0)
+		p = "/";
+	else
+		p = path+1;
+
+	DEBUG(DFD, "checking %s\n", path);
+	for(re = include; *re != nil; re++){
+		if(regexec(*re, p, nil, 0) != 1){
+			DEBUG(DFD, "excluded+ %s\n", path);
+			return -1;
+		}
+	}
+	for(re = exclude; *re != nil; re++){
+		if(regexec(*re, p, nil, 0) == 1){
+			DEBUG(DFD, "excluded- %s\n", path);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int
+preaddir(Fid *f, uchar *data, int n, vlong offset)
+{
+	int r = 0, m;
+	Dir *d;
+
+	DEBUG(DFD, "\tpreaddir n=%d wo=%lld fo=%lld\n", n, offset, f->offset);
+	if(offset == 0 && f->offset != 0){
+		if(seek(f->fid, 0, 0) != 0)
+			return -1;
+		f->offset = f->cdir = f->ndir = 0;
+		free(f->dir);
+		f->dir = nil;
+	}else if(offset != f->offset){
+		werrstr("can't seek dir %lld to %lld", f->offset, offset);
+		return -1;
+	}
+
+	while(n > 0){
+		if(f->dir == nil){
+			f->ndir = fsdirread(f->fid, &f->dir);
+			if(f->ndir < 0)
+				return f->ndir;
+			if(f->ndir == 0)
+				return r;
+		}
+		d = &f->dir[f->cdir++];
+		if(exclude){
+			char *p = makepath(f->f, d->name);
+			if(excludefile(p)){
+				free(p);
+				goto skipentry;
+			}
+			free(p);
+		}
+		m = convD2M(d, data, n);
+		DEBUG(DFD, "\t\tconvD2M %d\n", m);
+		if(m <= BIT16SZ){
+			DEBUG(DFD, "\t\t\tneeded %d\n", GBIT16(data));
+			/* not enough room for full entry; leave for next time */
+			f->cdir--;
+			return r;
+		}else{
+			data += m;
+			n -= m;
+			r += m;
+			f->offset += m;
+		}
+skipentry:	if(f->cdir >= f->ndir){
+			f->cdir = f->ndir = 0;
+			free(f->dir);
+			f->dir = nil;
+		}
+	}
+	return r;
+}