xref: /inferno-os/emu/port/dev.c (revision 45a14cc6b60b02e58eb1b271508ccc2fa3c52b8f)
137da2899SCharles.Forsyth #include	"dat.h"
237da2899SCharles.Forsyth #include	"fns.h"
337da2899SCharles.Forsyth #include	"error.h"
437da2899SCharles.Forsyth 
537da2899SCharles.Forsyth extern ulong	kerndate;
637da2899SCharles.Forsyth 
737da2899SCharles.Forsyth void
mkqid(Qid * q,vlong path,ulong vers,int type)837da2899SCharles.Forsyth mkqid(Qid *q, vlong path, ulong vers, int type)
937da2899SCharles.Forsyth {
1037da2899SCharles.Forsyth 	q->type = type;
1137da2899SCharles.Forsyth 	q->vers = vers;
1237da2899SCharles.Forsyth 	q->path = path;
1337da2899SCharles.Forsyth }
1437da2899SCharles.Forsyth 
1537da2899SCharles.Forsyth int
devno(int c,int user)1637da2899SCharles.Forsyth devno(int c, int user)
1737da2899SCharles.Forsyth {
1837da2899SCharles.Forsyth 	int i;
1937da2899SCharles.Forsyth 
2037da2899SCharles.Forsyth 	for(i = 0; devtab[i] != nil; i++) {
2137da2899SCharles.Forsyth 		if(devtab[i]->dc == c)
2237da2899SCharles.Forsyth 			return i;
2337da2899SCharles.Forsyth 	}
2437da2899SCharles.Forsyth 	if(user == 0)
2537da2899SCharles.Forsyth 		panic("devno %C 0x%ux", c, c);
2637da2899SCharles.Forsyth 
2737da2899SCharles.Forsyth 	return -1;
2837da2899SCharles.Forsyth }
2937da2899SCharles.Forsyth 
3037da2899SCharles.Forsyth void
devdir(Chan * c,Qid qid,char * n,long length,char * user,long perm,Dir * db)3137da2899SCharles.Forsyth devdir(Chan *c, Qid qid, char *n, long length, char *user, long perm, Dir *db)
3237da2899SCharles.Forsyth {
3337da2899SCharles.Forsyth 	db->name = n;
3437da2899SCharles.Forsyth 	if(c->flag&CMSG)
3537da2899SCharles.Forsyth 		qid.type |= QTMOUNT;
3637da2899SCharles.Forsyth 	db->qid = qid;
3737da2899SCharles.Forsyth 	db->type = devtab[c->type]->dc;
3837da2899SCharles.Forsyth 	db->dev = c->dev;
3937da2899SCharles.Forsyth 	db->mode = perm | (qid.type << 24);
4037da2899SCharles.Forsyth 	db->atime = time(0);
4137da2899SCharles.Forsyth 	db->mtime = kerndate;
4237da2899SCharles.Forsyth 	db->length = length;
4337da2899SCharles.Forsyth 	db->uid = user;
4437da2899SCharles.Forsyth 	db->gid = eve;
4537da2899SCharles.Forsyth 	db->muid = user;
4637da2899SCharles.Forsyth }
4737da2899SCharles.Forsyth 
4837da2899SCharles.Forsyth /*
4937da2899SCharles.Forsyth  * the zeroth element of the table MUST be the directory itself for ..
5037da2899SCharles.Forsyth  */
5137da2899SCharles.Forsyth int
devgen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)5237da2899SCharles.Forsyth devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
5337da2899SCharles.Forsyth {
5437da2899SCharles.Forsyth 	USED(name);
5537da2899SCharles.Forsyth 	if(tab == 0)
5637da2899SCharles.Forsyth 		return -1;
5737da2899SCharles.Forsyth 	if(i != DEVDOTDOT){
5837da2899SCharles.Forsyth 		/* skip over the first element, that for . itself */
5937da2899SCharles.Forsyth 		i++;
6037da2899SCharles.Forsyth 		if(i >= ntab)
6137da2899SCharles.Forsyth 			return -1;
6237da2899SCharles.Forsyth 		tab += i;
6337da2899SCharles.Forsyth 	}
6437da2899SCharles.Forsyth 	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
6537da2899SCharles.Forsyth 	return 1;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth 
6837da2899SCharles.Forsyth void
devinit(void)6937da2899SCharles.Forsyth devinit(void)
7037da2899SCharles.Forsyth {
7137da2899SCharles.Forsyth }
7237da2899SCharles.Forsyth 
7337da2899SCharles.Forsyth void
devshutdown(void)7437da2899SCharles.Forsyth devshutdown(void)
7537da2899SCharles.Forsyth {
7637da2899SCharles.Forsyth }
7737da2899SCharles.Forsyth 
7837da2899SCharles.Forsyth Chan*
devattach(int tc,char * spec)7937da2899SCharles.Forsyth devattach(int tc, char *spec)
8037da2899SCharles.Forsyth {
8137da2899SCharles.Forsyth 	Chan *c;
8237da2899SCharles.Forsyth 	char *buf;
8337da2899SCharles.Forsyth 
8437da2899SCharles.Forsyth 	c = newchan();
8537da2899SCharles.Forsyth 	mkqid(&c->qid, 0, 0, QTDIR);
8637da2899SCharles.Forsyth 	c->type = devno(tc, 0);
8737da2899SCharles.Forsyth 	if(spec == nil)
8837da2899SCharles.Forsyth 		spec = "";
8937da2899SCharles.Forsyth 	buf = smalloc(4+strlen(spec)+1);
9037da2899SCharles.Forsyth 	sprint(buf, "#%C%s", tc, spec);
9137da2899SCharles.Forsyth 	c->name = newcname(buf);
9237da2899SCharles.Forsyth 	free(buf);
9337da2899SCharles.Forsyth 	return c;
9437da2899SCharles.Forsyth }
9537da2899SCharles.Forsyth 
9637da2899SCharles.Forsyth Chan*
devclone(Chan * c)9737da2899SCharles.Forsyth devclone(Chan *c)
9837da2899SCharles.Forsyth {
9937da2899SCharles.Forsyth 	Chan *nc;
10037da2899SCharles.Forsyth 
10137da2899SCharles.Forsyth 	if(c->flag & COPEN)
10237da2899SCharles.Forsyth 		panic("clone of open file type %C\n", devtab[c->type]->dc);
10337da2899SCharles.Forsyth 
10437da2899SCharles.Forsyth 	nc = newchan();
10537da2899SCharles.Forsyth 	nc->type = c->type;
10637da2899SCharles.Forsyth 	nc->dev = c->dev;
10737da2899SCharles.Forsyth 	nc->mode = c->mode;
10837da2899SCharles.Forsyth 	nc->qid = c->qid;
10937da2899SCharles.Forsyth 	nc->offset = c->offset;
11037da2899SCharles.Forsyth 	nc->umh = nil;
11137da2899SCharles.Forsyth 	nc->mountid = c->mountid;
11237da2899SCharles.Forsyth 	nc->aux = c->aux;
11337da2899SCharles.Forsyth 	nc->mqid = c->mqid;
11437da2899SCharles.Forsyth 	nc->mcp = c->mcp;
11537da2899SCharles.Forsyth 	return nc;
11637da2899SCharles.Forsyth }
11737da2899SCharles.Forsyth 
11837da2899SCharles.Forsyth Walkqid*
devwalk(Chan * c,Chan * nc,char ** name,int nname,Dirtab * tab,int ntab,Devgen * gen)11937da2899SCharles.Forsyth devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
12037da2899SCharles.Forsyth {
121*45a14cc6SCharles.Forsyth 	int i, j;
122*45a14cc6SCharles.Forsyth 	volatile int alloc;
12337da2899SCharles.Forsyth 	Walkqid *wq;
12437da2899SCharles.Forsyth 	char *n;
12537da2899SCharles.Forsyth 	Dir dir;
12637da2899SCharles.Forsyth 
12737da2899SCharles.Forsyth 	if(nname > 0)
12837da2899SCharles.Forsyth 		isdir(c);
12937da2899SCharles.Forsyth 
13037da2899SCharles.Forsyth 	alloc = 0;
13137da2899SCharles.Forsyth 	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
13237da2899SCharles.Forsyth 	if(waserror()){
13337da2899SCharles.Forsyth 		if(alloc && wq->clone!=nil)
13437da2899SCharles.Forsyth 			cclose(wq->clone);
13537da2899SCharles.Forsyth 		free(wq);
13637da2899SCharles.Forsyth 		return nil;
13737da2899SCharles.Forsyth 	}
13837da2899SCharles.Forsyth 	if(nc == nil){
13937da2899SCharles.Forsyth 		nc = devclone(c);
14037da2899SCharles.Forsyth 		nc->type = 0;	/* device doesn't know about this channel yet */
14137da2899SCharles.Forsyth 		alloc = 1;
14237da2899SCharles.Forsyth 	}
14337da2899SCharles.Forsyth 	wq->clone = nc;
14437da2899SCharles.Forsyth 
14537da2899SCharles.Forsyth 	for(j=0; j<nname; j++){
14637da2899SCharles.Forsyth 		if(!(nc->qid.type&QTDIR)){
14737da2899SCharles.Forsyth 			if(j==0)
14837da2899SCharles.Forsyth 				error(Enotdir);
14937da2899SCharles.Forsyth 			goto Done;
15037da2899SCharles.Forsyth 		}
15137da2899SCharles.Forsyth 		n = name[j];
15237da2899SCharles.Forsyth 		if(strcmp(n, ".") == 0){
15337da2899SCharles.Forsyth     Accept:
15437da2899SCharles.Forsyth 			wq->qid[wq->nqid++] = nc->qid;
15537da2899SCharles.Forsyth 			continue;
15637da2899SCharles.Forsyth 		}
15737da2899SCharles.Forsyth 		if(strcmp(n, "..") == 0){
15837da2899SCharles.Forsyth 			(*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir);
15937da2899SCharles.Forsyth 			nc->qid = dir.qid;
16037da2899SCharles.Forsyth 			goto Accept;
16137da2899SCharles.Forsyth 		}
16237da2899SCharles.Forsyth 		/*
16337da2899SCharles.Forsyth 		 * Ugly problem: If we're using devgen, make sure we're
16437da2899SCharles.Forsyth 		 * walking the directory itself, represented by the first
16537da2899SCharles.Forsyth 		 * entry in the table, and not trying to step into a sub-
16637da2899SCharles.Forsyth 		 * directory of the table, e.g. /net/net. Devgen itself
16737da2899SCharles.Forsyth 		 * should take care of the problem, but it doesn't have
16837da2899SCharles.Forsyth 		 * the necessary information (that we're doing a walk).
16937da2899SCharles.Forsyth 		 */
17037da2899SCharles.Forsyth 		if(gen==devgen && nc->qid.path!=tab[0].qid.path)
17137da2899SCharles.Forsyth 			goto Notfound;
17237da2899SCharles.Forsyth 		for(i=0;; i++) {
17337da2899SCharles.Forsyth 			switch((*gen)(nc, n, tab, ntab, i, &dir)){
17437da2899SCharles.Forsyth 			case -1:
17537da2899SCharles.Forsyth 			Notfound:
17637da2899SCharles.Forsyth 				if(j == 0)
17737da2899SCharles.Forsyth 					error(Enonexist);
17837da2899SCharles.Forsyth 				kstrcpy(up->env->errstr, Enonexist, ERRMAX);
17937da2899SCharles.Forsyth 				goto Done;
18037da2899SCharles.Forsyth 			case 0:
18137da2899SCharles.Forsyth 				continue;
18237da2899SCharles.Forsyth 			case 1:
18337da2899SCharles.Forsyth 				if(strcmp(n, dir.name) == 0){
18437da2899SCharles.Forsyth 					nc->qid = dir.qid;
18537da2899SCharles.Forsyth 					goto Accept;
18637da2899SCharles.Forsyth 				}
18737da2899SCharles.Forsyth 				continue;
18837da2899SCharles.Forsyth 			}
18937da2899SCharles.Forsyth 		}
19037da2899SCharles.Forsyth 	}
19137da2899SCharles.Forsyth 	/*
19237da2899SCharles.Forsyth 	 * We processed at least one name, so will return some data.
19337da2899SCharles.Forsyth 	 * If we didn't process all nname entries succesfully, we drop
19437da2899SCharles.Forsyth 	 * the cloned channel and return just the Qids of the walks.
19537da2899SCharles.Forsyth 	 */
19637da2899SCharles.Forsyth Done:
19737da2899SCharles.Forsyth 	poperror();
19837da2899SCharles.Forsyth 	if(wq->nqid < nname){
19937da2899SCharles.Forsyth 		if(alloc)
20037da2899SCharles.Forsyth 			cclose(wq->clone);
20137da2899SCharles.Forsyth 		wq->clone = nil;
20237da2899SCharles.Forsyth 	}else if(wq->clone){
20337da2899SCharles.Forsyth 		/* attach cloned channel to same device */
20437da2899SCharles.Forsyth 		wq->clone->type = c->type;
20537da2899SCharles.Forsyth 	}
20637da2899SCharles.Forsyth 	return wq;
20737da2899SCharles.Forsyth }
20837da2899SCharles.Forsyth 
20937da2899SCharles.Forsyth int
devstat(Chan * c,uchar * db,int n,Dirtab * tab,int ntab,Devgen * gen)21037da2899SCharles.Forsyth devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
21137da2899SCharles.Forsyth {
21237da2899SCharles.Forsyth 	int i;
21337da2899SCharles.Forsyth 	Dir dir;
21437da2899SCharles.Forsyth 	char *p, *elem;
21537da2899SCharles.Forsyth 
21637da2899SCharles.Forsyth 	for(i=0;; i++)
21737da2899SCharles.Forsyth 		switch((*gen)(c, nil, tab, ntab, i, &dir)){
21837da2899SCharles.Forsyth 		case -1:
21937da2899SCharles.Forsyth 			if(c->qid.type & QTDIR){
22037da2899SCharles.Forsyth 				if(c->name == nil)
22137da2899SCharles.Forsyth 					elem = "???";
22237da2899SCharles.Forsyth 				else if(strcmp(c->name->s, "/") == 0)
22337da2899SCharles.Forsyth 					elem = "/";
22437da2899SCharles.Forsyth 				else
22537da2899SCharles.Forsyth 					for(elem=p=c->name->s; *p; p++)
22637da2899SCharles.Forsyth 						if(*p == '/')
22737da2899SCharles.Forsyth 							elem = p+1;
22837da2899SCharles.Forsyth 				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
22937da2899SCharles.Forsyth 				n = convD2M(&dir, db, n);
23037da2899SCharles.Forsyth 				if(n == 0)
23137da2899SCharles.Forsyth 					error(Ebadarg);
23237da2899SCharles.Forsyth 				return n;
23337da2899SCharles.Forsyth 			}
23437da2899SCharles.Forsyth 			print("%s %s: devstat %C %llux\n",
23537da2899SCharles.Forsyth 				up->text, up->env->user,
23637da2899SCharles.Forsyth 				devtab[c->type]->dc, c->qid.path);
23737da2899SCharles.Forsyth 
23837da2899SCharles.Forsyth 			error(Enonexist);
23937da2899SCharles.Forsyth 		case 0:
24037da2899SCharles.Forsyth 			break;
24137da2899SCharles.Forsyth 		case 1:
24237da2899SCharles.Forsyth 			if(c->qid.path == dir.qid.path) {
24337da2899SCharles.Forsyth 				if(c->flag&CMSG)
24437da2899SCharles.Forsyth 					dir.mode |= DMMOUNT;
24537da2899SCharles.Forsyth 				n = convD2M(&dir, db, n);
24637da2899SCharles.Forsyth 				if(n == 0)
24737da2899SCharles.Forsyth 					error(Ebadarg);
24837da2899SCharles.Forsyth 				return n;
24937da2899SCharles.Forsyth 			}
25037da2899SCharles.Forsyth 			break;
25137da2899SCharles.Forsyth 		}
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth 
25437da2899SCharles.Forsyth long
devdirread(Chan * c,char * d,long n,Dirtab * tab,int ntab,Devgen * gen)25537da2899SCharles.Forsyth devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
25637da2899SCharles.Forsyth {
25737da2899SCharles.Forsyth 	long m, dsz;
25837da2899SCharles.Forsyth 	struct{
25937da2899SCharles.Forsyth 		Dir d;
26037da2899SCharles.Forsyth 		char slop[100];	/* TO DO */
26137da2899SCharles.Forsyth 	}dir;
26237da2899SCharles.Forsyth 
26337da2899SCharles.Forsyth 	for(m=0; m<n; c->dri++) {
26437da2899SCharles.Forsyth 		switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){
26537da2899SCharles.Forsyth 		case -1:
26637da2899SCharles.Forsyth 			return m;
26737da2899SCharles.Forsyth 
26837da2899SCharles.Forsyth 		case 0:
26937da2899SCharles.Forsyth 			break;
27037da2899SCharles.Forsyth 
27137da2899SCharles.Forsyth 		case 1:
27237da2899SCharles.Forsyth 			dsz = convD2M(&dir.d, (uchar*)d, n-m);
27337da2899SCharles.Forsyth 			if(dsz <= BIT16SZ){	/* <= not < because this isn't stat; read is stuck */
27437da2899SCharles.Forsyth 				if(m == 0)
27537da2899SCharles.Forsyth 					error(Eshort);
27637da2899SCharles.Forsyth 				return m;
27737da2899SCharles.Forsyth 			}
27837da2899SCharles.Forsyth 			m += dsz;
27937da2899SCharles.Forsyth 			d += dsz;
28037da2899SCharles.Forsyth 			break;
28137da2899SCharles.Forsyth 		}
28237da2899SCharles.Forsyth 	}
28337da2899SCharles.Forsyth 
28437da2899SCharles.Forsyth 	return m;
28537da2899SCharles.Forsyth }
28637da2899SCharles.Forsyth 
28737da2899SCharles.Forsyth /*
28837da2899SCharles.Forsyth  * error(Eperm) if open permission not granted for up->env->user.
28937da2899SCharles.Forsyth  */
29037da2899SCharles.Forsyth void
devpermcheck(char * fileuid,ulong perm,int omode)29137da2899SCharles.Forsyth devpermcheck(char *fileuid, ulong perm, int omode)
29237da2899SCharles.Forsyth {
29337da2899SCharles.Forsyth 	ulong t;
29437da2899SCharles.Forsyth 	static int access[] = { 0400, 0200, 0600, 0100 };
29537da2899SCharles.Forsyth 
29637da2899SCharles.Forsyth 	if(strcmp(up->env->user, fileuid) == 0)
29737da2899SCharles.Forsyth 		perm <<= 0;
29837da2899SCharles.Forsyth 	else
29937da2899SCharles.Forsyth 	if(strcmp(up->env->user, eve) == 0)
30037da2899SCharles.Forsyth 		perm <<= 3;
30137da2899SCharles.Forsyth 	else
30237da2899SCharles.Forsyth 		perm <<= 6;
30337da2899SCharles.Forsyth 
30437da2899SCharles.Forsyth 	t = access[omode&3];
30537da2899SCharles.Forsyth 	if((t&perm) != t)
30637da2899SCharles.Forsyth 		error(Eperm);
30737da2899SCharles.Forsyth }
30837da2899SCharles.Forsyth 
30937da2899SCharles.Forsyth Chan*
devopen(Chan * c,int omode,Dirtab * tab,int ntab,Devgen * gen)31037da2899SCharles.Forsyth devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
31137da2899SCharles.Forsyth {
31237da2899SCharles.Forsyth 	int i;
31337da2899SCharles.Forsyth 	Dir dir;
31437da2899SCharles.Forsyth 
31537da2899SCharles.Forsyth 	for(i=0;; i++) {
31637da2899SCharles.Forsyth 		switch((*gen)(c, nil, tab, ntab, i, &dir)){
31737da2899SCharles.Forsyth 		case -1:
31837da2899SCharles.Forsyth 			goto Return;
31937da2899SCharles.Forsyth 		case 0:
32037da2899SCharles.Forsyth 			break;
32137da2899SCharles.Forsyth 		case 1:
32237da2899SCharles.Forsyth 			if(c->qid.path == dir.qid.path) {
32337da2899SCharles.Forsyth 				devpermcheck(dir.uid, dir.mode, omode);
32437da2899SCharles.Forsyth 				goto Return;
32537da2899SCharles.Forsyth 			}
32637da2899SCharles.Forsyth 			break;
32737da2899SCharles.Forsyth 		}
32837da2899SCharles.Forsyth 	}
32937da2899SCharles.Forsyth Return:
33037da2899SCharles.Forsyth 	c->offset = 0;
33137da2899SCharles.Forsyth 	if((c->qid.type&QTDIR) && omode!=OREAD)
33237da2899SCharles.Forsyth 		error(Eperm);
33337da2899SCharles.Forsyth 	c->mode = openmode(omode);
33437da2899SCharles.Forsyth 	c->flag |= COPEN;
33537da2899SCharles.Forsyth 	return c;
33637da2899SCharles.Forsyth }
33737da2899SCharles.Forsyth 
33837da2899SCharles.Forsyth Block*
devbread(Chan * c,long n,ulong offset)33937da2899SCharles.Forsyth devbread(Chan *c, long n, ulong offset)
34037da2899SCharles.Forsyth {
34137da2899SCharles.Forsyth 	Block *bp;
34237da2899SCharles.Forsyth 
34337da2899SCharles.Forsyth 	bp = allocb(n);
34437da2899SCharles.Forsyth 	if(waserror()) {
34537da2899SCharles.Forsyth 		freeb(bp);
34637da2899SCharles.Forsyth 		nexterror();
34737da2899SCharles.Forsyth 	}
34837da2899SCharles.Forsyth 	bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
34937da2899SCharles.Forsyth 	poperror();
35037da2899SCharles.Forsyth 	return bp;
35137da2899SCharles.Forsyth }
35237da2899SCharles.Forsyth 
35337da2899SCharles.Forsyth long
devbwrite(Chan * c,Block * bp,ulong offset)35437da2899SCharles.Forsyth devbwrite(Chan *c, Block *bp, ulong offset)
35537da2899SCharles.Forsyth {
35637da2899SCharles.Forsyth 	long n;
35737da2899SCharles.Forsyth 
35837da2899SCharles.Forsyth 	if(waserror()) {
35937da2899SCharles.Forsyth 		freeb(bp);
36037da2899SCharles.Forsyth 		nexterror();
36137da2899SCharles.Forsyth 	}
36237da2899SCharles.Forsyth 	n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
36337da2899SCharles.Forsyth 	poperror();
36437da2899SCharles.Forsyth 	freeb(bp);
36537da2899SCharles.Forsyth 
36637da2899SCharles.Forsyth 	return n;
36737da2899SCharles.Forsyth }
36837da2899SCharles.Forsyth 
36937da2899SCharles.Forsyth void
devcreate(Chan * c,char * name,int mode,ulong perm)37037da2899SCharles.Forsyth devcreate(Chan *c, char *name, int mode, ulong perm)
37137da2899SCharles.Forsyth {
37237da2899SCharles.Forsyth 	USED(c);
37337da2899SCharles.Forsyth 	USED(name);
37437da2899SCharles.Forsyth 	USED(mode);
37537da2899SCharles.Forsyth 	USED(perm);
37637da2899SCharles.Forsyth 	error(Eperm);
37737da2899SCharles.Forsyth }
37837da2899SCharles.Forsyth 
37937da2899SCharles.Forsyth void
devremove(Chan * c)38037da2899SCharles.Forsyth devremove(Chan *c)
38137da2899SCharles.Forsyth {
38237da2899SCharles.Forsyth 	USED(c);
38337da2899SCharles.Forsyth 	error(Eperm);
38437da2899SCharles.Forsyth }
38537da2899SCharles.Forsyth 
38637da2899SCharles.Forsyth int
devwstat(Chan * c,uchar * dp,int n)38737da2899SCharles.Forsyth devwstat(Chan *c, uchar *dp, int n)
38837da2899SCharles.Forsyth {
38937da2899SCharles.Forsyth 	USED(c);
39037da2899SCharles.Forsyth 	USED(dp);
39137da2899SCharles.Forsyth 	USED(n);
39237da2899SCharles.Forsyth 	error(Eperm);
39337da2899SCharles.Forsyth 	return 0;
39437da2899SCharles.Forsyth }
39537da2899SCharles.Forsyth 
39637da2899SCharles.Forsyth int
readstr(ulong off,char * buf,ulong n,char * str)39737da2899SCharles.Forsyth readstr(ulong off, char *buf, ulong n, char *str)
39837da2899SCharles.Forsyth {
39937da2899SCharles.Forsyth 	int size;
40037da2899SCharles.Forsyth 
40137da2899SCharles.Forsyth 	size = strlen(str);
40237da2899SCharles.Forsyth 	if(off >= size)
40337da2899SCharles.Forsyth 		return 0;
40437da2899SCharles.Forsyth 	if(off+n > size)
40537da2899SCharles.Forsyth 		n = size-off;
40637da2899SCharles.Forsyth 	memmove(buf, str+off, n);
40737da2899SCharles.Forsyth 	return n;
40837da2899SCharles.Forsyth }
40937da2899SCharles.Forsyth 
41037da2899SCharles.Forsyth int
readnum(ulong off,char * buf,ulong n,ulong val,int size)41137da2899SCharles.Forsyth readnum(ulong off, char *buf, ulong n, ulong val, int size)
41237da2899SCharles.Forsyth {
41337da2899SCharles.Forsyth 	char tmp[64];
41437da2899SCharles.Forsyth 
41537da2899SCharles.Forsyth 	if(size > 64) size = 64;
41637da2899SCharles.Forsyth 
41737da2899SCharles.Forsyth 	snprint(tmp, sizeof(tmp), "%*.0lud ", size, val);
41837da2899SCharles.Forsyth 	if(off >= size)
41937da2899SCharles.Forsyth 		return 0;
42037da2899SCharles.Forsyth 	if(off+n > size)
42137da2899SCharles.Forsyth 		n = size-off;
42237da2899SCharles.Forsyth 	memmove(buf, tmp+off, n);
42337da2899SCharles.Forsyth 	return n;
42437da2899SCharles.Forsyth }
42537da2899SCharles.Forsyth 
42637da2899SCharles.Forsyth /*
42737da2899SCharles.Forsyth  * check that the name in a wstat is plausible
42837da2899SCharles.Forsyth  */
42937da2899SCharles.Forsyth void
validwstatname(char * name)43037da2899SCharles.Forsyth validwstatname(char *name)
43137da2899SCharles.Forsyth {
43237da2899SCharles.Forsyth 	validname(name, 0);
43337da2899SCharles.Forsyth 	if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
43437da2899SCharles.Forsyth 		error(Efilename);
43537da2899SCharles.Forsyth }
43637da2899SCharles.Forsyth 
43737da2899SCharles.Forsyth Dev*
devbyname(char * name)43837da2899SCharles.Forsyth devbyname(char *name)
43937da2899SCharles.Forsyth {
44037da2899SCharles.Forsyth 	int i;
44137da2899SCharles.Forsyth 
44237da2899SCharles.Forsyth 	for(i = 0; devtab[i] != nil; i++)
44337da2899SCharles.Forsyth 		if(strcmp(devtab[i]->name, name) == 0)
44437da2899SCharles.Forsyth 			return devtab[i];
44537da2899SCharles.Forsyth 	return nil;
44637da2899SCharles.Forsyth }
447