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

📄 nfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		mode &= (attr.mode&0777) | ~0777;	gid = attr.gid;	if(r->ifcall.perm&DMDIR)		mk = nfsMkdir;	else		mk = nfsCreate;	if((*mk)(aux->auth, r->tag, &aux->handle, r->ifcall.name, &h, mode, gid, &have, &attr) < 0	|| (!have && nfsGetattr(aux->auth, r->tag, &h, &attr) < 0)){		responderrstr(r);		return;	}	attrToQid(&attr, &r->fid->qid);	aux->parent = aux->handle;	aux->handle = h;	free(aux->name);	aux->name = estrdup9p(r->ifcall.name);	r->ofcall.qid = r->fid->qid;	respond(r, nil);}voidfsreaddir(Req *r){	FidAux *aux;	uchar *p, *freeme, *ep, *p9, *ep9;	char *s;	uint count;	int n, (*unpack)(uchar*, uchar*, uchar**, Nfs3Entry*);	Nfs3Entry e;	u64int cookie;	Dir d;	aux = r->fid->aux;	/*	 * r->ifcall.count seems a reasonable estimate to	 * how much NFS entry data we want.  is it?	 */	if(r->ifcall.offset)		cookie = aux->cookie;	else		cookie = 0;	if(nfsReadDir(aux->auth, r->tag, &aux->handle, r->ifcall.count, cookie,		&p, &count, &unpack, &freeme) < 0){		responderrstr(r);		return;	}	ep = p+count;	p9 = (uchar*)r->ofcall.data;	ep9 = p9+r->ifcall.count;	/*	 * BUG: Issue all of the stat requests in parallel.	 */	while(p < ep && p9 < ep9){		if((*unpack)(p, ep, &p, &e) < 0)			break;		aux->cookie = e.cookie;		if(strcmp(e.name, ".") == 0 || strcmp(e.name, "..") == 0)			continue;		for(s=e.name; (uchar)*s >= ' '; s++)			;		if(*s != 0)	/* bad character in name */			continue;		if(!e.haveAttr && !e.haveHandle)			if(nfsLookup(aux->auth, r->tag, &aux->handle, e.name, &e.handle, &e.haveAttr, &e.attr) < 0)				continue;		if(!e.haveAttr)			if(nfsGetattr(aux->auth, r->tag, &e.handle, &e.attr) < 0)				continue;		memset(&d, 0, sizeof d);		attrToDir(&e.attr, &d);		d.name = e.name;		if((n = convD2M(&d, p9, ep9-p9)) <= BIT16SZ)			break;		p9 += n;	}	free(freeme);	r->ofcall.count = p9 - (uchar*)r->ofcall.data;	respond(r, nil);}	voidfsread(Req *r){	uchar *p, *freeme;	uint count;	FidAux *aux;	if(r->fid->qid.type&QTDIR){		fsreaddir(r);		return;	}	aux = r->fid->aux;	if(nfsRead(aux->auth, r->tag, &aux->handle, r->ifcall.count, r->ifcall.offset, &p, &count, &freeme) < 0){		responderrstr(r);		return;	}	r->ofcall.data = (char*)p;	r->ofcall.count = count;	respond(r, nil);	free(freeme);}voidfswrite(Req *r){	uint count;	FidAux *aux;	aux = r->fid->aux;	if(nfsWrite(aux->auth, r->tag, &aux->handle, (uchar*)r->ifcall.data, r->ifcall.count, r->ifcall.offset, &count) < 0){		responderrstr(r);		return;	}	r->ofcall.count = count;	respond(r, nil);}voidfsremove(Req *r){	int n;	FidAux *aux;	aux = r->fid->aux;	if(aux->name == nil){		respond(r, "nfs3client botch -- don't know parent handle in remove");		return;	}	if(r->fid->qid.type&QTDIR)		n = nfsRmdir(aux->auth, r->tag, &aux->parent, aux->name);	else		n = nfsRemove(aux->auth, r->tag, &aux->parent, aux->name);	if(n < 0){		responderrstr(r);		return;	}	respond(r, nil);}voidfsstat(Req *r){	FidAux *aux;	Nfs3Attr attr;	aux = r->fid->aux;	if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){		responderrstr(r);		return;	}	memset(&r->d, 0, sizeof r->d);	attrToDir(&attr, &r->d);	r->d.name = estrdup9p(aux->name ? aux->name : "???");	respond(r, nil);}voidfswstat(Req *r){	int op, sync;	FidAux *aux;	Nfs3SetAttr attr;	memset(&attr, 0, sizeof attr);	aux = r->fid->aux;	/* Fill out stat first to catch errors */	op = 0;	sync = 1;	if(~r->d.mode){		if(r->d.mode&(DMAPPEND|DMEXCL)){			respond(r, "wstat -- DMAPPEND and DMEXCL bits not supported");			return;		}		op = 1;		sync = 0;		attr.setMode = 1;		attr.mode = r->d.mode & 0777;	}	if(r->d.uid && r->d.uid[0]){		attr.setUid = 1;		if(strtouid(r->d.uid, &attr.uid) < 0){			respond(r, "wstat -- unknown uid");			return;		}		op = 1;		sync = 0;	}	if(r->d.gid && r->d.gid[0]){		attr.setGid = 1;		if(strtogid(r->d.gid, &attr.gid) < 0){			respond(r, "wstat -- unknown gid");			return;		}		op = 1;		sync = 0;	}	if(~r->d.length){		attr.setSize = 1;		attr.size = r->d.length;		op = 1;		sync = 0;	}	if(~r->d.mtime){		attr.setMtime = Nfs3SetTimeClient;		attr.mtime.sec = r->d.mtime;		op = 1;		sync = 0;	}	if(~r->d.atime){		attr.setAtime = Nfs3SetTimeClient;		attr.atime.sec = r->d.atime;		op = 1;		sync = 0;	}	/* Try rename first because it's more likely to fail (?) */	if(r->d.name && r->d.name[0]){		if(aux->name == nil){			respond(r, "nfsclient botch -- don't know parent handle in rename");			return;		}		if(nfsRename(aux->auth, r->tag, &aux->parent, aux->name, &aux->parent, r->d.name) < 0){			responderrstr(r);			return;		}		free(aux->name);		aux->name = estrdup9p(r->d.name);		sync = 0;	}	/*	 * Now we have a problem.  The rename succeeded	 * but the setattr could fail.  Sic transit atomicity.	 */	if(op){		if(nfsSetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){			responderrstr(r);			return;		}	}	if(sync){		/* NFS commit */		if(nfsCommit(aux->auth, r->tag, &aux->handle) < 0){			responderrstr(r);			return;		}	}	respond(r, nil);}char*fswalk1(Fid *fid, char *name, void *v){	u1int have;	ulong tag;	FidAux *aux;	Nfs3Attr attr;	Nfs3Handle h;	tag = *(ulong*)v;	aux = fid->aux;	if(nfsLookup(aux->auth, tag, &aux->handle, name, &h, &have, &attr) < 0	|| (!have && nfsGetattr(aux->auth, tag, &h, &attr) < 0)){		rerrstr(aux->err, sizeof aux->err);		return aux->err;	}	aux->parent = aux->handle;	aux->handle = h;	free(aux->name);	if(strcmp(name, "..") == 0)		aux->name = nil;	else		aux->name = estrdup9p(name);	attrToQid(&attr, &fid->qid);	return nil;}char*fsclone(Fid *fid, Fid *newfid, void*){	FidAux *a, *na;	a = fid->aux;	na = emalloc9p(sizeof(FidAux));	*na = *a;	if(na->name)		na->name = estrdup9p(na->name);	newfid->aux = na;	if(na->auth)		na->auth->ref++;	return nil;}voidfswalk(Req *r){	walkandclone(r, fswalk1, fsclone, &r->tag);}voidfsflush(Req *r){	Req *or;	/*	 * Send on the flush channel(s).	 * The library will make sure the response	 * is delayed as necessary.	 */	or = r->oldreq;	if(nfscli)		sendul(nfscli->flushchan, (ulong)or->tag);	if(mntcli)		sendul(mntcli->flushchan, (ulong)or->tag);	respond(r, nil);}voidfsdispatch(void *v){	Req *r;	r = v;	switch(r->ifcall.type){	default:	respond(r, "unknown type");	break;	case Tattach:	fsattach(r);	break;	case Topen:	fsopen(r);	break;	case Tcreate:	fscreate(r);	break;	case Tread:	fsread(r);	break;	case Twrite:	fswrite(r);	break;	case Tremove:	fsremove(r);	break;	case Tflush:	fsflush(r);	break;	case Tstat:	fsstat(r);	break;	case Twstat:	fswstat(r);	break;	case Twalk:	fswalk(r);	break;	}}voidfsthread(void*){	Req *r;	while((r = recvp(fschan)) != nil)		threadcreate(fsdispatch, r, SunStackSize);}voidfssend(Req *r){	sendp(fschan, r);}voidfsdie(Srv*){	threadexitsall(nil);}Srv fs ={.destroyfid =	fsdestroyfid,.attach=		fssend,.open=		fssend,.create=		fssend,.read=		fssend,.write=		fssend,.remove=		fssend,.flush=		fssend,.stat=		fssend,.wstat=		fssend,.walk=		fssend,.end=		fsdie};voidusage(void){	fprint(2, "usage: nfs [-DRv] [-p perm] [-s srvname] [-u passwd group] addr [addr]\n");	fprint(2, "\taddr - address of portmapper server\n");	fprint(2, "\taddr addr - addresses of mount server and nfs server\n");	exits("usage");}char*netchangeport(char *addr, uint port, char *buf, uint nbuf){	char *r;	strecpy(buf, buf+nbuf, addr);	r = strrchr(buf, '!');	if(r == nil)		return nil;	r++;	seprint(r, buf+nbuf, "%ud", port);	return buf;}char mbuf[256], nbuf[256];char *mountaddr, *nfsaddr;Channel *csync;int chattyrpc;void dialproc(void*);voidthreadmain(int argc, char **argv){	char *srvname, *passwd, *group, *addr, *p;	SunClient *cli;	int proto;	uint mport, nport;	ulong perm;	Dir d;	perm = 0600;	passwd = nil;	group = nil;	srvname = nil;	sys = sysname();	if(sys == nil)		sys = "plan9";	ARGBEGIN{	default:		usage();	case 'D':		chatty9p++;		break;	case 'R':		chattyrpc++;		break;	case 'p':		perm = strtol(EARGF(usage()), &p, 8);		if(perm==0 || *p != 0)			usage();		break;	case 's':		srvname = EARGF(usage());		break;	case 'u':		passwd = EARGF(usage());		group = EARGF(usage());		break;	case 'v':		verbose++;		break;	}ARGEND	if(argc != 1 && argc != 2)		usage();	if(srvname == nil)		srvname = argv[0];	fmtinstall('B', sunRpcFmt);	fmtinstall('C', sunCallFmt);	fmtinstall('H', encodefmt);	sunFmtInstall(&portProg);	sunFmtInstall(&nfs3Prog);	sunFmtInstall(&nfsMount3Prog);	if(passwd && (map = readmap(passwd, group)) == nil)		fprint(2, "warning: reading %s and %s: %r\n", passwd, group);	if(map == nil)		map = &emptymap;	if(argc == 1){		addr = netmkaddr(argv[0], "udp", "portmap");		if((cli = sunDial(addr)) == nil)			sysfatal("dial %s: %r", addr);		cli->chatty = chattyrpc;		sunClientProg(cli, &portProg);		if(strstr(addr, "udp!"))			proto = PortProtoUdp;		else			proto = PortProtoTcp;		if(getport(cli, NfsMount3Program, NfsMount3Version, proto, &mport) < 0)			sysfatal("lookup mount program port: %r");		if(getport(cli, Nfs3Program, Nfs3Version, proto, &nport) < 0)			sysfatal("lookup nfs program port: %r");		sunClientClose(cli);		mountaddr = netchangeport(addr, mport, mbuf, sizeof mbuf);		nfsaddr = netchangeport(addr, nport, nbuf, sizeof nbuf);		strcat(mountaddr, "!r");		strcat(nfsaddr, "!r");		if(verbose)			fprint(2, "nfs %s %s\n", mountaddr, nfsaddr);	}else{		mountaddr = argv[0];		nfsaddr = argv[1];	}	/* have to dial in another proc because it creates threads */	csync = chancreate(sizeof(void*), 0);	proccreate(dialproc, nil, SunStackSize);	recvp(csync);	threadpostmountsrv(&fs, srvname, nil, 0);	if(perm != 0600){		p = smprint("/srv/%s", srvname);		if(p){			nulldir(&d);			d.mode = perm;			dirwstat(p, &d);		}	}	threadexits(nil);}voiddialproc(void*){	rfork(RFNAMEG);	rfork(RFNOTEG);	if((mntcli = sunDial(mountaddr)) == nil)		sysfatal("dial mount program at %s: %r", mountaddr);	mntcli->chatty = chattyrpc;	sunClientProg(mntcli, &nfsMount3Prog);	if(mountNull(0) < 0)		sysfatal("execute nop with mnt server at %s: %r", mountaddr);		if((nfscli = sunDial(nfsaddr)) == nil)		sysfatal("dial nfs program at %s: %r", nfsaddr);	nfscli->chatty = chattyrpc;	sunClientProg(nfscli, &nfs3Prog);	if(nfsNull(0) < 0)		sysfatal("execute nop with nfs server at %s: %r", nfsaddr);	fschan = chancreate(sizeof(Req*), 0);	threadcreate(fsthread, nil, SunStackSize);	sendp(csync, 0);}

⌨️ 快捷键说明

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