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

📄 nfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
			return 0;		}		if(readplus == 0){			rerrstr(e, sizeof e);			if(strstr(e, "procedure unavailable") || strstr(e, "not supported"))				readplus = -1;		}		if(readplus == 0)			fprint(2, "readdirplus: %r\n");	}	if(readplus == 1)		return -1;	memset(&tx, 0, sizeof tx);	nfs3Call(a, &tx.call, Nfs3CallTReadDir);	tx.handle = *h;	tx.count = count;	tx.cookie = cookie;	memset(&rx, 0, sizeof rx);	nfs3Call(a, &rx.call, Nfs3CallRReadDir);	if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0)		return -1;	if(rx.status != Nfs3Ok){		free(*pfreeme);		*pfreeme = 0;		nfs3Errstr(rx.status);		return -1;	}	/* readplus failed but read succeeded */	readplus = -1;	*unpack = nfs3EntryUnpack;	*pcount = rx.count;	*pp = rx.data;	return 0;}/* * name <-> int translation */typedef struct Map Map;typedef struct User User;typedef struct Group Group;Map *map;Map emptymap;struct User{	char *name;	uint uid;	uint gid;	uint g[16];	uint ng;	uchar *auth;	int nauth;};struct Group{	char *name;	/* same pos as in User struct */	uint gid;	/* same pos as in User struct */};struct Map{	int nuser;	int ngroup;	User *user;	User **ubyname;	User **ubyid;	Group *group;	Group **gbyname;	Group **gbyid;};User*finduser(User **u, int nu, char *s){	int lo, hi, mid, n;	hi = nu;	lo = 0;	while(hi > lo){		mid = (lo+hi)/2;		n = strcmp(u[mid]->name, s);		if(n == 0)			return u[mid];		if(n < 0)			lo = mid+1;		else			hi = mid;	}	return nil;}intstrtoid(User **u, int nu, char *s, u32int *id){	u32int x;	char *p;	User *uu;	x = strtoul(s, &p, 10);	if(*s != 0 && *p == 0){		*id = x;		return 0;	}	uu = finduser(u, nu, s);	if(uu == nil)		return -1;	*id = uu->uid;	return 0;}char*idtostr(User **u, int nu, u32int id){	char buf[32];	int lo, hi, mid;	hi = nu;	lo = 0;	while(hi > lo){		mid = (lo+hi)/2;		if(u[mid]->uid == id)			return estrdup9p(u[mid]->name);		if(u[mid]->uid < id)			lo = mid+1;		else			hi = mid;	}	snprint(buf, sizeof buf, "%ud", id);		return estrdup9p(buf);}		char*uidtostr(u32int uid){	return idtostr(map->ubyid, map->nuser, uid);}char*gidtostr(u32int gid){	return idtostr((User**)map->gbyid, map->ngroup, gid);}intstrtouid(char *s, u32int *id){	return strtoid(map->ubyname, map->nuser, s, id);}intstrtogid(char *s, u32int *id){	return strtoid((User**)map->gbyid, map->ngroup, s, id);}intidcmp(const void *va, const void *vb){	User **a, **b;	a = (User**)va;	b = (User**)vb;	return (*a)->uid - (*b)->uid;}intnamecmp(const void *va, const void *vb){	User **a, **b;	a = (User**)va;	b = (User**)vb;	return strcmp((*a)->name, (*b)->name);}voidclosemap(Map *m){	int i;	for(i=0; i<m->nuser; i++){		free(m->user[i].name);		free(m->user[i].auth);	}	for(i=0; i<m->ngroup; i++)		free(m->group[i].name);	free(m->user);	free(m->group);	free(m->ubyid);	free(m->ubyname);	free(m->gbyid);	free(m->gbyname);	free(m);}Map*readmap(char *passwd, char *group){	char *s, *f[10], *p, *nextp, *name;	uchar *q, *eq;	int i, n, nf, line, uid, gid;	Biobuf *b;	Map *m;	User *u;	Group *g;	SunAuthUnix au;	m = emalloc(sizeof(Map));	if((b = Bopen(passwd, OREAD)) == nil){		free(m);		return nil;	}	line = 0;	for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){		line++;		if(s[0] == '#')			continue;		nf = getfields(s, f, nelem(f), 0, ":");		if(nf < 4)			continue;		name = f[0];		uid = strtol(f[2], &p, 10);		if(f[2][0] == 0 || *p != 0){			fprint(2, "%s:%d: non-numeric id in third field\n", passwd, line);			continue;		}		gid = strtol(f[3], &p, 10);		if(f[3][0] == 0 || *p != 0){			fprint(2, "%s:%d: non-numeric id in fourth field\n", passwd, line);			continue;		}		if(m->nuser%32 == 0)			m->user = erealloc(m->user, (m->nuser+32)*sizeof(m->user[0]));		u = &m->user[m->nuser++];		u->name = estrdup9p(name);		u->uid = uid;		u->gid = gid;		u->ng = 0;		u->auth = 0;		u->nauth = 0;	}	Bterm(b);	m->ubyname = emalloc(m->nuser*sizeof(User*));	m->ubyid = emalloc(m->nuser*sizeof(User*));	for(i=0; i<m->nuser; i++){		m->ubyname[i] = &m->user[i];		m->ubyid[i] = &m->user[i];	}	qsort(m->ubyname, m->nuser, sizeof(m->ubyname[0]), namecmp);	qsort(m->ubyid, m->nuser, sizeof(m->ubyid[0]), idcmp);	if((b = Bopen(group, OREAD)) == nil){		closemap(m);		return nil;	}	line = 0;	for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){		line++;		if(s[0] == '#')			continue;		nf = getfields(s, f, nelem(f), 0, ":");		if(nf < 4)			continue;		name = f[0];		gid = strtol(f[2], &p, 10);		if(f[2][0] == 0 || *p != 0){			fprint(2, "%s:%d: non-numeric id in third field\n", group, line);			continue;		}		if(m->ngroup%32 == 0)			m->group = erealloc(m->group, (m->ngroup+32)*sizeof(m->group[0]));		g = &m->group[m->ngroup++];		g->name = estrdup9p(name);		g->gid = gid;		for(p=f[3]; *p; p=nextp){			if((nextp = strchr(p, ',')) != nil)				*nextp++ = 0;			else				nextp = p+strlen(p);			u = finduser(m->ubyname, m->nuser, p);			if(u == nil){				if(verbose)					fprint(2, "%s:%d: unknown user %s\n", group, line, p);				continue;			}			if(u->ng >= nelem(u->g)){				fprint(2, "%s:%d: user %s is in too many groups; ignoring %s\n", group, line, p, name);				continue;			}			u->g[u->ng++] = gid;		}	}	Bterm(b);	m->gbyname = emalloc(m->ngroup*sizeof(Group*));	m->gbyid = emalloc(m->ngroup*sizeof(Group*));	for(i=0; i<m->ngroup; i++){		m->gbyname[i] = &m->group[i];		m->gbyid[i] = &m->group[i];	}	qsort(m->gbyname, m->ngroup, sizeof(m->gbyname[0]), namecmp);	qsort(m->gbyid, m->ngroup, sizeof(m->gbyid[0]), idcmp);	for(i=0; i<m->nuser; i++){		au.stamp = 0;		au.sysname = sys;		au.uid = m->user[i].uid;		au.gid = m->user[i].gid;		memmove(au.g, m->user[i].g, sizeof au.g);		au.ng = m->user[i].ng;		n = sunAuthUnixSize(&au);		q = emalloc(n);		eq = q+n;		m->user[i].auth = q;		m->user[i].nauth = n;		if(sunAuthUnixPack(q, eq, &q, &au) < 0 || q != eq){			fprint(2, "sunAuthUnixPack failed for %s\n", m->user[i].name);			free(m->user[i].auth);			m->user[i].auth = 0;			m->user[i].nauth = 0;		}	}	return m;}Auth*mkauth(char *user){	Auth *a;	uchar *p;	int n;	SunAuthUnix au;	User *u;	u = finduser(map->ubyname, map->nuser, user);	if(u == nil || u->nauth == 0){		/* nobody */		au.stamp = 0;		au.uid = -1;		au.gid = -1;		au.ng = 0;		au.sysname = sys;		n = sunAuthUnixSize(&au);		a = emalloc(sizeof(Auth)+n);		a->data = (uchar*)&a[1];		a->ndata = n;		if(sunAuthUnixPack(a->data, a->data+a->ndata, &p, &au) < 0		|| p != a->data+a->ndata){			free(a);			return nil;		}		a->ref = 1;if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);		return a;	}	a = emalloc(sizeof(Auth)+u->nauth);	a->data = (uchar*)&a[1];	a->ndata = u->nauth;	memmove(a->data, u->auth, a->ndata);	a->ref = 1;if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data);	return a;}voidfreeauth(Auth *a){	if(--a->ref > 0)		return;	free(a);}/* * 9P server */voidresponderrstr(Req *r){	char e[ERRMAX];	rerrstr(e, sizeof e);	respond(r, e);}voidfsdestroyfid(Fid *fid){	FidAux *aux;	aux = fid->aux;	if(aux == nil)		return;	freeauth(aux->auth);	free(aux->name);	free(aux);}voidattrToQid(Nfs3Attr *attr, Qid *qid){	qid->path = attr->fileid;	qid->vers = attr->mtime.sec;	qid->type = 0;	if(attr->type == Nfs3FileDir)		qid->type |= QTDIR;}voidattrToDir(Nfs3Attr *attr, Dir *d){	d->mode = attr->mode & 0777;	if(attr->type == Nfs3FileDir)		d->mode |= DMDIR;	d->uid = uidtostr(attr->uid);	d->gid = gidtostr(attr->gid);	d->length = attr->size;	attrToQid(attr, &d->qid);	d->mtime = attr->mtime.sec;	d->atime = attr->atime.sec;	d->muid = nil;}voidfsattach(Req *r){	char *path;	Auth *auth;	FidAux *aux;	Nfs3Attr attr;	Nfs3Handle h;	path = r->ifcall.aname;	if(path==nil || path[0]==0)		path = defaultpath;	auth = mkauth(r->ifcall.uname);	if(mountMnt(auth, r->tag, path, &h) < 0	|| nfsGetattr(auth, r->tag, &h, &attr) < 0){		freeauth(auth);		responderrstr(r);		return;	}	aux = emalloc(sizeof(FidAux));	aux->auth = auth;	aux->handle = h;	aux->cookie = 0;	aux->name = nil;	memset(&aux->parent, 0, sizeof aux->parent);	r->fid->aux = aux;	attrToQid(&attr, &r->fid->qid);	r->ofcall.qid = r->fid->qid;	respond(r, nil);}voidfsopen(Req *r){	FidAux *aux;	Nfs3Attr attr;	Nfs3SetAttr sa;	u1int have;	ulong a, b;	aux = r->fid->aux;	a = 0;	switch(r->ifcall.mode&OMASK){	case OREAD:		a = 0x0001;		break;	case OWRITE:		a = 0x0004;		break;	case ORDWR:		a = 0x0001|0x0004;		break;	case OEXEC:		a = 0x20;		break;	}	if(r->ifcall.mode&OTRUNC)		a |= 0x0004;	if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0	|| (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){    Error:		responderrstr(r);		return;	}	if(a != b){		respond(r, "permission denied");		return;	}	if(r->ifcall.mode&OTRUNC){		memset(&sa, 0, sizeof sa);		sa.setSize = 1;		if(nfsSetattr(aux->auth, r->tag, &aux->handle, &sa) < 0)			goto Error;	}	attrToQid(&attr, &r->fid->qid);	r->ofcall.qid = r->fid->qid;	respond(r, nil);}voidfscreate(Req *r){	FidAux *aux;	u1int have;	Nfs3Attr attr;	Nfs3Handle h;	ulong mode;	uint gid;	int (*mk)(Auth*, ulong, Nfs3Handle*, char*, Nfs3Handle*, ulong, uint, u1int*, Nfs3Attr*);	aux = r->fid->aux;	/*	 * Plan 9 has no umask, so let's use the	 * parent directory bits like Plan 9 does.	 * What the heck, let's inherit the group too.	 * (Unix will let us set the group to anything	 * since we're the owner!)	 */	if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){		responderrstr(r);		return;	}	mode = r->ifcall.perm&0777;	if(r->ifcall.perm&DMDIR)		mode &= (attr.mode&0666) | ~0666;	else

⌨️ 快捷键说明

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