⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exportsrv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#define Extern	extern#include "exportfs.h"char Ebadfid[] = "Bad fid";char Enotdir[] = "Not a directory";char Edupfid[] = "Fid already in use";char Eopen[] = "Fid already opened";char Exmnt[] = "Cannot .. past mount point";char Emip[] = "Mount in progress";char Enopsmt[] = "Out of pseudo mount points";char Enomem[] = "No memory";char Eversion[] = "Bad 9P2000 version";char Ereadonly[] = "File system read only";ulong messagesize;int readonly;voidXversion(Fsrpc *t){	Fcall rhdr;	if(t->work.msize > messagesize)		t->work.msize = messagesize;	messagesize = t->work.msize;	if(strncmp(t->work.version, "9P2000", 6) != 0){		reply(&t->work, &rhdr, Eversion);		return;	}	rhdr.version = "9P2000";	rhdr.msize = t->work.msize;	reply(&t->work, &rhdr, 0);	t->busy = 0;}voidXauth(Fsrpc *t){	Fcall rhdr;	reply(&t->work, &rhdr, "exportfs: authentication not required");	t->busy = 0;}voidXflush(Fsrpc *t){	Fsrpc *w, *e;	Fcall rhdr;	e = &Workq[Nr_workbufs];	for(w = Workq; w < e; w++) {		if(w->work.tag == t->work.oldtag) {			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);				if(w->canint)					postnote(PNPROC, w->pid, "flush");				t->busy = 0;				return;			}		}	}	reply(&t->work, &rhdr, 0);	DEBUG(DFD, "\tflush reply\n");	t->busy = 0;}voidXattach(Fsrpc *t){	int i, nfd;	Fcall rhdr;	Fid *f;	char buf[128];	f = newfid(t->work.fid);	if(f == 0) {		reply(&t->work, &rhdr, Ebadfid);		t->busy = 0;		return;	}	if(srvfd >= 0){		if(psmpt == 0){		Nomount:			reply(&t->work, &rhdr, Enopsmt);			t->busy = 0;			freefid(t->work.fid);			return;		}		for(i=0; i<Npsmpt; i++)			if(psmap[i] == 0)				break;		if(i >= Npsmpt)			goto Nomount;		sprint(buf, "%d", i);		f->f = file(psmpt, buf);		if(f->f == nil)			goto Nomount;		sprint(buf, "/mnt/exportfs/%d", i);		nfd = dup(srvfd, -1);		if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){			errstr(buf, sizeof buf);			reply(&t->work, &rhdr, buf);			t->busy = 0;			freefid(t->work.fid);			close(nfd);			return;		}		psmap[i] = 1;		f->mid = i;	}else{		f->f = root;		f->f->ref++;	}	rhdr.qid = f->f->qid;	reply(&t->work, &rhdr, 0);	t->busy = 0;}Fid*clonefid(Fid *f, int new){	Fid *n;	n = newfid(new);	if(n == 0) {		n = getfid(new);		if(n == 0)			fatal("inconsistent fids");		if(n->fid >= 0)			close(n->fid);		freefid(new);		n = newfid(new);		if(n == 0)			fatal("inconsistent fids2");	}	n->f = f->f;	n->f->ref++;	return n;}voidXwalk(Fsrpc *t){	char err[ERRMAX], *e;	Fcall rhdr;	Fid *f, *nf;	File *wf;	int i;	f = getfid(t->work.fid);	if(f == 0) {		reply(&t->work, &rhdr, Ebadfid);		t->busy = 0;		return;	}	nf = nil;	if(t->work.newfid != t->work.fid){		nf = clonefid(f, t->work.newfid);		f = nf;	}	rhdr.nwqid = 0;	e = nil;	for(i=0; i<t->work.nwname; i++){		if(i == MAXWELEM){			e = "Too many path elements";			break;		}		if(strcmp(t->work.wname[i], "..") == 0) {			if(f->f->parent == nil) {				e = Exmnt;				break;			}			wf = f->f->parent;			wf->ref++;			goto Accept;		}			wf = file(f->f, t->work.wname[i]);		if(wf == 0){			errstr(err, sizeof err);			e = err;			break;		}    Accept:		freefile(f->f);		rhdr.wqid[rhdr.nwqid++] = wf->qid;		f->f = wf;		continue;	}	if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))		freefid(t->work.newfid);	if(rhdr.nwqid > 0)		e = nil;	reply(&t->work, &rhdr, e);	t->busy = 0;}voidXclunk(Fsrpc *t){	Fcall rhdr;	Fid *f;	f = getfid(t->work.fid);	if(f == 0) {		reply(&t->work, &rhdr, Ebadfid);		t->busy = 0;		return;	}	if(f->fid >= 0)		close(f->fid);	freefid(t->work.fid);	reply(&t->work, &rhdr, 0);	t->busy = 0;}voidXstat(Fsrpc *t){	char err[ERRMAX], *path;	Fcall rhdr;	Fid *f;	Dir *d;	int s;	uchar *statbuf;	f = getfid(t->work.fid);	if(f == 0) {		reply(&t->work, &rhdr, Ebadfid);		t->busy = 0;		return;	}	if(f->fid >= 0)		d = dirfstat(f->fid);	else {		path = makepath(f->f, "");		d = dirstat(path);		free(path);	}	if(d == nil) {		errstr(err, sizeof err);		reply(&t->work, &rhdr, err);		t->busy = 0;		return;	}	d->qid.path = f->f->qidt->uniqpath;	s = sizeD2M(d);	statbuf = emallocz(s);	s = convD2M(d, statbuf, s);	free(d);	rhdr.nstat = s;	rhdr.stat = statbuf;	reply(&t->work, &rhdr, 0);	free(statbuf);	t->busy = 0;}static intgetiounit(int fd){	int n;	n = iounit(fd);	if(n > messagesize-IOHDRSZ)		n = messagesize-IOHDRSZ;	return n;}voidXcreate(Fsrpc *t){	char err[ERRMAX], *path;	Fcall rhdr;	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);		t->busy = 0;		return;	}		path = makepath(f->f, t->work.name);	f->fid = create(path, t->work.mode, t->work.perm);	free(path);	if(f->fid < 0) {		errstr(err, sizeof err);		reply(&t->work, &rhdr, err);		t->busy = 0;		return;	}	nf = file(f->f, t->work.name);	if(nf == 0) {		errstr(err, sizeof err);		reply(&t->work, &rhdr, err);		t->busy = 0;		return;	}	f->mode = t->work.mode;	freefile(f->f);	f->f = nf;	rhdr.qid = f->f->qid;	rhdr.iounit = getiounit(f->fid);	reply(&t->work, &rhdr, 0);	t->busy = 0;}voidXremove(Fsrpc *t){	char err[ERRMAX], *path;	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);		t->busy = 0;		return;	}	path = makepath(f->f, "");	DEBUG(DFD, "\tremove: %s\n", path);	if(remove(path) < 0) {		free(path);		errstr(err, sizeof err);		reply(&t->work, &rhdr, err);		t->busy = 0;		return;	}	free(path);	f->f->inval = 1;	if(f->fid >= 0)		close(f->fid);	freefid(t->work.fid);	reply(&t->work, &rhdr, 0);	t->busy = 0;}voidXwstat(Fsrpc *t){	char err[ERRMAX], *path;	Fcall rhdr;	Fid *f;	int s;	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;		return;	}	strings = emallocz(t->work.nstat);	/* ample */	if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){		rerrstr(err, sizeof err);		reply(&t->work, &rhdr, err);		t->busy = 0;		free(strings);		return;	}	if(f->fid >= 0)		s = dirfwstat(f->fid, &d);	else {		path = makepath(f->f, "");		s = dirwstat(path, &d);		free(path);	}	if(s < 0) {		rerrstr(err, sizeof err);		reply(&t->work, &rhdr, err);	}	else {		/* wstat may really be rename */		if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){			free(f->f->name);			f->f->name = estrdup(d.name);		}		reply(&t->work, &rhdr, 0);	}	free(strings);	t->busy = 0;}voidslave(Fsrpc *f){	Proc *p;	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*)p->pid, f);				if(pid != p->pid)					fatal("rendezvous sync fail");				return;			}			}		if(++nproc > MAXPROC)			fatal("too many procs");		pid = rfork(RFPROC|RFMEM);		switch(pid) {		case -1:			fatal("rfork");		case 0:			blockingslave();			fatal("slave");		default:			p = malloc(sizeof(Proc));			if(p == 0)				fatal("out of memory");			p->busy = 0;			p->pid = pid;			p->next = Proclist;			Proclist = p;			rendezvous((void*)pid, p);		}	}}voidblockingslave(void){	Fsrpc *p;	Fcall rhdr;	Proc *m;	uintptr pid;	notify(flushaction);	pid = getpid();	m = rendezvous((void*)pid, 0);		for(;;) {		p = rendezvous((void*)pid, (void*)pid);		if(p == (void*)~0)			/* Interrupted */			continue;		DEBUG(DFD, "\tslave: %p %F b %d p %p\n", pid, &p->work, p->busy, p->pid);		if(p->flushtag != NOTAG)			goto flushme;		switch(p->work.type) {		case Tread:			slaveread(p);			break;		case Twrite:			slavewrite(p);			break;		case Topen:			slaveopen(p);			break;		default:			reply(&p->work, &rhdr, "exportfs: slave type error");		}		if(p->flushtag != NOTAG) {flushme:			p->work.type = Tflush;			p->work.tag = p->flushtag;			reply(&p->work, &rhdr, 0);		}		p->busy = 0;		m->busy = 0;	}}intopenmount(int sfd){	int p[2];	char *arg[10], fdbuf[20], mbuf[20];	if(pipe(p) < 0)		return -1;	switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNAMEG|RFFDG)){	case -1:		return -1;	default:		close(sfd);		close(p[0]);		return p[1];	case 0:		break;	}	close(p[1]);	arg[0] = "exportfs";	snprint(fdbuf, sizeof fdbuf, "-S/fd/%d", sfd);	arg[1] = fdbuf;	snprint(mbuf, sizeof mbuf, "-m%lud", messagesize-IOHDRSZ);	arg[2] = mbuf;	arg[3] = nil;	close(0);	close(1);	dup(p[0], 0);	dup(p[0], 1);	exec("/bin/exportfs", arg);	_exits("whoops: exec failed");		return -1;}voidslaveopen(Fsrpc *p){	char err[ERRMAX], *path;	Fcall *work, rhdr;	Fid *f;	Dir *d;	work = &p->work;	f = getfid(work->fid);	if(f == 0) {		reply(work, &rhdr, Ebadfid);		return;	}	if(f->fid >= 0) {		close(f->fid);		f->fid = -1;	}		path = makepath(f->f, "");	DEBUG(DFD, "\topen: %s %d\n", path, work->mode);	p->canint = 1;	if(p->flushtag != NOTAG){		free(path);		return;	}	/* There is a race here I ignore because there are no locks */	f->fid = open(path, work->mode);	free(path);	p->canint = 0;	if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {	Error:		errstr(err, sizeof err);		reply(work, &rhdr, err);		return;	}	f->f->qid = d->qid;	free(d);	if(f->f->qid.type & QTMOUNT){	/* fork new exportfs for this */		f->fid = openmount(f->fid);		if(f->fid < 0)			goto Error;	}	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);}voidslaveread(Fsrpc *p){	Fid *f;	int n, r;	Fcall *work, rhdr;	char *data, err[ERRMAX];	work = &p->work;	f = getfid(work->fid);	if(f == 0) {		reply(work, &rhdr, Ebadfid);		return;	}	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;	p->canint = 1;	if(p->flushtag != NOTAG)		return;	data = malloc(n);	if(data == nil)		fatal(Enomem);	/* can't just call pread, since directories must update the offset */	if(patternfile != nil && (f->f->qid.type&QTDIR))		r = preaddir(f, (uchar*)data, n, work->offset);	else		r = pread(f->fid, data, n, work->offset);	p->canint = 0;	if(r < 0) {		free(data);		errstr(err, sizeof err);		reply(work, &rhdr, err);		return;	}	DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);	rhdr.data = data;	rhdr.count = r;	reply(work, &rhdr, 0);	free(data);}voidslavewrite(Fsrpc *p){	char err[ERRMAX];	Fcall *work, rhdr;	Fid *f;	int n;	work = &p->work;	f = getfid(work->fid);	if(f == 0) {		reply(work, &rhdr, Ebadfid);		return;	}	n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;	p->canint = 1;	if(p->flushtag != NOTAG)		return;	n = pwrite(f->fid, work->data, n, work->offset);	p->canint = 0;	if(n < 0) {		errstr(err, sizeof err);		reply(work, &rhdr, err);		return;	}	DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);	rhdr.count = n;	reply(work, &rhdr, 0);}voidreopen(Fid *f){	USED(f);	fatal("reopen");}voidflushaction(void *a, char *cause){	USED(a);	if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {		fprint(2, "exportsrv: note: %s\n", cause);		exits("noted");	}	if(strncmp(cause, "kill", 4) == 0)		noted(NDFLT);	noted(NCONT);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -