xref: /plan9/sys/src/9/port/dev.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier #define	DEVTAB
83e12c5d1SDavid du Colombier #include	"devtab.h"
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier extern ulong	kerndate;
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier int
133e12c5d1SDavid du Colombier devno(int c, int user)
143e12c5d1SDavid du Colombier {
15bd389b36SDavid du Colombier 	Rune *s;
16bd389b36SDavid du Colombier 	int i;
173e12c5d1SDavid du Colombier 
18bd389b36SDavid du Colombier 	s = devchar;
19bd389b36SDavid du Colombier 	i = 0;
20bd389b36SDavid du Colombier 	while(*s){
21bd389b36SDavid du Colombier 		if(c == *s)
22bd389b36SDavid du Colombier 			return i;
23bd389b36SDavid du Colombier 		i++;
24bd389b36SDavid du Colombier 		s++;
25bd389b36SDavid du Colombier 	}
26bd389b36SDavid du Colombier 
273e12c5d1SDavid du Colombier 	if(user)
283e12c5d1SDavid du Colombier 		return -1;
29bd389b36SDavid du Colombier 	panic("devno %C 0x%ux", c, c);
30bd389b36SDavid du Colombier 	return 0;
313e12c5d1SDavid du Colombier }
323e12c5d1SDavid du Colombier 
333e12c5d1SDavid du Colombier void
343e12c5d1SDavid du Colombier devdir(Chan *c, Qid qid, char *n, long length, char *user, long perm, Dir *db)
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier 	strcpy(db->name, n);
373e12c5d1SDavid du Colombier 	db->qid = qid;
383e12c5d1SDavid du Colombier 	db->type = devchar[c->type];
393e12c5d1SDavid du Colombier 	db->dev = c->dev;
403e12c5d1SDavid du Colombier 	if(qid.path & CHDIR)
413e12c5d1SDavid du Colombier 		db->mode = CHDIR|perm;
423e12c5d1SDavid du Colombier 	else
433e12c5d1SDavid du Colombier 		db->mode = perm;
44*219b2ee8SDavid du Colombier 	if(c->flag&CMSG)
45*219b2ee8SDavid du Colombier 		db->mode |= CHMOUNT;
463e12c5d1SDavid du Colombier 	db->atime = seconds();
473e12c5d1SDavid du Colombier 	db->mtime = kerndate;
483e12c5d1SDavid du Colombier 	db->hlength = 0;
493e12c5d1SDavid du Colombier 	db->length = length;
50*219b2ee8SDavid du Colombier 	memmove(db->uid, user, NAMELEN);
51*219b2ee8SDavid du Colombier 	memmove(db->gid, eve, NAMELEN);
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier int
553e12c5d1SDavid du Colombier devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
563e12c5d1SDavid du Colombier {
573e12c5d1SDavid du Colombier 	if(tab==0 || i>=ntab)
583e12c5d1SDavid du Colombier 		return -1;
593e12c5d1SDavid du Colombier 	tab += i;
603e12c5d1SDavid du Colombier 	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
613e12c5d1SDavid du Colombier 	return 1;
623e12c5d1SDavid du Colombier }
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier Chan *
653e12c5d1SDavid du Colombier devattach(int tc, char *spec)
663e12c5d1SDavid du Colombier {
673e12c5d1SDavid du Colombier 	Chan *c;
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier 	USED(spec);
703e12c5d1SDavid du Colombier 	c = newchan();
713e12c5d1SDavid du Colombier 	c->qid = (Qid){CHDIR, 0};
723e12c5d1SDavid du Colombier 	c->type = devno(tc, 0);
733e12c5d1SDavid du Colombier 	return c;
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier Chan *
773e12c5d1SDavid du Colombier devclone(Chan *c, Chan *nc)
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	if(c->flag & COPEN)
80bd389b36SDavid du Colombier 		panic("clone of open file type %C\n", devchar[c->type]);
813e12c5d1SDavid du Colombier 	if(nc == 0)
823e12c5d1SDavid du Colombier 		nc = newchan();
833e12c5d1SDavid du Colombier 	nc->type = c->type;
843e12c5d1SDavid du Colombier 	nc->dev = c->dev;
853e12c5d1SDavid du Colombier 	nc->mode = c->mode;
863e12c5d1SDavid du Colombier 	nc->qid = c->qid;
873e12c5d1SDavid du Colombier 	nc->offset = c->offset;
883e12c5d1SDavid du Colombier 	nc->flag = c->flag;
893e12c5d1SDavid du Colombier 	nc->mnt = c->mnt;
903e12c5d1SDavid du Colombier 	nc->mountid = c->mountid;
913e12c5d1SDavid du Colombier 	nc->aux = c->aux;
923e12c5d1SDavid du Colombier 	nc->mchan = c->mchan;
933e12c5d1SDavid du Colombier 	nc->mqid = c->mqid;
943e12c5d1SDavid du Colombier 	return nc;
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier int
983e12c5d1SDavid du Colombier devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
993e12c5d1SDavid du Colombier {
1003e12c5d1SDavid du Colombier 	long i;
1013e12c5d1SDavid du Colombier 	Dir dir;
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier 	isdir(c);
1043e12c5d1SDavid du Colombier 	if(name[0]=='.' && name[1]==0)
1053e12c5d1SDavid du Colombier 		return 1;
1063e12c5d1SDavid du Colombier 	for(i=0;; i++)
1073e12c5d1SDavid du Colombier 		switch((*gen)(c, tab, ntab, i, &dir)){
1083e12c5d1SDavid du Colombier 		case -1:
1093e12c5d1SDavid du Colombier 			strncpy(u->error, Enonexist, NAMELEN);
1103e12c5d1SDavid du Colombier 			return 0;
1113e12c5d1SDavid du Colombier 		case 0:
1123e12c5d1SDavid du Colombier 			continue;
1133e12c5d1SDavid du Colombier 		case 1:
1143e12c5d1SDavid du Colombier 			if(strcmp(name, dir.name) == 0){
1153e12c5d1SDavid du Colombier 				c->qid = dir.qid;
1163e12c5d1SDavid du Colombier 				return 1;
1173e12c5d1SDavid du Colombier 			}
1183e12c5d1SDavid du Colombier 			continue;
1193e12c5d1SDavid du Colombier 		}
1203e12c5d1SDavid du Colombier 	return 1;	/* not reached */
1213e12c5d1SDavid du Colombier }
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier void
1243e12c5d1SDavid du Colombier devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen)
1253e12c5d1SDavid du Colombier {
1263e12c5d1SDavid du Colombier 	int i;
1273e12c5d1SDavid du Colombier 	Dir dir;
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier 	for(i=0;; i++)
1303e12c5d1SDavid du Colombier 		switch((*gen)(c, tab, ntab, i, &dir)){
1313e12c5d1SDavid du Colombier 		case -1:
1323e12c5d1SDavid du Colombier 			/*
1333e12c5d1SDavid du Colombier 			 *  given a channel, we cannot derive the directory name
1343e12c5d1SDavid du Colombier 			 *  that the channel was generated from since it was lost
1353e12c5d1SDavid du Colombier 			 *  by namec.
1363e12c5d1SDavid du Colombier 			 */
1373e12c5d1SDavid du Colombier 			if(c->qid.path & CHDIR){
138*219b2ee8SDavid du Colombier 				devdir(c, c->qid, ".", 0L, eve, CHDIR|0775, &dir);
1393e12c5d1SDavid du Colombier 				convD2M(&dir, db);
1403e12c5d1SDavid du Colombier 				return;
1413e12c5d1SDavid du Colombier 			}
142bd389b36SDavid du Colombier 			print("%s %s: devstat %C %lux\n", u->p->text, u->p->user,
1433e12c5d1SDavid du Colombier 							devchar[c->type], c->qid.path);
1443e12c5d1SDavid du Colombier 			error(Enonexist);
1453e12c5d1SDavid du Colombier 		case 0:
1463e12c5d1SDavid du Colombier 			break;
1473e12c5d1SDavid du Colombier 		case 1:
1483e12c5d1SDavid du Colombier 			if(eqqid(c->qid, dir.qid)){
149*219b2ee8SDavid du Colombier 				if(c->flag&CMSG)
150*219b2ee8SDavid du Colombier 					dir.mode |= CHMOUNT;
1513e12c5d1SDavid du Colombier 				convD2M(&dir, db);
1523e12c5d1SDavid du Colombier 				return;
1533e12c5d1SDavid du Colombier 			}
1543e12c5d1SDavid du Colombier 			break;
1553e12c5d1SDavid du Colombier 		}
1563e12c5d1SDavid du Colombier }
1573e12c5d1SDavid du Colombier 
1583e12c5d1SDavid du Colombier long
1593e12c5d1SDavid du Colombier devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
1603e12c5d1SDavid du Colombier {
1613e12c5d1SDavid du Colombier 	long k, m;
1623e12c5d1SDavid du Colombier 	Dir dir;
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 	k = c->offset/DIRLEN;
1653e12c5d1SDavid du Colombier 	for(m=0; m<n; k++)
1663e12c5d1SDavid du Colombier 		switch((*gen)(c, tab, ntab, k, &dir)){
1673e12c5d1SDavid du Colombier 		case -1:
1683e12c5d1SDavid du Colombier 			return m;
1693e12c5d1SDavid du Colombier 
1703e12c5d1SDavid du Colombier 		case 0:
1713e12c5d1SDavid du Colombier 			c->offset += DIRLEN;
1723e12c5d1SDavid du Colombier 			break;
1733e12c5d1SDavid du Colombier 
1743e12c5d1SDavid du Colombier 		case 1:
1753e12c5d1SDavid du Colombier 			convD2M(&dir, d);
1763e12c5d1SDavid du Colombier 			m += DIRLEN;
1773e12c5d1SDavid du Colombier 			d += DIRLEN;
1783e12c5d1SDavid du Colombier 			break;
1793e12c5d1SDavid du Colombier 		}
1803e12c5d1SDavid du Colombier 	return m;
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier Chan *
1843e12c5d1SDavid du Colombier devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier 	int i;
1873e12c5d1SDavid du Colombier 	Dir dir;
1883e12c5d1SDavid du Colombier 	ulong t, mode;
1893e12c5d1SDavid du Colombier 	static int access[] = { 0400, 0200, 0600, 0100 };
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 	for(i=0;; i++)
1923e12c5d1SDavid du Colombier 		switch((*gen)(c, tab, ntab, i, &dir)){
1933e12c5d1SDavid du Colombier 		case -1:
1943e12c5d1SDavid du Colombier 			goto Return;
1953e12c5d1SDavid du Colombier 		case 0:
1963e12c5d1SDavid du Colombier 			break;
1973e12c5d1SDavid du Colombier 		case 1:
1983e12c5d1SDavid du Colombier 			if(eqqid(c->qid, dir.qid)) {
1993e12c5d1SDavid du Colombier 				if(strcmp(u->p->user, dir.uid) == 0)	/* User */
2003e12c5d1SDavid du Colombier 					mode = dir.mode;
2013e12c5d1SDavid du Colombier 				else if(strcmp(u->p->user, eve) == 0)	/* eve is group */
2023e12c5d1SDavid du Colombier 					mode = dir.mode<<3;
2033e12c5d1SDavid du Colombier 				else
2043e12c5d1SDavid du Colombier 					mode = dir.mode<<6;		/* Other */
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier 				t = access[omode&3];
2073e12c5d1SDavid du Colombier 				if((t & mode) == t)
2083e12c5d1SDavid du Colombier 					goto Return;
2093e12c5d1SDavid du Colombier 				error(Eperm);
2103e12c5d1SDavid du Colombier 			}
2113e12c5d1SDavid du Colombier 			break;
2123e12c5d1SDavid du Colombier 		}
2133e12c5d1SDavid du Colombier     Return:
2143e12c5d1SDavid du Colombier 	c->offset = 0;
2153e12c5d1SDavid du Colombier 	if((c->qid.path&CHDIR) && omode!=OREAD)
2163e12c5d1SDavid du Colombier 		error(Eperm);
2173e12c5d1SDavid du Colombier 	c->mode = openmode(omode);
2183e12c5d1SDavid du Colombier 	c->flag |= COPEN;
2193e12c5d1SDavid du Colombier 	return c;
2203e12c5d1SDavid du Colombier }
221