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

1997/0327/port/devroot.c (diff list | history)

1997/0327/sys/src/9/port/devroot.c:1,2491997/0408/sys/src/9/port/devroot.c:1,252 (short | long | prev | next)
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
1993/0724    
enum{ 
	Qdir=	0, 
1990/0227    
	Qbin, 
	Qdev, 
	Qenv, 
	Qproc, 
1992/0213    
	Qnet, 
1995/1114    
	Qnetalt, 
1993/0501    
	Qrecover, 
1993/0724    
	Qboot,		/* readable files */ 
1991/1206    
 
1993/0724    
	Nfiles=13,	/* max root files */	 
1990/0227    
}; 
 
1991/1206    
extern ulong	bootlen; 
1992/0902    
extern uchar	bootcode[]; 
1991/0214    
 
1993/0724    
Dirtab rootdir[Nfiles]={ 
	"bin",		{Qbin|CHDIR},	0,	0777, 
	"dev",		{Qdev|CHDIR},	0,	0777, 
	"env",		{Qenv|CHDIR},	0,	0777, 
	"proc",		{Qproc|CHDIR},	0,	0777, 
	"net",		{Qnet|CHDIR},	0,	0777, 
1995/1114    
	"net.alt",	{Qnetalt|CHDIR},	0,	0777, 
1993/0724    
	"recover",	{Qrecover},	0,	0777, 
1990/0227    
}; 
 
1993/0724    
static uchar	*rootdata[Nfiles]; 
static int	nroot = Qboot - 1; 
1993/1031    
static int	recovbusy; 
1993/0724    
 
1993/0501    
typedef struct Recover Recover; 
struct Recover 
{ 
	int	len; 
	char	*req; 
	Recover	*next; 
}; 
 
struct  
{ 
	Lock; 
	QLock; 
	Rendez; 
	Recover	*q; 
}reclist; 
 
1993/0724    
/* 
 *  add a root file 
 */ 
void 
addrootfile(char *name, uchar *contents, ulong len) 
1991/0615    
{ 
1993/0724    
	Dirtab *d; 
	 
1992/0711    
 
1993/0724    
	if(nroot >= Nfiles) 
		panic("too many root files"); 
	rootdata[nroot] = contents; 
	d = &rootdir[nroot]; 
	strcpy(d->name, name); 
	d->length = len; 
	d->perm = 0555; 
	d->qid.path = nroot+1; 
	nroot++; 
1991/0615    
} 
 
1997/0327    
static void 
1990/0227    
rootreset(void) 
{ 
1993/0724    
	addrootfile("boot", bootcode, bootlen);	/* always have a boot file */ 
1990/0227    
} 
 
1997/0327    
static Chan* 
1990/0227    
rootattach(char *spec) 
{ 
	return devattach('/', spec); 
} 
 
1997/0327    
static int	  
1990/0227    
rootwalk(Chan *c, char *name) 
{ 
1991/1206    
	if(strcmp(name, "..") == 0) { 
		c->qid.path = Qdir|CHDIR; 
		return 1; 
	} 
1992/0225    
	if((c->qid.path & ~CHDIR) != Qdir) 
1992/0226    
		return 0; 
1993/0724    
	return devwalk(c, name, rootdir, nroot, devgen); 
1990/0227    
} 
 
1997/0327    
static void	  
1990/0227    
rootstat(Chan *c, char *dp) 
{ 
1993/0724    
	devstat(c, dp, rootdir, nroot, devgen); 
1990/0227    
} 
 
1997/0327    
static Chan* 
1990/0227    
rootopen(Chan *c, int omode) 
{ 
1993/0501    
	switch(c->qid.path & ~CHDIR) { 
	default: 
		break; 
	case Qrecover: 
1993/1031    
		if(recovbusy) 
			error(Einuse);		 
1993/0501    
		if(strcmp(up->user, eve) != 0) 
			error(Eperm); 
1993/1031    
		recovbusy = 1; 
1993/0501    
		break; 
	} 
 
1993/0724    
	return devopen(c, omode, rootdir, nroot, devgen); 
1990/0227    
} 
 
/* 
 * sysremove() knows this is a nop 
 */ 
1997/0327    
static void	  
1990/0227    
rootclose(Chan *c) 
{ 
1993/1031    
	switch(c->qid.path) { 
	default: 
		break; 
	case Qrecover: 
		if(c->flag&COPEN) 
			recovbusy = 0; 
		break; 
	} 
1990/0227    
} 
 
1997/0327    
static int 
1995/0804    
rdrdy(void*) 
1993/0501    
{ 
	return reclist.q != 0; 
} 
 
1997/0327    
static long	  
1991/0411    
rootread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1993/0724    
	ulong t; 
	Dirtab *d; 
	uchar *data; 
1993/0501    
	Recover *r; 
1990/0227    
 
1993/0724    
	t = c->qid.path & ~CHDIR; 
	switch(t){ 
1990/0227    
	case Qdir: 
1993/0724    
		return devdirread(c, buf, n, rootdir, nroot, devgen); 
1993/0501    
	case Qrecover: 
		qlock(&reclist); 
		if(waserror()) { 
			qunlock(&reclist); 
			nexterror(); 
		} 
 
		sleep(&reclist, rdrdy, 0); 
 
		lock(&reclist); 
		r = reclist.q; 
		reclist.q = r->next; 
		unlock(&reclist); 
 
		qunlock(&reclist); 
 
		poperror(); 
		if(n < r->len) 
			n = r->len; 
		memmove(buf, r->req, n); 
		free(r->req); 
		free(r); 
		return n; 
1993/0724    
	} 
1993/0501    
 
1993/0724    
	if(t < Qboot) 
1990/0227    
		return 0; 
1993/0724    
 
	d = &rootdir[t-1]; 
	data = rootdata[t-1]; 
	if(offset >= d->length) 
		return 0; 
	if(offset+n > d->length) 
		n = d->length - offset; 
	memmove(buf, data+offset, n); 
	return n; 
1990/0227    
} 
 
1997/0327    
static long	  
1995/0804    
rootwrite(Chan *c, void *buf, long n, ulong) 
1990/0227    
{ 
1993/0501    
	char tmp[256]; 
 
	switch(c->qid.path & ~CHDIR){ 
	default: 
		error(Egreg); 
	case Qrecover: 
		if(n > sizeof(tmp)-1) 
			error(Etoosmall); 
		/* Nul terminate */ 
		memmove(tmp, buf, n); 
		tmp[n] = '\0'; 
		mntrepl(tmp); 
		return n; 
	} 
	return 0; 
1995/0108    
} 
 
1997/0327    
Dev rootdevtab = { 
1997/0408    
	'/', 
	"root", 
 
1997/0327    
	rootreset, 
	devinit, 
	rootattach, 
	devclone, 
	rootwalk, 
	rootstat, 
	rootopen, 
	devcreate, 
	rootclose, 
	rootread, 
	devbread, 
	rootwrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 
1993/0501    
 
void 
rootrecover(Path *p, char *mntname) 
{ 
	int i; 
	Recover *r; 
	char buf[256]; 
 
	r = malloc(sizeof(Recover)); 
	i = ptpath(p, buf, sizeof(buf)); 
	r->req = smalloc(i+strlen(mntname)+2); 
	sprint(r->req, "%s %s", buf, mntname); 
	lock(&reclist); 
	r->next = reclist.q; 
	reclist.q = r; 
	unlock(&reclist); 
	wakeup(&reclist); 
1990/0227    
} 


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