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

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

port/devtinyfs.c on 1996/0116
1996/0116    
/* 
 *  template for making a new device 
 */ 
 
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
 
#include	"devtab.h" 
 
enum{ 
	Qdir, 
1996/0120    
	Qmedium, 
1996/0123    
 
1996/0131    
	Blen=	48, 
 
	Tdir=	0, 
	Tdata, 
	Tend, 
1996/0116    
}; 
 
1996/0122    
typedef struct FS FS; 
struct FS { 
1996/0116    
	QLock; 
1996/0122    
	Ref	r; 
	int	dev; 
	FS	*next; 
1996/0116    
	Chan	*c; 
1996/0131    
	uchar	*map; 
	int	nblocks; 
1996/0122    
}; 
 
struct { 
	QLock; 
	FS	*l; 
	int	hidev; 
1996/0116    
} tinyfs; 
 
1996/0131    
#define GETS(x) ((x)[0]|((x)[1]<<8)) 
#define PUTS(x, v) {(x)[0] = (v);(x)[1] = ((v)>>8);} 
 
#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) 
{ 
	uchar *e; 
	uchar s; 
1996/0123    
 
1996/0131    
	s = 0; 
	for(e = p + Blen; p < e; p++) 
		s += *p; 
} 
1996/0123    
 
1996/0131    
static void 
mapclr(FS *fs, int bno) 
{ 
	fs->map[bno>>3] &= ~(1<<(bno&7)); 
} 
 
static void 
mapset(FS *fs, int bno) 
{ 
	fs->map[bno>>3] |= 1<<(bno&7); 
} 
 
static int 
mapalloc(FS *fs) 
{ 
	int i, j, lim; 
	uchar x; 
 
	qlock(fs); 
	lim = (fs->nblocks + 8 - 1)/8; 
	for(i = 0; i < lim; i++){ 
		x = fs->map[i]; 
		if(x == 0xff) 
			continue; 
		for(j = 0; j < 8; j++) 
			if((x & (1<<j)) == 0){ 
				fs->map[i] = x|(1<<j); 
				qunlock(fs); 
				return i*8 + j; 
			} 
	} 
	qunlock(fs); 
	return -1; 
} 
 
1996/0123    
/* 
 *  see if we have a reasonable fat/root directory 
 */ 
static int 
fsinit(FS *fs) 
{ 
1996/0131    
	uchar buf[Blen+DIRLEN]; 
1996/0123    
	Dir d; 
1996/0131    
	ulong x, bno; 
1996/0123    
 
	devtab[fs->c->type].stat(fs->c, buf); 
	convM2D(buf, &d); 
1996/0131    
	fs->nblocks = d.length/Blen; 
	if(fs->nblocks < 3) 
1996/0123    
		error("tinyfs medium too small"); 
 
1996/0131    
	/* bitmap for block usage */ 
	x = (fs->nblocks + 8 - 1)/8; 
	fs->map = malloc(x); 
	memset(fs->map, 0x0, x); 
	for(bno = fs->nblocks; bno < x*8; bno++) 
		mapset(fs, bno); 
1996/0123    
 
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) 
			continue; 
		switch(buf[0]){ 
		case Tdir: 
			mapset(fs, bno); 
			break; 
		} 
	} 
1996/0123    
} 
 
/* 
 *  set up the fat and then a root directory (starting at first cluster (1)) 
 */ 
static void 
fssetup(FS *fs) 
{ 
	uchar buf[DIRLEN]; 
	Dir d; 
 
	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/0116    
Chan * 
tinyfsattach(char *spec) 
{ 
1996/0122    
	FS *fs, **l; 
	Chan *c, *cc; 
1996/0120    
 
1996/0122    
	cc = namec((char*)arg[0], Aopen, arg[1], 0); 
1996/0123    
	if(waserror()){ 
		close(cc); 
		unlock(&fs); 
		nexterror(); 
	} 
1996/0122    
	qlock(&tinyfs); 
	l = &tinyfs.l; 
	for(fs = tinyfs.l; fs != 0; fs = fs->next){ 
		if(eqchan(c, fs->c)) 
			break; 
		l = &(fs->next); 
	} 
	if(fs){ 
		incref(&fs->r); 
		qunlock(&tinyfs); 
		close(cc); 
	} else { 
		fs = smalloc(sizeof(*fs)); 
		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/0123    
	poperror(); 
1996/0122    
 
	c = devattach('E', spec); 
	c->aux = fs; 
	c->dev = fs->dev; 
 
	return c; 
1996/0116    
} 
 
Chan * 
tinyfsclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
tinyfswalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, tinyfs.file, tinyfs.nfile, devgen); 
} 
 
void 
tinyfsstat(Chan *c, char *db) 
{ 
	devstat(c, db, tinyfs.file, tinyfs.nfile, devgen); 
} 
 
Chan * 
tinyfsopen(Chan *c, int omode) 
{ 
	return devopen(c, omode, tinyfs.file, tinyfs.nfile, devgen); 
} 
 
void 
tinyfscreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Dirtab	*d; 
 
	if(perm & CHDIR) 
		error("directory creation illegal"); 
 
	if(waserror()){ 
		qunlock(&tinyfs); 
		nexterror(); 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->qid = d->qid; 
} 
 
void 
tinyfsremove(Chan *c) 
{ 
	USED(c); 
	error(Eperm); 
} 
 
void 
tinyfswstat(Chan *c, char *dp) 
{ 
	USED(c, dp); 
	error(Eperm); 
} 
 
void 
tinyfsclose(Chan *c) 
{ 
} 
 
long 
tinyfsread(Chan *c, void *a, long n, ulong offset) 
{ 
	switch(c->qid.path & ~CHDIR){ 
	case Qdir: 
		return devdirread(c, a, n, tinyfstab, Ntinyfstab, devgen); 
	case Qdata: 
		break; 
	default: 
		n=0; 
		break; 
	} 
	return n; 
} 
 
Block* 
tinyfsbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
long 
tinyfswrite(Chan *c, char *a, long n, ulong offset) 
{ 
	if(waserror()){ 
		qunlock(&tinyfs); 
		nexterror(); 
	} 
	qlock(&tinyfs); 
	qunlock(&tinyfs); 
 
	switch(c->qid.path & ~CHDIR){ 
	case Qdata: 
		break; 
	default: 
		error(Ebadusefd); 
	} 
	return n; 
} 
 
long 
tinyfsbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
} 


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