plan 9 kernel history: overview | file list | diff list

1996/0201/port/devtinyfs.c (diff list | history)

1996/0131/sys/src/9/port/devtinyfs.c:15,421996/0201/sys/src/9/port/devtinyfs.c:15,79 (short | long | prev | next)
1996/0116    
	Qdir, 
1996/0120    
	Qmedium, 
1996/0123    
 
1996/0131    
	Blen=	48, 
1996/0201    
	Maxfs=		10,	/* max file systems */ 
1996/0131    
 
	Tdir=	0, 
	Tdata, 
	Tend, 
1996/0201    
	Blen=		48,	/* block length */ 
	Nlen=		28,	/* name length */ 
	Dlen=		Blen - 4, 
 
	Tagdir=		'd', 
	Tagdata=	'D', 
	Tagend=		'e', 
	Tagfree=	'f', 
 
	Nopin=		0xffff; 
1996/0116    
}; 
 
1996/0122    
typedef struct FS FS; 
struct FS { 
1996/0116    
	QLock; 
1996/0122    
	Ref	r; 
	int	dev; 
	FS	*next; 
1996/0201    
/* medium representation of a Tdir */ 
typedef struct Mdir Mdir; 
struct Mdir { 
	uchar	type; 
	uchar	bno[2]; 
	uchar	pin[2]; 
	char	name[Nlen]; 
	char	pad[Blen - Nlen - 6]; 
	uchar	sum; 
}; 
 
/* medium representation of a Tdata/Tend */ 
typedef struct Mdata Mdata; 
struct Mdata { 
	uchar	type; 
	uchar	bno[2]; 
	char	data[Dlen]; 
	uchar	sum; 
}; 
 
typedef struct Tfile Tfile; 
struct Tfile { 
	char	name[NAMELEN]; 
	ushort	bno; 
	ushort	dbno; 
	ushort	pin; 
	ulong	length; 
}; 
 
typedef struct Tfs Tfs; 
struct Tfs { 
	Lock; 
	int	r; 
1996/0116    
	Chan	*c; 
1996/0131    
	uchar	*map; 
	int	nblocks; 
1996/0201    
	Tfile	*f; 
	int	nf; 
	int	fsize; 
1996/0122    
}; 
 
struct { 
	QLock; 
	FS	*l; 
	int	hidev; 
1996/0201    
	Tfs	fs[Maxfs]; 
	short	nfs; 
1996/0116    
} tinyfs; 
 
1996/0131    
#define GETS(x) ((x)[0]|((x)[1]<<8)) 
1996/0131/sys/src/9/port/devtinyfs.c:45,601996/0201/sys/src/9/port/devtinyfs.c:82,87
1996/0131    
#define GETL(x) (GETS(x)|(GETS(x+2)<<16)) 
#define PUTL(x, v) {PUTS(x, v);PUTS(x+2, (v)>>16)}; 
 
1996/0116    
void 
tinyfsreset(void) 
{ 
} 
                 
void 
tinyfsinit(void) 
{ 
} 
                 
1996/0131    
static uchar 
checksum(uchar *p) 
{ 
1996/0131/sys/src/9/port/devtinyfs.c:67,861996/0201/sys/src/9/port/devtinyfs.c:94,119
1996/0131    
} 
1996/0123    
 
1996/0131    
static void 
mapclr(FS *fs, int bno) 
1996/0201    
mapclr(Tfs *fs, ulong bno) 
1996/0131    
{ 
	fs->map[bno>>3] &= ~(1<<(bno&7)); 
} 
 
static void 
mapset(FS *fs, int bno) 
1996/0201    
mapset(Tfs *fs, ulong bno) 
1996/0131    
{ 
	fs->map[bno>>3] |= 1<<(bno&7); 
} 
 
static int 
mapalloc(FS *fs) 
1996/0201    
isalloced(Tfs *fs, ulong bno) 
1996/0131    
{ 
1996/0201    
	return fs->map[bno>>3] & (1<<(bno&7)); 
} 
 
static int 
mapalloc(Tfs *fs) 
{ 
1996/0131    
	int i, j, lim; 
	uchar x; 
 
1996/0131/sys/src/9/port/devtinyfs.c:101,1151996/0201/sys/src/9/port/devtinyfs.c:134,242
1996/0131    
	return -1; 
} 
 
1996/0201    
static Mdir* 
validdir(Tfs *fs, uchar *p) 
{ 
	Mdir *md; 
	ulong x; 
 
	if(checksum(p) != 0) 
		return 0; 
	if(buf[0] != Tagdir) 
		return 0; 
	md = (Mdir*)p; 
	x = GETS(md->bno); 
	if(x >= fs->nblocks) 
		return 0; 
	return md; 
} 
 
static Mdata* 
validdata(Tfs *fs, uchar *p) 
{ 
	Mdata *md; 
	ulong x; 
 
	if(checksum(p) != 0) 
		return 0; 
	md = (Mdir*)p; 
	switch(buf[0]){ 
	case Tagdata: 
		x = GETS(md->bno); 
		if(x >= fs->nblocks) 
			return 0; 
		break; 
	case Tagend: 
		x = GETS(md->bno); 
		if(x > Blen - 4) 
			return 0; 
		break; 
	} 
	return md; 
} 
 
static void 
freefile(Tfs *fs, Tfile *f, ulong bend) 
{ 
	uchar buf[Blen]; 
	ulong bno; 
	int n; 
	Mdata *md; 
 
	/* remove blocks from map */ 
	bno = f->dbno; 
	while(bend != bno){ 
		mapclr(fs, bno); 
		n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno); 
		if(n != Blen) 
			break; 
		md = validdata(buf); 
		if(md == 0) 
			break; 
		if(md->type == Tagend) 
			break; 
		bno = GETS(md->bno); 
	} 
 
	/* change file type to free on medium */ 
	n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*f->bno); 
	if(n != Blen) 
		return; 
	buf[0] = Tagfree; 
	devtab[fs->c->type].write(fs->c, buf, Blen, Blen*f->bno); 
 
	/* forget we ever knew about it */ 
	memset(f, 0, sizeof(*f)); 
} 
 
static void 
expand(Tfs *fs) 
{ 
	Tfile *f; 
 
	fs->fsize += 8; 
	f = smalloc(fs->fsize*sizeof(*f)); 
 
	lock(fs); 
	memmove(f, fs->f, fs->nf*sizoef(f)); 
	free(fs->f); 
	fs->f = f; 
	unlock(fs); 
} 
 
1996/0123    
/* 
 *  see if we have a reasonable fat/root directory 
 */ 
static int 
fsinit(FS *fs) 
1996/0201    
static void 
fsinit(Tfs *fs) 
1996/0123    
{ 
1996/0131    
	uchar buf[Blen+DIRLEN]; 
1996/0123    
	Dir d; 
1996/0131    
	ulong x, bno; 
1996/0201    
	int n; 
	Tfile *f; 
	Mdir *mdir; 
	Mdata *mdat; 
1996/0123    
 
	devtab[fs->c->type].stat(fs->c, buf); 
	convM2D(buf, &d); 
1996/0131/sys/src/9/port/devtinyfs.c:119,2091996/0201/sys/src/9/port/devtinyfs.c:246,381
1996/0123    
 
1996/0131    
	/* bitmap for block usage */ 
	x = (fs->nblocks + 8 - 1)/8; 
	fs->map = malloc(x); 
1996/0201    
	fs->map = smalloc(x); 
1996/0131    
	memset(fs->map, 0x0, x); 
	for(bno = fs->nblocks; bno < x*8; bno++) 
		mapset(fs, bno); 
1996/0123    
 
1996/0201    
	/* find files */ 
1996/0131    
	for(bno = 0; bno < fs->nblocks; bno++){ 
		n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno); 
		if(n != Blen) 
			break; 
		if(checksum(buf) != 0) 
1996/0201    
 
		mdir = validdir(buf); 
		if(mdir == 0) 
1996/0131    
			continue; 
		switch(buf[0]){ 
		case Tdir: 
1996/0201    
 
		if(fs->nfs <= fs->fsize) 
			expand(fs); 
		f = &fs->f[fs->nf++]; 
 
		x = GETS(mdir->bno); 
		mapset(fs, bno); 
		strncpy(f->name, mdir->name, sizeof(f->name)); 
		f->pin = GETS(mdir->pin); 
		f->bno = bno; 
		f->dbno = x; 
	} 
 
	/* follow files */ 
	for(f = fs->f; f; f = f->next){ 
		bno = fs->dbno; 
		for(;;) { 
			if(isalloced(fs, bno)){ 
				freefile(f, bno); 
				break; 
			} 
			n = devtab[fs->c->type].read(fs->c, buf, Blen, Blen*bno); 
			if(n != Blen){ 
				freefile(fs, f, bno); 
				break; 
			} 
			mdata = validdata(fs, buf); 
			if(mdata == 0){ 
				freefile(fs, f, bno); 
				break; 
			} 
1996/0131    
			mapset(fs, bno); 
			break; 
1996/0201    
			switch(mdata->type){ 
			case Tagdata: 
				bno = GETS(mdata->bno); 
				f->len += Dlen; 
				break; 
			case Tagend: 
				f->len += GETS(mdata->bno); 
				break; 
			} 
1996/0131    
		} 
	} 
1996/0123    
} 
 
/* 
 *  set up the fat and then a root directory (starting at first cluster (1)) 
 */ 
static void 
fssetup(FS *fs) 
1996/0201    
static int 
tinyfsgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) 
1996/0123    
{ 
	uchar buf[DIRLEN]; 
	Dir d; 
1996/0201    
	Tfs *fs; 
	Tfile *f; 
	Qid qid; 
1996/0123    
 
	devtab[fs->c->type].stat(fs->c, buf); 
	convM2D(buf, &d); 
	fs->clustsize = d.length>>16; 
	if(fs->clustsize < 64) 
		fs->clustsize = 64; 
	fs->nclust = (d.length - 12)/fs->clustsize; 
	fs->fat = smalloc(2*fs->nclust); 
	n = devtab[fs->c->type].write(fs->c, buf, 2*fs->nclust, Superlen); 
	if(n < 2*fs->nclust) 
		error(Eio); 
	n = devtab[fs->c->type].write(fs->c, buf, Superlen, 0); 
	if(n < Superlen) 
		error(Eio); 
1996/0201    
	fs = &tinyfs.fs[c->dev]; 
	if(i >= fs->nf) 
		return -1; 
	f = &fs->f[i]; 
	qid.path = i; 
	qid.vers = 0; 
	devdir(c, qid, f->name, f->length, eve, f->pin==Nopin?0444:0666, dp); 
	return 1; 
1996/0123    
} 
 
1996/0201    
void 
tinyfsreset(void) 
{ 
	if(Nlen > NAMELEN) 
		panic("tinyfsreset"); 
} 
 
void 
tinyfsinit(void) 
{ 
} 
 
1996/0116    
Chan * 
tinyfsattach(char *spec) 
{ 
1996/0122    
	FS *fs, **l; 
1996/0201    
	Tfs *fs; 
1996/0122    
	Chan *c, *cc; 
1996/0201    
	int i; 
1996/0120    
 
1996/0122    
	cc = namec((char*)arg[0], Aopen, arg[1], 0); 
1996/0123    
	if(waserror()){ 
		close(cc); 
		unlock(&fs); 
1996/0201    
		qunlock(&tinyfs); 
1996/0123    
		nexterror(); 
	} 
1996/0201    
 
1996/0122    
	qlock(&tinyfs); 
	l = &tinyfs.l; 
	for(fs = tinyfs.l; fs != 0; fs = fs->next){ 
		if(eqchan(c, fs->c)) 
1996/0201    
	for(i = 0; i < tinyfs.nfs; i++){ 
		fs = &tinyfs.fs[i]; 
		if(fs && eqchan(c, fs->c)) 
1996/0122    
			break; 
		l = &(fs->next); 
	} 
	if(fs){ 
		incref(&fs->r); 
		qunlock(&tinyfs); 
1996/0201    
	if(i < tinyfs.nfs){ 
		lock(fs); 
		fs->r++; 
		unlock(fs); 
1996/0122    
		close(cc); 
	} else { 
		fs = smalloc(sizeof(*fs)); 
1996/0201    
		if(tinyfs.nfs >= Maxfs) 
			error("too many tinyfs's"); 
		fs = &tinyfs.fs[tinyfs.nfs]; 
		memset(fs, 0, sizeof(*fs)); 
1996/0122    
		fs->c = cc; 
		incref(&fs->r); 
1996/0123    
		if(waserror()){ 
			free(fs); 
			nexterror(); 
		} 
		if(fsinit(fs) < 0) 
			fssetup(fs); 
		poperror(); 
		*l = fs; 
1996/0122    
		qunlock(&tinyfs); 
1996/0201    
		fs->r = 1; 
		fsinit(fs); 
		tinyfs.nfs++; 
1996/0122    
	} 
1996/0201    
	qunlock(&tinyfs); 
1996/0123    
	poperror(); 
1996/0122    
 
	c = devattach('E', spec); 
	c->aux = fs; 
	c->dev = fs->dev; 
1996/0201    
	c = devattach('U', spec); 
	c->dev = fs - tinyfs.fs; 
	c->qid.path = CHDIR; 
	c->qid.vers = 0; 
1996/0122    
 
	return c; 
1996/0116    
} 
1996/0131/sys/src/9/port/devtinyfs.c:217,2521996/0201/sys/src/9/port/devtinyfs.c:389,462
1996/0116    
int 
tinyfswalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, tinyfs.file, tinyfs.nfile, devgen); 
1996/0201    
	return devwalk(c, name, 0, 0, tinyfsgen); 
1996/0116    
} 
 
void 
tinyfsstat(Chan *c, char *db) 
{ 
	devstat(c, db, tinyfs.file, tinyfs.nfile, devgen); 
1996/0201    
	devstat(c, db, 0, 0, tinyfsgen); 
1996/0116    
} 
 
Chan * 
tinyfsopen(Chan *c, int omode) 
{ 
	return devopen(c, omode, tinyfs.file, tinyfs.nfile, devgen); 
1996/0201    
	Tfs *fs; 
	Tfile *f; 
 
	fs = &tinyfs.fs[c->dev]; 
 
	if(c->path & CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
	} else { 
		lock(fs); 
		f = fs->f[c->path]; 
		unlock(fs); 
 
		if(f->pin == Nopin){ 
			if(omode != OREAD) 
				error(Eperm); 
		} else { 
			if(omode != ORDWR) 
				error(Eperm); 
		} 
	} 
 
	return devopen(c, omode, 0, 0, tinyfsgen); 
1996/0116    
} 
 
void 
tinyfscreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Dirtab	*d; 
1996/0201    
	Tfs *fs; 
	Tfile *f; 
1996/0116    
 
	if(perm & CHDIR) 
		error("directory creation illegal"); 
 
	if(waserror()){ 
		qunlock(&tinyfs); 
		nexterror(); 
1996/0201    
	fs = &tinyfs.fs[c->dev]; 
	for(;;) { 
		lock(fs); 
		for(i = 0; i < fs->fsize; i++){ 
			f = &fs->f[i]; 
			if(f->name[0] == 0){ 
				strncpy(f->name, name, sizeof(f->name)-1); 
				break; 
			} 
		} 
		if(i < fs->fsize) 
			break; 
 
		unlock(fs); 
		expand(fs); 
1996/0116    
	} 
1996/0201    
	unlock(fs); 
 
	c->qid.path = f - fs->f; 
	c->qid.vers = 1;		/* creating */ 
1996/0116    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->qid = d->qid; 
} 
 
void 
1996/0131/sys/src/9/port/devtinyfs.c:266,2711996/0201/sys/src/9/port/devtinyfs.c:476,512
1996/0116    
void 
tinyfsclose(Chan *c) 
{ 
1996/0201    
	Tfs *fs, **l; 
	Tfile *f, *nf; 
 
	fs = c->aux; 
	lock(fs); 
	fs->ref--; 
	unlock(fs); 
 
	if(fs->ref) 
		return; 
 
	qlock(&tinyfs); 
	lock(fs); 
	if(fs->ref == 0){ 
		for(l = &fs->l; *l;){ 
			if(*l == fs){ 
				*l = fs->next; 
				break; 
			} 
			l = &(*l)->next; 
		} 
		for(f = fs->f; f; f = nf){ 
			nf = f->next; 
			free(f); 
		} 
		free(fs->map); 
		close(fs->c); 
		free(fs); 
	} 
	unlock(fs); 
	qunlock(&tinyfs); 
1996/0116    
} 
 
long 
1996/0131/sys/src/9/port/devtinyfs.c:273,2791996/0201/sys/src/9/port/devtinyfs.c:514,520
1996/0116    
{ 
	switch(c->qid.path & ~CHDIR){ 
	case Qdir: 
		return devdirread(c, a, n, tinyfstab, Ntinyfstab, devgen); 
1996/0201    
		return devdirread(c, a, n, tinyfstab, Ntinyfstab, tinyfsgen); 
1996/0116    
	case Qdata: 
		break; 
	default: 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)