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

📄 entry.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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;	d->mtime = e->mtime;	d->qid = eqid(e);}Dirr *ediropen(Entry *e){	Dirr *d, *t;	d = emalloc9p(sizeof(Dirr));	d->dir = e;	d->cur = e->files;	t = e->readers;	d->next = t;	d->prev = nil;	if(t != nil)		t->prev = d;	e->readers = d;	e->ref++;	return d;}intedirread(Dirr *r, char *a, long n){	Dir d;	Entry *e;	int m, x;	m = 0;	for(e = r->cur; e != nil; e = e->fnext) {		estat(e, &d, 0);		x = convD2M(&d, (uchar *)a, n);		if(x <= BIT16SZ)			break;		a += x;		n -= x;		m += x;	}	r->cur = e;	return m;}voidedirclose(Dirr *d){	Entry *e;	Dirr *p, *n;	e = d->dir;	p = d->prev;	n = d->next;	if(n != nil)		n->prev = p;	if(p != nil)		p->next = n;	else		e->readers = n;	edestroy(e);	free(d);}static	Renum	R;static voidxrenum(Extent *x){	while(x != nil) {		if(x->sect == R.old)			x->sect = R.new;		x = x->next;	}}static voidrenum(Entry *e){	if(e->mode & DMDIR) {		for(e = e->files; e != nil; e = e->fnext)			renum(e);	}	else {		xrenum(e->gen[0].head);		xrenum(e->gen[1].head);	}}voiderenum(Renum *r){	R = *r;	renum(root);}

⌨️ 快捷键说明

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