xref: /plan9-contrib/sys/src/9k/port/dev.c (revision 9ef1f84b659abcb917c5c090acbce0772e494f21)
1*9ef1f84bSDavid du Colombier #include	"u.h"
2*9ef1f84bSDavid du Colombier #include	"../port/lib.h"
3*9ef1f84bSDavid du Colombier #include	"mem.h"
4*9ef1f84bSDavid du Colombier #include	"dat.h"
5*9ef1f84bSDavid du Colombier #include	"fns.h"
6*9ef1f84bSDavid du Colombier #include	"../port/error.h"
7*9ef1f84bSDavid du Colombier 
8*9ef1f84bSDavid du Colombier extern ulong	kerndate;
9*9ef1f84bSDavid du Colombier 
10*9ef1f84bSDavid du Colombier void
mkqid(Qid * q,vlong path,ulong vers,int type)11*9ef1f84bSDavid du Colombier mkqid(Qid *q, vlong path, ulong vers, int type)
12*9ef1f84bSDavid du Colombier {
13*9ef1f84bSDavid du Colombier 	q->type = type;
14*9ef1f84bSDavid du Colombier 	q->vers = vers;
15*9ef1f84bSDavid du Colombier 	q->path = path;
16*9ef1f84bSDavid du Colombier }
17*9ef1f84bSDavid du Colombier 
18*9ef1f84bSDavid du Colombier void
devdir(Chan * c,Qid qid,char * n,vlong length,char * user,long perm,Dir * db)19*9ef1f84bSDavid du Colombier devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
20*9ef1f84bSDavid du Colombier {
21*9ef1f84bSDavid du Colombier 	db->name = n;
22*9ef1f84bSDavid du Colombier 	if(c->flag&CMSG)
23*9ef1f84bSDavid du Colombier 		qid.type |= QTMOUNT;
24*9ef1f84bSDavid du Colombier 	db->qid = qid;
25*9ef1f84bSDavid du Colombier 	/*
26*9ef1f84bSDavid du Colombier 	 * When called via devwalk c->dev is nil
27*9ef1f84bSDavid du Colombier 	 * until the walk succeeds.
28*9ef1f84bSDavid du Colombier 	 */
29*9ef1f84bSDavid du Colombier 	if(c->dev != nil)
30*9ef1f84bSDavid du Colombier 		db->type = c->dev->dc;
31*9ef1f84bSDavid du Colombier 	else
32*9ef1f84bSDavid du Colombier 		db->type = -1;
33*9ef1f84bSDavid du Colombier 	db->dev = c->devno;
34*9ef1f84bSDavid du Colombier 	db->mode = perm;
35*9ef1f84bSDavid du Colombier 	db->mode |= qid.type << 24;
36*9ef1f84bSDavid du Colombier 	db->atime = seconds();
37*9ef1f84bSDavid du Colombier 	db->mtime = kerndate;
38*9ef1f84bSDavid du Colombier 	db->length = length;
39*9ef1f84bSDavid du Colombier 	db->uid = user;
40*9ef1f84bSDavid du Colombier 	db->gid = eve;
41*9ef1f84bSDavid du Colombier 	db->muid = user;
42*9ef1f84bSDavid du Colombier }
43*9ef1f84bSDavid du Colombier 
44*9ef1f84bSDavid du Colombier /*
45*9ef1f84bSDavid du Colombier  * (here, Devgen is the prototype; devgen is the function in dev.c.)
46*9ef1f84bSDavid du Colombier  *
47*9ef1f84bSDavid du Colombier  * a Devgen is expected to return the directory entry for ".."
48*9ef1f84bSDavid du Colombier  * if you pass it s==DEVDOTDOT (-1).  otherwise...
49*9ef1f84bSDavid du Colombier  *
50*9ef1f84bSDavid du Colombier  * there are two contradictory rules.
51*9ef1f84bSDavid du Colombier  *
52*9ef1f84bSDavid du Colombier  * (i) if c is a directory, a Devgen is expected to list its children
53*9ef1f84bSDavid du Colombier  * as you iterate s.
54*9ef1f84bSDavid du Colombier  *
55*9ef1f84bSDavid du Colombier  * (ii) whether or not c is a directory, a Devgen is expected to list
56*9ef1f84bSDavid du Colombier  * its siblings as you iterate s.
57*9ef1f84bSDavid du Colombier  *
58*9ef1f84bSDavid du Colombier  * devgen always returns the list of children in the root
59*9ef1f84bSDavid du Colombier  * directory.  thus it follows (i) when c is the root and (ii) otherwise.
60*9ef1f84bSDavid du Colombier  * many other Devgens follow (i) when c is a directory and (ii) otherwise.
61*9ef1f84bSDavid du Colombier  *
62*9ef1f84bSDavid du Colombier  * devwalk assumes (i).  it knows that devgen breaks (i)
63*9ef1f84bSDavid du Colombier  * for children that are themselves directories, and explicitly catches them.
64*9ef1f84bSDavid du Colombier  *
65*9ef1f84bSDavid du Colombier  * devstat assumes (ii).  if the Devgen in question follows (i)
66*9ef1f84bSDavid du Colombier  * for this particular c, devstat will not find the necessary info.
67*9ef1f84bSDavid du Colombier  * with our particular Devgen functions, this happens only for
68*9ef1f84bSDavid du Colombier  * directories, so devstat makes something up, assuming
69*9ef1f84bSDavid du Colombier  * c->name, c->qid, eve, DMDIR|0555.
70*9ef1f84bSDavid du Colombier  *
71*9ef1f84bSDavid du Colombier  * devdirread assumes (i).  the callers have to make sure
72*9ef1f84bSDavid du Colombier  * that the Devgen satisfies (i) for the chan being read.
73*9ef1f84bSDavid du Colombier  */
74*9ef1f84bSDavid du Colombier /*
75*9ef1f84bSDavid du Colombier  * the zeroth element of the table MUST be the directory itself for ..
76*9ef1f84bSDavid du Colombier */
77*9ef1f84bSDavid du Colombier int
devgen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)78*9ef1f84bSDavid du Colombier devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
79*9ef1f84bSDavid du Colombier {
80*9ef1f84bSDavid du Colombier 	if(tab == 0)
81*9ef1f84bSDavid du Colombier 		return -1;
82*9ef1f84bSDavid du Colombier 	if(i == DEVDOTDOT){
83*9ef1f84bSDavid du Colombier 		/* nothing */
84*9ef1f84bSDavid du Colombier 	}else if(name){
85*9ef1f84bSDavid du Colombier 		for(i=1; i<ntab; i++)
86*9ef1f84bSDavid du Colombier 			if(strcmp(tab[i].name, name) == 0)
87*9ef1f84bSDavid du Colombier 				break;
88*9ef1f84bSDavid du Colombier 		if(i==ntab)
89*9ef1f84bSDavid du Colombier 			return -1;
90*9ef1f84bSDavid du Colombier 		tab += i;
91*9ef1f84bSDavid du Colombier 	}else{
92*9ef1f84bSDavid du Colombier 		/* skip over the first element, that for . itself */
93*9ef1f84bSDavid du Colombier 		i++;
94*9ef1f84bSDavid du Colombier 		if(i >= ntab)
95*9ef1f84bSDavid du Colombier 			return -1;
96*9ef1f84bSDavid du Colombier 		tab += i;
97*9ef1f84bSDavid du Colombier 	}
98*9ef1f84bSDavid du Colombier 	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
99*9ef1f84bSDavid du Colombier 	return 1;
100*9ef1f84bSDavid du Colombier }
101*9ef1f84bSDavid du Colombier 
102*9ef1f84bSDavid du Colombier void
devreset(void)103*9ef1f84bSDavid du Colombier devreset(void)
104*9ef1f84bSDavid du Colombier {
105*9ef1f84bSDavid du Colombier }
106*9ef1f84bSDavid du Colombier 
107*9ef1f84bSDavid du Colombier void
devinit(void)108*9ef1f84bSDavid du Colombier devinit(void)
109*9ef1f84bSDavid du Colombier {
110*9ef1f84bSDavid du Colombier }
111*9ef1f84bSDavid du Colombier 
112*9ef1f84bSDavid du Colombier void
devshutdown(void)113*9ef1f84bSDavid du Colombier devshutdown(void)
114*9ef1f84bSDavid du Colombier {
115*9ef1f84bSDavid du Colombier }
116*9ef1f84bSDavid du Colombier 
117*9ef1f84bSDavid du Colombier Chan*
devattach(int dc,char * spec)118*9ef1f84bSDavid du Colombier devattach(int dc, char *spec)
119*9ef1f84bSDavid du Colombier {
120*9ef1f84bSDavid du Colombier 	Chan *c;
121*9ef1f84bSDavid du Colombier 	char *buf;
122*9ef1f84bSDavid du Colombier 
123*9ef1f84bSDavid du Colombier 	/*
124*9ef1f84bSDavid du Colombier 	 * There are no error checks here because
125*9ef1f84bSDavid du Colombier 	 * this can only be called from the driver of dc
126*9ef1f84bSDavid du Colombier 	 * which pretty much guarantees devtabget will
127*9ef1f84bSDavid du Colombier 	 * succeed.
128*9ef1f84bSDavid du Colombier 	 */
129*9ef1f84bSDavid du Colombier 	c = newchan();
130*9ef1f84bSDavid du Colombier 	mkqid(&c->qid, 0, 0, QTDIR);
131*9ef1f84bSDavid du Colombier 	c->dev = devtabget(dc, 0);
132*9ef1f84bSDavid du Colombier 	if(spec == nil)
133*9ef1f84bSDavid du Colombier 		spec = "";
134*9ef1f84bSDavid du Colombier 	buf = smalloc(4+strlen(spec)+1);
135*9ef1f84bSDavid du Colombier 	sprint(buf, "#%C%s", dc, spec);
136*9ef1f84bSDavid du Colombier 	c->path = newpath(buf);
137*9ef1f84bSDavid du Colombier 	free(buf);
138*9ef1f84bSDavid du Colombier 	return c;
139*9ef1f84bSDavid du Colombier }
140*9ef1f84bSDavid du Colombier 
141*9ef1f84bSDavid du Colombier 
142*9ef1f84bSDavid du Colombier Chan*
devclone(Chan * c)143*9ef1f84bSDavid du Colombier devclone(Chan *c)
144*9ef1f84bSDavid du Colombier {
145*9ef1f84bSDavid du Colombier 	Chan *nc;
146*9ef1f84bSDavid du Colombier 
147*9ef1f84bSDavid du Colombier 	if(c->flag & COPEN){
148*9ef1f84bSDavid du Colombier 		panic("devclone: file of type %C already open\n",
149*9ef1f84bSDavid du Colombier 			c->dev != nil? c->dev->dc: -1);
150*9ef1f84bSDavid du Colombier 	}
151*9ef1f84bSDavid du Colombier 
152*9ef1f84bSDavid du Colombier 	nc = newchan();
153*9ef1f84bSDavid du Colombier 
154*9ef1f84bSDavid du Colombier 	/*
155*9ef1f84bSDavid du Colombier 	 * The caller fills dev in if and when necessary.
156*9ef1f84bSDavid du Colombier 	nc->dev = nil;					//XDYNXX
157*9ef1f84bSDavid du Colombier 	 */
158*9ef1f84bSDavid du Colombier 	nc->devno = c->devno;
159*9ef1f84bSDavid du Colombier 	nc->mode = c->mode;
160*9ef1f84bSDavid du Colombier 	nc->qid = c->qid;
161*9ef1f84bSDavid du Colombier 	nc->offset = c->offset;
162*9ef1f84bSDavid du Colombier 	nc->umh = nil;
163*9ef1f84bSDavid du Colombier 	nc->aux = c->aux;
164*9ef1f84bSDavid du Colombier 	nc->mqid = c->mqid;
165*9ef1f84bSDavid du Colombier 	nc->mc = c->mc;
166*9ef1f84bSDavid du Colombier 	return nc;
167*9ef1f84bSDavid du Colombier }
168*9ef1f84bSDavid du Colombier 
169*9ef1f84bSDavid du Colombier Walkqid*
devwalk(Chan * c,Chan * nc,char ** name,int nname,Dirtab * tab,int ntab,Devgen * gen)170*9ef1f84bSDavid du Colombier devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
171*9ef1f84bSDavid du Colombier {
172*9ef1f84bSDavid du Colombier 	int i, j, alloc;
173*9ef1f84bSDavid du Colombier 	Walkqid *wq;
174*9ef1f84bSDavid du Colombier 	char *n;
175*9ef1f84bSDavid du Colombier 	Dir dir;
176*9ef1f84bSDavid du Colombier 
177*9ef1f84bSDavid du Colombier 	if(nname > 0)
178*9ef1f84bSDavid du Colombier 		isdir(c);
179*9ef1f84bSDavid du Colombier 
180*9ef1f84bSDavid du Colombier 	alloc = 0;
181*9ef1f84bSDavid du Colombier 	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
182*9ef1f84bSDavid du Colombier 	if(waserror()){
183*9ef1f84bSDavid du Colombier 		if(alloc && wq->clone!=nil)
184*9ef1f84bSDavid du Colombier 			cclose(wq->clone);
185*9ef1f84bSDavid du Colombier 		free(wq);
186*9ef1f84bSDavid du Colombier 		return nil;
187*9ef1f84bSDavid du Colombier 	}
188*9ef1f84bSDavid du Colombier 	if(nc == nil){
189*9ef1f84bSDavid du Colombier 		nc = devclone(c);
190*9ef1f84bSDavid du Colombier 		/*
191*9ef1f84bSDavid du Colombier 		 * nc->dev remains nil for now.		//XDYNX
192*9ef1f84bSDavid du Colombier 		 */
193*9ef1f84bSDavid du Colombier 		alloc = 1;
194*9ef1f84bSDavid du Colombier 	}
195*9ef1f84bSDavid du Colombier 	wq->clone = nc;
196*9ef1f84bSDavid du Colombier 
197*9ef1f84bSDavid du Colombier 	for(j=0; j<nname; j++){
198*9ef1f84bSDavid du Colombier 		if(!(nc->qid.type & QTDIR)){
199*9ef1f84bSDavid du Colombier 			if(j==0)
200*9ef1f84bSDavid du Colombier 				error(Enotdir);
201*9ef1f84bSDavid du Colombier 			goto Done;
202*9ef1f84bSDavid du Colombier 		}
203*9ef1f84bSDavid du Colombier 		n = name[j];
204*9ef1f84bSDavid du Colombier 		if(strcmp(n, ".") == 0){
205*9ef1f84bSDavid du Colombier     Accept:
206*9ef1f84bSDavid du Colombier 			wq->qid[wq->nqid++] = nc->qid;
207*9ef1f84bSDavid du Colombier 			continue;
208*9ef1f84bSDavid du Colombier 		}
209*9ef1f84bSDavid du Colombier 		if(strcmp(n, "..") == 0){
210*9ef1f84bSDavid du Colombier 			/*
211*9ef1f84bSDavid du Colombier 			 * Use c->dev->name in the error because
212*9ef1f84bSDavid du Colombier 			 * nc->dev should be nil here.
213*9ef1f84bSDavid du Colombier 			 */
214*9ef1f84bSDavid du Colombier 			if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){
215*9ef1f84bSDavid du Colombier 				print("devgen walk .. in dev%s %#llux broken\n",
216*9ef1f84bSDavid du Colombier 					c->dev->name, nc->qid.path);
217*9ef1f84bSDavid du Colombier 				error("broken devgen");
218*9ef1f84bSDavid du Colombier 			}
219*9ef1f84bSDavid du Colombier 			nc->qid = dir.qid;
220*9ef1f84bSDavid du Colombier 			goto Accept;
221*9ef1f84bSDavid du Colombier 		}
222*9ef1f84bSDavid du Colombier 		/*
223*9ef1f84bSDavid du Colombier 		 * Ugly problem: If we're using devgen, make sure we're
224*9ef1f84bSDavid du Colombier 		 * walking the directory itself, represented by the first
225*9ef1f84bSDavid du Colombier 		 * entry in the table, and not trying to step into a sub-
226*9ef1f84bSDavid du Colombier 		 * directory of the table, e.g. /net/net. Devgen itself
227*9ef1f84bSDavid du Colombier 		 * should take care of the problem, but it doesn't have
228*9ef1f84bSDavid du Colombier 		 * the necessary information (that we're doing a walk).
229*9ef1f84bSDavid du Colombier 		 */
230*9ef1f84bSDavid du Colombier 		if(gen==devgen && nc->qid.path!=tab[0].qid.path)
231*9ef1f84bSDavid du Colombier 			goto Notfound;
232*9ef1f84bSDavid du Colombier 		for(i=0;; i++) {
233*9ef1f84bSDavid du Colombier 			switch((*gen)(nc, n, tab, ntab, i, &dir)){
234*9ef1f84bSDavid du Colombier 			case -1:
235*9ef1f84bSDavid du Colombier 			Notfound:
236*9ef1f84bSDavid du Colombier 				if(j == 0)
237*9ef1f84bSDavid du Colombier 					error(Enonexist);
238*9ef1f84bSDavid du Colombier 				kstrcpy(up->errstr, Enonexist, ERRMAX);
239*9ef1f84bSDavid du Colombier 				goto Done;
240*9ef1f84bSDavid du Colombier 			case 0:
241*9ef1f84bSDavid du Colombier 				continue;
242*9ef1f84bSDavid du Colombier 			case 1:
243*9ef1f84bSDavid du Colombier 				if(strcmp(n, dir.name) == 0){
244*9ef1f84bSDavid du Colombier 					nc->qid = dir.qid;
245*9ef1f84bSDavid du Colombier 					goto Accept;
246*9ef1f84bSDavid du Colombier 				}
247*9ef1f84bSDavid du Colombier 				continue;
248*9ef1f84bSDavid du Colombier 			}
249*9ef1f84bSDavid du Colombier 		}
250*9ef1f84bSDavid du Colombier 	}
251*9ef1f84bSDavid du Colombier 	/*
252*9ef1f84bSDavid du Colombier 	 * We processed at least one name, so will return some data.
253*9ef1f84bSDavid du Colombier 	 * If we didn't process all nname entries succesfully, we drop
254*9ef1f84bSDavid du Colombier 	 * the cloned channel and return just the Qids of the walks.
255*9ef1f84bSDavid du Colombier 	 */
256*9ef1f84bSDavid du Colombier Done:
257*9ef1f84bSDavid du Colombier 	poperror();
258*9ef1f84bSDavid du Colombier 	if(wq->nqid < nname){
259*9ef1f84bSDavid du Colombier 		if(alloc)
260*9ef1f84bSDavid du Colombier 			cclose(wq->clone);
261*9ef1f84bSDavid du Colombier 		wq->clone = nil;
262*9ef1f84bSDavid du Colombier 	}else if(wq->clone){
263*9ef1f84bSDavid du Colombier 		/* attach cloned channel to same device */
264*9ef1f84bSDavid du Colombier //what goes here:					//XDYNX
265*9ef1f84bSDavid du Colombier // ->dev must be nil because can't walk an open chan, right?
266*9ef1f84bSDavid du Colombier // what about ref count on dev?
267*9ef1f84bSDavid du Colombier 		wq->clone->dev = c->dev;
268*9ef1f84bSDavid du Colombier 		//if(wq->clone->dev)			//XDYNX
269*9ef1f84bSDavid du Colombier 		//	devtabincr(wq->clone->dev);
270*9ef1f84bSDavid du Colombier 	}
271*9ef1f84bSDavid du Colombier 	return wq;
272*9ef1f84bSDavid du Colombier }
273*9ef1f84bSDavid du Colombier 
274*9ef1f84bSDavid du Colombier long
devstat(Chan * c,uchar * db,long n,Dirtab * tab,int ntab,Devgen * gen)275*9ef1f84bSDavid du Colombier devstat(Chan *c, uchar *db, long n, Dirtab *tab, int ntab, Devgen *gen)
276*9ef1f84bSDavid du Colombier {
277*9ef1f84bSDavid du Colombier 	int i;
278*9ef1f84bSDavid du Colombier 	Dir dir;
279*9ef1f84bSDavid du Colombier 	char *p, *elem;
280*9ef1f84bSDavid du Colombier 
281*9ef1f84bSDavid du Colombier 	for(i=0;; i++){
282*9ef1f84bSDavid du Colombier 		switch((*gen)(c, nil, tab, ntab, i, &dir)){
283*9ef1f84bSDavid du Colombier 		case -1:
284*9ef1f84bSDavid du Colombier 			if(c->qid.type & QTDIR){
285*9ef1f84bSDavid du Colombier 				if(c->path == nil)
286*9ef1f84bSDavid du Colombier 					elem = "???";
287*9ef1f84bSDavid du Colombier 				else if(strcmp(c->path->s, "/") == 0)
288*9ef1f84bSDavid du Colombier 					elem = "/";
289*9ef1f84bSDavid du Colombier 				else
290*9ef1f84bSDavid du Colombier 					for(elem=p=c->path->s; *p; p++)
291*9ef1f84bSDavid du Colombier 						if(*p == '/')
292*9ef1f84bSDavid du Colombier 							elem = p+1;
293*9ef1f84bSDavid du Colombier 				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
294*9ef1f84bSDavid du Colombier 				n = convD2M(&dir, db, n);
295*9ef1f84bSDavid du Colombier 				if(n == 0)
296*9ef1f84bSDavid du Colombier 					error(Ebadarg);
297*9ef1f84bSDavid du Colombier 				return n;
298*9ef1f84bSDavid du Colombier 			}
299*9ef1f84bSDavid du Colombier 
300*9ef1f84bSDavid du Colombier 			error(Enonexist);
301*9ef1f84bSDavid du Colombier 		case 0:
302*9ef1f84bSDavid du Colombier 			break;
303*9ef1f84bSDavid du Colombier 		case 1:
304*9ef1f84bSDavid du Colombier 			if(c->qid.path == dir.qid.path) {
305*9ef1f84bSDavid du Colombier 				if(c->flag&CMSG)
306*9ef1f84bSDavid du Colombier 					dir.mode |= DMMOUNT;
307*9ef1f84bSDavid du Colombier 				n = convD2M(&dir, db, n);
308*9ef1f84bSDavid du Colombier 				if(n == 0)
309*9ef1f84bSDavid du Colombier 					error(Ebadarg);
310*9ef1f84bSDavid du Colombier 				return n;
311*9ef1f84bSDavid du Colombier 			}
312*9ef1f84bSDavid du Colombier 			break;
313*9ef1f84bSDavid du Colombier 		}
314*9ef1f84bSDavid du Colombier 	}
315*9ef1f84bSDavid du Colombier }
316*9ef1f84bSDavid du Colombier 
317*9ef1f84bSDavid du Colombier long
devdirread(Chan * c,char * d,long n,Dirtab * tab,int ntab,Devgen * gen)318*9ef1f84bSDavid du Colombier devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
319*9ef1f84bSDavid du Colombier {
320*9ef1f84bSDavid du Colombier 	long m, dsz;
321*9ef1f84bSDavid du Colombier 	Dir dir;
322*9ef1f84bSDavid du Colombier 
323*9ef1f84bSDavid du Colombier 	for(m=0; m<n; c->dri++) {
324*9ef1f84bSDavid du Colombier 		switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){
325*9ef1f84bSDavid du Colombier 		case -1:
326*9ef1f84bSDavid du Colombier 			return m;
327*9ef1f84bSDavid du Colombier 
328*9ef1f84bSDavid du Colombier 		case 0:
329*9ef1f84bSDavid du Colombier 			break;
330*9ef1f84bSDavid du Colombier 
331*9ef1f84bSDavid du Colombier 		case 1:
332*9ef1f84bSDavid du Colombier 			dsz = convD2M(&dir, (uchar*)d, n-m);
333*9ef1f84bSDavid du Colombier 			if(dsz <= BIT16SZ){	/* <= not < because this isn't stat; read is stuck */
334*9ef1f84bSDavid du Colombier 				if(m == 0)
335*9ef1f84bSDavid du Colombier 					error(Eshort);
336*9ef1f84bSDavid du Colombier 				return m;
337*9ef1f84bSDavid du Colombier 			}
338*9ef1f84bSDavid du Colombier 			m += dsz;
339*9ef1f84bSDavid du Colombier 			d += dsz;
340*9ef1f84bSDavid du Colombier 			break;
341*9ef1f84bSDavid du Colombier 		}
342*9ef1f84bSDavid du Colombier 	}
343*9ef1f84bSDavid du Colombier 
344*9ef1f84bSDavid du Colombier 	return m;
345*9ef1f84bSDavid du Colombier }
346*9ef1f84bSDavid du Colombier 
347*9ef1f84bSDavid du Colombier /*
348*9ef1f84bSDavid du Colombier  * error(Eperm) if open permission not granted for up->user.
349*9ef1f84bSDavid du Colombier  */
350*9ef1f84bSDavid du Colombier void
devpermcheck(char * fileuid,int perm,int omode)351*9ef1f84bSDavid du Colombier devpermcheck(char *fileuid, int perm, int omode)
352*9ef1f84bSDavid du Colombier {
353*9ef1f84bSDavid du Colombier 	int t;
354*9ef1f84bSDavid du Colombier 	static int access[] = { 0400, 0200, 0600, 0100 };
355*9ef1f84bSDavid du Colombier 
356*9ef1f84bSDavid du Colombier 	if(strcmp(up->user, fileuid) == 0)
357*9ef1f84bSDavid du Colombier 		perm <<= 0;
358*9ef1f84bSDavid du Colombier 	else
359*9ef1f84bSDavid du Colombier 	if(strcmp(up->user, eve) == 0)
360*9ef1f84bSDavid du Colombier 		perm <<= 3;
361*9ef1f84bSDavid du Colombier 	else
362*9ef1f84bSDavid du Colombier 		perm <<= 6;
363*9ef1f84bSDavid du Colombier 
364*9ef1f84bSDavid du Colombier 	t = access[omode&3];
365*9ef1f84bSDavid du Colombier 	if((t&perm) != t)
366*9ef1f84bSDavid du Colombier 		error(Eperm);
367*9ef1f84bSDavid du Colombier }
368*9ef1f84bSDavid du Colombier 
369*9ef1f84bSDavid du Colombier Chan*
devopen(Chan * c,int omode,Dirtab * tab,int ntab,Devgen * gen)370*9ef1f84bSDavid du Colombier devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
371*9ef1f84bSDavid du Colombier {
372*9ef1f84bSDavid du Colombier 	int i;
373*9ef1f84bSDavid du Colombier 	Dir dir;
374*9ef1f84bSDavid du Colombier 
375*9ef1f84bSDavid du Colombier 	for(i=0;; i++) {
376*9ef1f84bSDavid du Colombier 		switch((*gen)(c, nil, tab, ntab, i, &dir)){
377*9ef1f84bSDavid du Colombier 		case -1:
378*9ef1f84bSDavid du Colombier 			goto Return;
379*9ef1f84bSDavid du Colombier 		case 0:
380*9ef1f84bSDavid du Colombier 			break;
381*9ef1f84bSDavid du Colombier 		case 1:
382*9ef1f84bSDavid du Colombier 			if(c->qid.path == dir.qid.path) {
383*9ef1f84bSDavid du Colombier 				devpermcheck(dir.uid, dir.mode, omode);
384*9ef1f84bSDavid du Colombier 				goto Return;
385*9ef1f84bSDavid du Colombier 			}
386*9ef1f84bSDavid du Colombier 			break;
387*9ef1f84bSDavid du Colombier 		}
388*9ef1f84bSDavid du Colombier 	}
389*9ef1f84bSDavid du Colombier Return:
390*9ef1f84bSDavid du Colombier 	c->offset = 0;
391*9ef1f84bSDavid du Colombier 	if((c->qid.type & QTDIR) && omode!=OREAD)
392*9ef1f84bSDavid du Colombier 		error(Eperm);
393*9ef1f84bSDavid du Colombier 	c->mode = openmode(omode);
394*9ef1f84bSDavid du Colombier 	c->flag |= COPEN;
395*9ef1f84bSDavid du Colombier 	return c;
396*9ef1f84bSDavid du Colombier }
397*9ef1f84bSDavid du Colombier 
398*9ef1f84bSDavid du Colombier void
devcreate(Chan *,char *,int,int)399*9ef1f84bSDavid du Colombier devcreate(Chan*, char*, int, int)
400*9ef1f84bSDavid du Colombier {
401*9ef1f84bSDavid du Colombier 	error(Eperm);
402*9ef1f84bSDavid du Colombier }
403*9ef1f84bSDavid du Colombier 
404*9ef1f84bSDavid du Colombier Block*
devbread(Chan * c,long n,vlong offset)405*9ef1f84bSDavid du Colombier devbread(Chan *c, long n, vlong offset)
406*9ef1f84bSDavid du Colombier {
407*9ef1f84bSDavid du Colombier 	Block *bp;
408*9ef1f84bSDavid du Colombier 
409*9ef1f84bSDavid du Colombier 	bp = allocb(n);
410*9ef1f84bSDavid du Colombier 	if(bp == 0)
411*9ef1f84bSDavid du Colombier 		error(Enomem);
412*9ef1f84bSDavid du Colombier 	if(waserror()) {
413*9ef1f84bSDavid du Colombier 		freeb(bp);
414*9ef1f84bSDavid du Colombier 		nexterror();
415*9ef1f84bSDavid du Colombier 	}
416*9ef1f84bSDavid du Colombier 	bp->wp += c->dev->read(c, bp->wp, n, offset);
417*9ef1f84bSDavid du Colombier 	poperror();
418*9ef1f84bSDavid du Colombier 	return bp;
419*9ef1f84bSDavid du Colombier }
420*9ef1f84bSDavid du Colombier 
421*9ef1f84bSDavid du Colombier long
devbwrite(Chan * c,Block * bp,vlong offset)422*9ef1f84bSDavid du Colombier devbwrite(Chan *c, Block *bp, vlong offset)
423*9ef1f84bSDavid du Colombier {
424*9ef1f84bSDavid du Colombier 	long n;
425*9ef1f84bSDavid du Colombier 
426*9ef1f84bSDavid du Colombier 	if(waserror()) {
427*9ef1f84bSDavid du Colombier 		freeb(bp);
428*9ef1f84bSDavid du Colombier 		nexterror();
429*9ef1f84bSDavid du Colombier 	}
430*9ef1f84bSDavid du Colombier 	n = c->dev->write(c, bp->rp, BLEN(bp), offset);
431*9ef1f84bSDavid du Colombier 	poperror();
432*9ef1f84bSDavid du Colombier 	freeb(bp);
433*9ef1f84bSDavid du Colombier 
434*9ef1f84bSDavid du Colombier 	return n;
435*9ef1f84bSDavid du Colombier }
436*9ef1f84bSDavid du Colombier 
437*9ef1f84bSDavid du Colombier void
devremove(Chan *)438*9ef1f84bSDavid du Colombier devremove(Chan*)
439*9ef1f84bSDavid du Colombier {
440*9ef1f84bSDavid du Colombier 	error(Eperm);
441*9ef1f84bSDavid du Colombier }
442*9ef1f84bSDavid du Colombier 
443*9ef1f84bSDavid du Colombier long
devwstat(Chan *,uchar *,long)444*9ef1f84bSDavid du Colombier devwstat(Chan*, uchar*, long)
445*9ef1f84bSDavid du Colombier {
446*9ef1f84bSDavid du Colombier 	error(Eperm);
447*9ef1f84bSDavid du Colombier 	return 0;
448*9ef1f84bSDavid du Colombier }
449*9ef1f84bSDavid du Colombier 
450*9ef1f84bSDavid du Colombier void
devpower(int)451*9ef1f84bSDavid du Colombier devpower(int)
452*9ef1f84bSDavid du Colombier {
453*9ef1f84bSDavid du Colombier 	error(Eperm);
454*9ef1f84bSDavid du Colombier }
455*9ef1f84bSDavid du Colombier 
456*9ef1f84bSDavid du Colombier int
devconfig(int,char *,DevConf *)457*9ef1f84bSDavid du Colombier devconfig(int, char *, DevConf *)
458*9ef1f84bSDavid du Colombier {
459*9ef1f84bSDavid du Colombier 	error(Eperm);
460*9ef1f84bSDavid du Colombier 	return 0;
461*9ef1f84bSDavid du Colombier }
462