rscext2 fixes36f827420 years agoHistory
516 lines · 9.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <thread.h>#include <sunrpc.h>#include <nfs3.h>#include <diskfs.h>#include <venti.h>#include <libsec.h> #undef stime#define stime configstime	/* sometimes in <time.h> */typedef struct Entry Entry;struct Entry{	Entry *parent;	Entry *nextdir;	Entry *nexthash;	Entry *kids;	int isfsys;	Fsys *fsys;	uchar score[VtScoreSize];	/* of fsys */	char *name;	uchar sha1[VtScoreSize];	/* of path to this entry */	ulong time;}; typedef struct Config Config;struct Config{	VtCache *vcache;	Entry *root;	Entry *hash[1024];	Qid qid;}; Config *config;static	ulong 	mtime;	/* mod time */static	ulong 	stime;	/* sync time */static	char*	configfile; static int addpath(Config*, char*, uchar[VtScoreSize], ulong);Fsys fsysconfig; static voidfreeconfig(Config *c){	Entry *next, *e;	int i; 	for(i=0; i<nelem(c->hash); i++){		for(e=c->hash[i]; e; e=next){			next = e->nexthash;			free(e);		}	}	free(c);} static intnamehash(uchar *s){	return (s[0]<<2)|(s[1]>>6);} static Entry*entrybyhandle(Nfs3Handle *h){	int hh;	Entry *e; 	hh = namehash(h->h);	for(e=config->hash[hh]; e; e=e->nexthash)		if(memcmp(e->sha1, h->h, VtScoreSize) == 0)			return e;	return nil;} static Config*readconfigfile(char *name, VtCache *vcache){	char *p, *pref, *f[10];	int ok;	Config *c;	uchar score[VtScoreSize];	int h, nf, line;	Biobuf *b;	Dir *dir; 	configfile = vtstrdup(name); 	if((dir = dirstat(name)) == nil)		return nil;		if((b = Bopen(name, OREAD)) == nil){		free(dir);		return nil;	} 	line = 0;	ok = 1;	c = emalloc(sizeof(Config));	c->vcache = vcache;	c->qid = dir->qid;	free(dir);	c->root = emalloc(sizeof(Entry));	c->root->name = "/";	c->root->parent = c->root;	sha1((uchar*)"/", 1, c->root->sha1, nil);	h = namehash(c->root->sha1);	c->hash[h] = c->root; 	for(; (p = Brdstr(b, '\n', 1)) != nil; free(p)){		line++;		if(p[0] == '#')			continue;		nf = tokenize(p, f, nelem(f));		if(nf != 3){			fprint(2, "%s:%d: syntax error\n", name, line);			/* ok = 0; */			continue;		}		if(vtparsescore(f[1], &pref, score) < 0){			fprint(2, "%s:%d: bad score '%s'\n", name, line, f[1]);			/* ok = 0; */			continue;		}		if(f[0][0] != '/'){			fprint(2, "%s:%d: unrooted path '%s'\n", name, line, f[0]);			/* ok = 0; */			continue;		}		if(addpath(c, f[0], score, strtoul(f[2], 0, 0)) < 0){			fprint(2, "%s:%d: %s: %r\n", name, line, f[0]);			/* ok = 0; */			continue;		}	}	Bterm(b); 	if(!ok){		freeconfig(c);		return nil;	}		return c;} static voidrefreshconfig(void){	ulong now;	Config *c, *old;	Dir *d; 	now = time(0);	if(now - stime < 60)		return;	if((d = dirstat(configfile)) == nil)		return;	if(d->mtime == mtime){		free(d);		stime = now;		return;	} 	c = readconfigfile(configfile, config->vcache);	if(c == nil){		free(d);		return;	} 	old = config;	config = c;	stime = now;	mtime = d->mtime;	free(d);	freeconfig(old);} static Entry*entrylookup(Entry *e, char *p, int np){	for(e=e->kids; e; e=e->nextdir)		if(strlen(e->name) == np && memcmp(e->name, p, np) == 0)			return e;	return nil;} static Entry*walkpath(Config *c, char *name){	Entry *e, *ee;	char *p, *nextp;	int h; 	e = c->root;	p = name;	for(; *p; p=nextp){		assert(*p == '/');		p++;		nextp = strchr(p, '/');		if(nextp == nil)			nextp = p+strlen(p);		if(e->fsys){			werrstr("%.*s is already a mount point", utfnlen(name, nextp-name), name);			return nil;		}		if((ee = entrylookup(e, p, nextp-p)) == nil){			ee = emalloc(sizeof(Entry)+(nextp-p)+1);			ee->parent = e;			ee->nextdir = e->kids;			e->kids = ee;			ee->name = (char*)&ee[1];			memmove(ee->name, p, nextp-p);			ee->name[nextp-p] = 0;			sha1((uchar*)name, nextp-name, ee->sha1, nil);			h = namehash(ee->sha1);			ee->nexthash = c->hash[h];			c->hash[h] = ee;		}		e = ee;	}	if(e->kids){		werrstr("%s already has children; cannot be mount point", name);		return nil;	}	return e;} static intaddpath(Config *c, char *name, uchar score[VtScoreSize], ulong time){	Entry *e; 	e = walkpath(c, name);	if(e == nil)		return -1;	e->isfsys = 1;	e->time = time;	memmove(e->score, score, VtScoreSize);	return 0;} static voidmkhandle(Nfs3Handle *h, Entry *e){	memmove(h->h, e->sha1, VtScoreSize);	h->len = VtScoreSize;} Nfs3Statushandleparse(Nfs3Handle *h, Fsys **pfsys, Nfs3Handle *nh, int isgetattr){	int hh;	Entry *e;	Disk *disk;	Fsys *fsys; 	refreshconfig(); 	if(h->len < VtScoreSize)		return Nfs3ErrBadHandle; 	hh = namehash(h->h);	for(e=config->hash[hh]; e; e=e->nexthash)		if(memcmp(e->sha1, h->h, VtScoreSize) == 0)			break;	if(e == nil)		return Nfs3ErrBadHandle; 	if(e->isfsys == 1 && e->fsys == nil && (h->len != VtScoreSize || !isgetattr)){		if((disk = diskopenventi(config->vcache, e->score)) == nil){			fprint(2, "cannot open disk %V: %r\n", e->score);			return Nfs3ErrIo;		}		if((fsys = fsysopen(disk)) == nil){			fprint(2, "cannot open fsys on %V: %r\n", e->score);			diskclose(disk);			return Nfs3ErrIo;		}		e->fsys = fsys;	} 	if(e->fsys == nil || (isgetattr && h->len == VtScoreSize)){		if(h->len != VtScoreSize)			return Nfs3ErrBadHandle;		*pfsys = &fsysconfig;		*nh = *h;		return Nfs3Ok;	}	*pfsys = e->fsys;	if(h->len == VtScoreSize)		return fsysroot(*pfsys, nh);	nh->len = h->len - VtScoreSize;	memmove(nh->h, h->h+VtScoreSize, nh->len);	return Nfs3Ok;} voidhandleunparse(Fsys *fsys, Nfs3Handle *h, Nfs3Handle *nh, int dotdot){	Entry *e;	int hh; 	refreshconfig(); 	if(fsys == &fsysconfig)		return; 	if(dotdot && nh->len == h->len - VtScoreSize	&& memcmp(h->h+VtScoreSize, nh->h, nh->len) == 0){		/* walked .. but didn't go anywhere: must be at root */		hh = namehash(h->h);		for(e=config->hash[hh]; e; e=e->nexthash)			if(memcmp(e->sha1, h->h, VtScoreSize) == 0)				break;		if(e == nil)			return;	/* cannot happen */ 		/* walk .. */		e = e->parent;		nh->len = VtScoreSize;		memmove(nh->h, e->sha1, VtScoreSize);		return;	} 	/* otherwise just insert the same prefix */	memmove(nh->h+VtScoreSize, nh->h, VtScoreSize);	nh->len += VtScoreSize;	memmove(nh->h, h->h, VtScoreSize);} Nfs3Statusfsysconfigroot(Fsys *fsys, Nfs3Handle *h){	USED(fsys); 	mkhandle(h, config->root);	return Nfs3Ok;} Nfs3Statusfsysconfiggetattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr){	Entry *e; 	USED(fsys);	USED(au); 	if(h->len != VtScoreSize)		return Nfs3ErrBadHandle; 	e = entrybyhandle(h);	if(e == nil)		return Nfs3ErrNoEnt; 	memset(attr, 0, sizeof *attr);	attr->type = Nfs3FileDir;	attr->mode = 0555;	attr->nlink = 2;	attr->size = 1024;	attr->fileid = *(u64int*)h->h;	attr->atime.sec = e->time;	attr->mtime.sec = e->time;	attr->ctime.sec = e->time;	return Nfs3Ok;} Nfs3Statusfsysconfigaccess(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr){	want &= Nfs3AccessRead|Nfs3AccessLookup|Nfs3AccessExecute;	*got = want;	return fsysconfiggetattr(fsys, au, h, attr);} Nfs3Statusfsysconfiglookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh){	Entry *e; 	USED(fsys);	USED(au); 	if(h->len != VtScoreSize)		return Nfs3ErrBadHandle; 	e = entrybyhandle(h);	if(e == nil)		return Nfs3ErrNoEnt; 	if(strcmp(name, "..") == 0)		e = e->parent;	else if(strcmp(name, ".") == 0){		/* nothing */	}else{		if((e = entrylookup(e, name, strlen(name))) == nil)			return Nfs3ErrNoEnt;	} 	mkhandle(nh, e);	return Nfs3Ok;} Nfs3Statusfsysconfigreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link){	USED(h);	USED(fsys);	USED(au); 	*link = 0;	return Nfs3ErrNotSupp;} Nfs3Statusfsysconfigreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int offset, uchar **pdata, u32int *pcount, u1int *peof){	USED(fsys);	USED(h);	USED(count);	USED(offset);	USED(pdata);	USED(pcount);	USED(peof);	USED(au); 	return Nfs3ErrNotSupp;} Nfs3Statusfsysconfigreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int cookie, uchar **pdata, u32int *pcount, u1int *peof){	uchar *data, *p, *ep, *np;	u64int c;	Entry *e;	Nfs3Entry ne; 	USED(fsys);	USED(au); 	if(h->len != VtScoreSize)		return Nfs3ErrBadHandle; 	e = entrybyhandle(h);	if(e == nil)		return Nfs3ErrNoEnt; 	e = e->kids;	c = cookie;	for(; c && e; c--)		e = e->nextdir;	if(e == nil){		*pdata = 0;		*pcount = 0;		*peof = 1;		return Nfs3Ok;	} 	data = emalloc(count);	p = data;	ep = data+count;	while(e && p < ep){		ne.name = e->name;		ne.namelen = strlen(e->name);		ne.cookie = ++cookie;		ne.fileid = *(u64int*)e->sha1;		if(nfs3entrypack(p, ep, &np, &ne) < 0)			break;		p = np;		e = e->nextdir;	}	*pdata = data;	*pcount = p - data;	*peof = 0;	return Nfs3Ok;} voidfsysconfigclose(Fsys *fsys){	USED(fsys);} intreadconfig(char *name, VtCache *vcache, Nfs3Handle *h){	Config *c;	Dir *d; 	if((d = dirstat(name)) == nil)		return -1; 	c = readconfigfile(name, vcache);	if(c == nil){		free(d);		return -1;	} 

Lines 1–500 of 516.