595 lines · 8.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include "flashfs.h" static	int	nextfnum;static	Intmap*	map;static	Dir	dirproto; static	char	user[]	= "flash"; 	Entry	*root;	ulong	used;	ulong	limit;	ulong	maxwrite; enum{	debug	= 0,}; static intfnum(void){	return ++nextfnum;} static voidmaxfnum(int n){	if(n > nextfnum)		nextfnum = n;} static inthash(char *s){	int c, d, h; 	h = 0;	while((c = *s++) != '\0') {		d = c;		c ^= c << 6;		h += (c << 11) ^ (c >> 1);		h ^= (d << 14) + (d << 7) + (d << 4) + d;	} 	if(h < 0)		return ~h;	return h;} static voiddirinit(Entry *e){	Entry **t; 	e->size = 0;	t = emalloc9p(HSIZE * sizeof(Entry*));	memset(t, 0, HSIZE * sizeof(Entry*));	e->htab = t;	e->files = nil;	e->readers = nil;} static voidfileinit(Entry *e){	e->size = 0;	e->gen[0].head = nil;	e->gen[0].tail = nil;	e->gen[1].head = nil;	e->gen[1].tail = nil;} static voidelfree(Extent *x){	Extent *t; 	while(x != nil) {		t = x->next;		used -= x->size;		free(x);		x = t;	}} static voidextfree(Entry *e){	elfree(e->gen[0].head);	elfree(e->gen[1].head);} static voidefree(Entry *e){	if(debug)		fprint(2, "free %s\n", e->name); 	if(e->mode & DMDIR)		free(e->htab);	else		extfree(e); 	free(e->name);	free(e);} voideinit(void){	Entry *e; 	e = emalloc9p(sizeof(Entry));	e->ref = 1;	e->parent = nil;	dirinit(e);	e->name = estrdup9p("");	e->fnum = 0;	e->mode = DMDIR | 0775;	e->mnum = 0;	e->mtime = 0;	root = e;	map = allocmap(nil);} static voiddumptree(Entry *e, int n){	Entry *l; 	if(debug)		fprint(2, "%d %s %d\n", n, e->name, e->ref); 	if(e->mode & DMDIR) {		n++;		for(l = e->files; l != nil; l = l->fnext)			dumptree(l, n);	}} voidedump(void){	if(debug)		dumptree(root, 0);} Entry *elookup(ulong key){	if(key == 0)		return root;	maxfnum(key);	return lookupkey(map, key);} Extent *esum(Entry *e, int sect, ulong addr, int *more){	Exts *x;	Extent *t, *u; 	x = &e->gen[eparity];	t = x->tail;	if(t == nil || t->sect != sect || t->addr != addr)		return nil;	u = t->prev;	if(u != nil) {		u->next = nil;		*more = 1;	}	else {		x->head = nil;		*more = 0;	}	x->tail = u;	x = &e->gen[eparity^1];	u = x->head;	t->next = u;	x->head = t;	if(u == nil)		x->tail = t;	else		u->prev = t;	return t;} voidedestroy(Entry *e){	e->ref--;	if(e->ref == 0)		efree(e);} Entry *ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err){	int h;	Entry *e, *f; 	h = hash(name) & HMASK;	for(e = d->htab[h]; e != nil; e = e->hnext) {		if(strcmp(e->name, name) == 0) {			*err = Eexists;			return nil;		}	} 	e = emalloc9p(sizeof(Entry));	e->ref = 1;	e->parent = d;	d->ref++;	f = d->htab[h];	e->hnext = f;	e->hprev = nil;	if(f != nil)		f->hprev = e;	d->htab[h] = e;	f = d->files;	e->fnext = f;	e->fprev = nil;	if(f != nil)		f->fprev = e;	d->files = e; 	d->ref--;	e->ref++;	e->name = estrdup9p(name);	if(n == 0)		n = fnum();	else		maxfnum(n);	insertkey(map, n, e);	e->fnum = n;	e->mode = mode & d->mode;	e->mnum = 0;	e->mtime = mtime; 	if(e->mode & DMDIR)		dirinit(e);	else		fileinit(e); 	d->mtime = mtime;	return e;} voidetrunc(Entry *e, ulong n, ulong mtime){	extfree(e);	deletekey(map, e->fnum);	if(n == 0)		n = fnum();	else		maxfnum(n);	e->fnum = n;	e->mnum = 0;	e->mtime = mtime;	insertkey(map, n, e);	fileinit(e);	e->parent->mtime = mtime;} char *eremove(Entry *e){	Dirr *r;	Entry *d, *n, *p; 	d = e->parent;	if(d == nil)		return Eperm; 	if((e->mode & DMDIR) != 0 && e->files != nil)		return Edirnotempty; 	p = e->hprev;	n = e->hnext;	if(n != nil)		n->hprev = p;	if(p != nil)		p->hnext = n;	else		d->htab[hash(e->name) & HMASK] = n; 	for(r = d->readers; r != nil; r = r->next) {		if(r->cur == e)			r->cur = e->fnext;	} 	p = e->fprev;	n = e->fnext;	if(n != nil)		n->fprev = p;	if(p != nil)		p->fnext = n;	else		d->files = n; 	e->parent = nil;	d->ref--;	deletekey(map, e->fnum);	edestroy(e);	return nil;} Entry *ewalk(Entry *d, char *name, char **err){	Entry *e; 	if((d->mode & DMDIR) == 0) {		*err = Enotdir;		return nil;	} 	if(strcmp(name, "..") == 0) {		e = d->parent;		if(e == nil)			return d;		edestroy(d);		e->ref++;		return e;	} 	for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) {		if(strcmp(e->name, name) == 0) {			d->ref--;			e->ref++;			return e;		}	} 	*err = Enonexist;	return nil;} static voideread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off){	uchar *a0, *a1;	ulong n0, n1, o0, o1, d, z; 	for(;;) {		while(e != nil) {			if(off < e->off + e->size && off + n > e->off) {				if(off >= e->off) {					d = off - e->off;					z = e->size - d;					if(n <= z) {						readdata(e->sect, a, n, e->addr + d);						return;					}					readdata(e->sect, a, z, e->addr + d);					a += z;					n -= z;					off += z;				}				else {					a0 = a;					n0 = e->off - off;					o0 = off;					a += n0;					n -= n0;					off += n0;					z = e->size;					if(n <= z) {						readdata(e->sect, a, n, e->addr);						a = a0;						n = n0;						off = o0;					}					else {						readdata(e->sect, a, z, e->addr);						a1 = a + z;						n1 = n - z;						o1 = off + z;						if(n0 < n1) {							eread0(e->next, x, a0, n0, o0);							a = a1;							n = n1;							off = o1;						}						else {							eread0(e->next, x, a1, n1, o1);							a = a0;							n = n0;							off = o0;						}					}				}			}			e = e->next;		} 		if(x == nil)			break; 		e = x;		x = nil;	} 	memset(a, 0, n);} ulongeread(Entry *e, int parity, void *a, ulong n, ulong off){	if(n + off >= e->size)		n = e->size - off;	if(n <= 0)		return 0;	eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off);	return n;} voidewrite(Entry *e, Extent *x, int parity, ulong mtime){	ulong z;	Extent *t; 	t = e->gen[parity].head;	x->next = t;	x->prev = nil;	e->gen[parity].head = x;	if(t == nil)		e->gen[parity].tail = x;	else		t->prev = x;	if(mtime != 0)		e->mtime = mtime;	used += x->size;	z = x->off + x->size;	if(z > e->size)		e->size = z;} ulongechmod(Entry *e, ulong mode, ulong mnum){	if(mnum != 0)		e->mnum = mnum;	else		e->mnum++;	e->mode &= ~0777;	e->mode |= mode;	return e->mnum;} Qideqid(Entry *e){	Qid qid; 	if(e->mode & DMDIR)		qid.type = QTDIR;	else		qid.type = 0;	qid.path = e->fnum;	return qid;} voidestat(Entry *e, Dir *d, int alloc){	d->type = 'z';	d->dev = 0;	if(alloc) {		d->uid = estrdup9p(user);		d->gid = estrdup9p(user);		d->muid = estrdup9p(user);		d->name = estrdup9p(e->name);	}	else {		d->uid = user;		d->gid = user;		d->muid = user;		d->name = e->name;	}	d->mode = e->mode;	d->length = e->size;	d->atime = e->mtime;

Lines 1–500 of 595.