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

📄 exportsrv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.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";int iounit(int x){	return 8192+IOHDRSZ;}void*emallocz(ulong n){	void *v;	v = mallocz(n, 1);	if(v == nil)		panic("out of memory");	return v;}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 %d 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){	Fcall rhdr;	Fid *f;	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;	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;	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;	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;	int pid;	static int nproc;	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);				if(pid != p->pid)					fatal("rendezvous sync fail");				return;			}			}		if(++nproc > MAXPROC)			fatal("too many procs");		pid = kproc("slave", blockingslave, nil);		DEBUG(DFD, "slave pid %d\n", pid);		if(pid == -1)			fatal("kproc");		p = malloc(sizeof(Proc));		if(p == 0)			fatal("out of memory");		p->busy = 0;		p->pid = pid;		p->next = Proclist;		Proclist = p;DEBUG(DFD, "parent %d rendez\n", pid);		rendezvous((void*)(uintptr)pid, p);DEBUG(DFD, "parent %d went\n", pid);	}}voidblockingslave(void *x){	Fsrpc *p;	Fcall rhdr;	Proc *m;	int pid;	USED(x);	notify(flushaction);	pid = getpid();DEBUG(DFD, "blockingslave %d rendez\n", pid);	m = (Proc*)rendezvous((void*)(uintptr)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 */			continue;		DEBUG(DFD, "\tslave: %d %F b %d p %d\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){	werrstr("openmount not implemented");	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;	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 */	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 + -