797 lines · 13.5 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "stdinc.h"#include <fcall.h>#include "vac.h" #define convM2Su(a, b, c, d) convM2S(a, b, c)#define convS2Mu(a, b, c, d) convS2M(a, b, c)#define convM2Du(a, b, c, d) convM2D(a, b, c)#define convD2Mu(a, b, c, d) convD2M(a, b, c) typedef struct Fid Fid; enum{	Stacksize = 320 * 1024,	/* was 32K */	OPERM	= 0x3		/* mask of all permission types in open mode */}; struct Fid{	short busy;	short open;	int fid;	char *user;	Qid qid;	VacFile *file;	VacDirEnum *vde;	Fid	*next;}; enum{	Pexec =		1,	Pwrite = 	2,	Pread = 	4,	Pother = 	1,	Pgroup = 	8,	Powner =	64}; Fid	*fids;uchar	*data;int	mfd[2];int	srvfd = -1;char	*user;uchar	mdata[8192+IOHDRSZ];int messagesize = sizeof mdata;Fcall	rhdr;Fcall	thdr;VacFs	*fs;VtConn  *conn;int	noperm;int	dotu;char *defmnt; Fid *	newfid(int);void	error(char*);void	io(void);void	vacshutdown(void);void	usage(void);int	perm(Fid*, int);int	permf(VacFile*, char*, int);ulong	getl(void *p);void	init(char*, char*, long, int);int	vacdirread(Fid *f, char *p, long off, long cnt);int	vacstat(VacFile *parent, VacDir *vd, uchar *p, int np);void 	srv(void* a);  char	*rflush(Fid*), *rversion(Fid*),	*rauth(Fid*), *rattach(Fid*), *rwalk(Fid*),	*ropen(Fid*), *rcreate(Fid*),	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*); char 	*(*fcalls[Tmax])(Fid*); voidinitfcalls(void){	fcalls[Tflush]=	rflush;	fcalls[Tversion]=	rversion;	fcalls[Tattach]=	rattach;	fcalls[Tauth]=		rauth;	fcalls[Twalk]=		rwalk;	fcalls[Topen]=		ropen;	fcalls[Tcreate]=	rcreate;	fcalls[Tread]=		rread;	fcalls[Twrite]=	rwrite;	fcalls[Tclunk]=	rclunk;	fcalls[Tremove]=	rremove;	fcalls[Tstat]=		rstat;	fcalls[Twstat]=	rwstat;} char	Eperm[] =	"permission denied";char	Enotdir[] =	"not a directory";char	Enotexist[] =	"file does not exist";char	Einuse[] =	"file in use";char	Eexist[] =	"file exists";char	Enotowner[] =	"not owner";char	Eisopen[] = 	"file already open for I/O";char	Excl[] = 	"exclusive use file already open";char	Ename[] = 	"illegal name";char	Erdonly[] = 	"read only file system";char	Eio[] = 	"i/o error";char	Eempty[] = 	"directory is not empty";char	Emode[] =	"illegal mode"; int dflag; voidnotifyf(void *a, char *s){	USED(a);	if(strncmp(s, "interrupt", 9) == 0)		noted(NCONT);	noted(NDFLT);} voidthreadmain(int argc, char *argv[]){	char *defsrv, *srvname;	int p[2], fd;	int stdio;	char *host = nil;	long ncache; 	stdio = 0;	ncache = 256;	fmtinstall('H', encodefmt);	fmtinstall('V', vtscorefmt);	fmtinstall('F', vtfcallfmt);		defmnt = nil;	defsrv = nil;	ARGBEGIN{	case 'd':		fmtinstall('F', fcallfmt);		dflag = 1;		break;	case 'c':		ncache = atoi(EARGF(usage()));		break;	case 'i':		defmnt = nil;		stdio = 1;		mfd[0] = 0;		mfd[1] = 1;		break;	case 'h':		host = EARGF(usage());		break;	case 'S':		defsrv = EARGF(usage());		break;	case 's':		defsrv = "vacfs";		break;	case 'm':		defmnt = EARGF(usage());		break;	case 'p':		noperm = 1;		break;	case 'V':		chattyventi = 1;		break;	default:		usage();	}ARGEND 	if(argc != 1)		usage(); 	if(defsrv == nil && defmnt == nil && !stdio)		defmnt = "/n/vac";	if(stdio && defmnt)		sysfatal("cannot use -m with -i"); 	initfcalls(); 	notify(notifyf);	user = getuser(); 	conn = vtdial(host);	if(conn == nil)		sysfatal("could not connect to server: %r"); 	if(vtconnect(conn) < 0)		sysfatal("vtconnect: %r"); 	fs = vacfsopen(conn, argv[0], VtOREAD, ncache);	if(fs == nil)		sysfatal("vacfsopen: %r"); 	if(!stdio){		if(pipe(p) < 0)			sysfatal("pipe failed: %r");		mfd[0] = p[0];		mfd[1] = p[0];		srvfd = p[1];		if(defsrv){			srvname = smprint("/srv/%s", defsrv);			fd = create(srvname, OWRITE|ORCLOSE, 0666);			if(fd < 0)				sysfatal("create %s: %r", srvname);			if(fprint(fd, "%d", srvfd) < 0)				sysfatal("write %s: %r", srvname);			free(srvname);		}	} 	procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG); 	if(!stdio){		close(p[0]);		if(defmnt){			if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)				sysfatal("mount %s: %r", defmnt);		}	}	threadexits(0);} voidsrv(void *a){	USED(a);	io();	vacshutdown();} voidusage(void){	fprint(2, "usage: %s [-sd] [-h host] [-c ncache] [-m mountpoint] vacfile\n", argv0);	threadexitsall("usage");} char*rversion(Fid *unused){	Fid *f; 	USED(unused); 	for(f = fids; f; f = f->next)		if(f->busy)			rclunk(f); 	if(rhdr.msize < 256)		return vtstrdup("version: message size too small");	messagesize = rhdr.msize;	if(messagesize > sizeof mdata)		messagesize = sizeof mdata;	thdr.msize = messagesize;	if(strncmp(rhdr.version, "9P2000", 6) != 0)		return vtstrdup("unrecognized 9P version");	thdr.version = "9P2000";	if(strncmp(rhdr.version, "9P2000.u", 8) == 0){		dotu = 1;		thdr.version = "9P2000.u";	}	return nil;} char*rflush(Fid *f){	USED(f);	return 0;} char*rauth(Fid *f){	USED(f);	return vtstrdup("vacfs: authentication not required");} char*rattach(Fid *f){	/* no authentication for the momment */	VacFile *file;	char err[80]; 	file = vacfsgetroot(fs);	if(file == nil) {		rerrstr(err, sizeof err);		return vtstrdup(err);	} 	f->busy = 1;	f->file = file;	f->qid.path = vacfilegetid(f->file);	f->qid.vers = 0;	f->qid.type = QTDIR;	thdr.qid = f->qid;	if(rhdr.uname[0])		f->user = vtstrdup(rhdr.uname);	else		f->user = "none";	return 0;} char*rwalk(Fid *f){	VacFile *file, *nfile;	Fid *nf;	int nqid, nwname;	Qid qid;	char *err = nil; 	if(f->busy == 0)		return Enotexist;	nf = nil;	if(rhdr.fid != rhdr.newfid){		if(f->open)			return vtstrdup(Eisopen);		if(f->busy == 0)			return vtstrdup(Enotexist);		nf = newfid(rhdr.newfid);		if(nf->busy)			return vtstrdup(Eisopen);		nf->busy = 1;		nf->open = 0;		nf->qid = f->qid;		nf->file = vacfileincref(f->file);		nf->user = vtstrdup(f->user);		f = nf;	} 	nwname = rhdr.nwname; 	/* easy case */	if(nwname == 0) {		thdr.nwqid = 0;		return 0;	} 	file = f->file;	vacfileincref(file);	qid = f->qid; 	for(nqid = 0; nqid < nwname; nqid++){		if((qid.type & QTDIR) == 0){			err = Enotdir;			break;		}		if(!permf(file, f->user, Pexec)) {			err = Eperm;			break;		}		nfile = vacfilewalk(file, rhdr.wname[nqid]);		if(nfile == nil)			break;		vacfiledecref(file);		file = nfile;		qid.type = QTFILE;		if(vacfileisdir(file))			qid.type = QTDIR;		qid.vers = vacfilegetmcount(file);		qid.path = vacfilegetid(file);		thdr.wqid[nqid] = qid;	} 	thdr.nwqid = nqid; 	if(nqid == nwname){		/* success */		f->qid = thdr.wqid[nqid-1];		vacfiledecref(f->file);		f->file = file;		return 0;	} 	vacfiledecref(file);	if(nf != nil)		rclunk(nf); 	/* only error on the first element */	if(nqid == 0)		return vtstrdup(err); 	return 0;} char *ropen(Fid *f){	int mode, trunc; 	if(f->open)		return vtstrdup(Eisopen);	if(!f->busy)		return vtstrdup(Enotexist); 	mode = rhdr.mode;	thdr.iounit = messagesize - IOHDRSZ;	if(f->qid.type & QTDIR){		if(mode != OREAD)			return vtstrdup(Eperm);		if(!perm(f, Pread))			return vtstrdup(Eperm);		thdr.qid = f->qid;		f->vde = nil;		f->open = 1;		return 0;	}	if(mode & ORCLOSE)		return vtstrdup(Erdonly);	trunc = mode & OTRUNC;	mode &= OPERM;	if(mode==OWRITE || mode==ORDWR || trunc)		if(!perm(f, Pwrite))			return vtstrdup(Eperm);	if(mode==OREAD || mode==ORDWR)		if(!perm(f, Pread))			return vtstrdup(Eperm);	if(mode==OEXEC)		if(!perm(f, Pexec))			return vtstrdup(Eperm);	thdr.qid = f->qid;	thdr.iounit = messagesize - IOHDRSZ;	f->open = 1;	return 0;} char*rcreate(Fid* fid){	VacFile *vf;	ulong mode; 	if(fid->open)		return vtstrdup(Eisopen);	if(!fid->busy)		return vtstrdup(Enotexist);	if(fs->mode & ModeSnapshot)		return vtstrdup(Erdonly);	vf = fid->file;	if(!vacfileisdir(vf))		return vtstrdup(Enotdir);	if(!permf(vf, fid->user, Pwrite))		return vtstrdup(Eperm); 	mode = rhdr.perm & 0777; 	if(rhdr.perm & DMDIR){		if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND))			return vtstrdup(Emode);		switch(rhdr.mode & OPERM){		default:			return vtstrdup(Emode);		case OEXEC:		case OREAD:			break;		case OWRITE:		case ORDWR:			return vtstrdup(Eperm);		}		mode |= ModeDir;	}	vf = vacfilecreate(vf, rhdr.name, mode);	if(vf == nil) {		char err[80];		rerrstr(err, sizeof err); 		return vtstrdup(err);	} 	vacfiledecref(fid->file); 	fid->file = vf;	fid->qid.type = QTFILE;	if(vacfileisdir(vf))		fid->qid.type = QTDIR;	fid->qid.vers = vacfilegetmcount(vf);	fid->qid.path = vacfilegetid(vf); 	thdr.qid = fid->qid;	thdr.iounit = messagesize - IOHDRSZ; 	return 0;} char*rread(Fid *f)

Lines 1–500 of 797.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t