xref: /plan9/sys/src/cmd/vnc/dev.c (revision b85a83648eec38fe82b6f00adfd7828ceec5ee8d)
1*9a747e4fSDavid du Colombier #include	<u.h>
2*9a747e4fSDavid du Colombier #include	<libc.h>
3*9a747e4fSDavid du Colombier #include	<fcall.h>
4*9a747e4fSDavid du Colombier #include	"compat.h"
5*9a747e4fSDavid du Colombier #include	"error.h"
6*9a747e4fSDavid du Colombier 
7*9a747e4fSDavid du Colombier extern ulong	kerndate;
8*9a747e4fSDavid du Colombier 
9*9a747e4fSDavid du Colombier void
mkqid(Qid * q,vlong path,ulong vers,int type)10*9a747e4fSDavid du Colombier mkqid(Qid *q, vlong path, ulong vers, int type)
11*9a747e4fSDavid du Colombier {
12*9a747e4fSDavid du Colombier 	q->type = type;
13*9a747e4fSDavid du Colombier 	q->vers = vers;
14*9a747e4fSDavid du Colombier 	q->path = path;
15*9a747e4fSDavid du Colombier }
16*9a747e4fSDavid du Colombier 
17*9a747e4fSDavid du Colombier int
devno(int c,int user)18*9a747e4fSDavid du Colombier devno(int c, int user)
19*9a747e4fSDavid du Colombier {
20*9a747e4fSDavid du Colombier 	int i;
21*9a747e4fSDavid du Colombier 
22*9a747e4fSDavid du Colombier 	for(i = 0; devtab[i] != nil; i++){
23*9a747e4fSDavid du Colombier 		if(devtab[i]->dc == c)
24*9a747e4fSDavid du Colombier 			return i;
25*9a747e4fSDavid du Colombier 	}
26*9a747e4fSDavid du Colombier 	if(user == 0)
27*9a747e4fSDavid du Colombier 		panic("devno %C 0x%ux", c, c);
28*9a747e4fSDavid du Colombier 
29*9a747e4fSDavid du Colombier 	return -1;
30*9a747e4fSDavid du Colombier }
31*9a747e4fSDavid du Colombier 
32*9a747e4fSDavid du Colombier void
devdir(Chan * c,Qid qid,char * n,vlong length,char * user,long perm,Dir * db)33*9a747e4fSDavid du Colombier devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
34*9a747e4fSDavid du Colombier {
35*9a747e4fSDavid du Colombier 	db->name = n;
36*9a747e4fSDavid du Colombier 	db->qid = qid;
37*9a747e4fSDavid du Colombier 	db->type = devtab[c->type]->dc;
38*9a747e4fSDavid du Colombier 	db->dev = c->dev;
39*9a747e4fSDavid du Colombier 	db->mode = (qid.type << 24) | perm;
40*9a747e4fSDavid du Colombier 	db->atime = seconds();
41*9a747e4fSDavid du Colombier 	db->mtime = kerndate;
42*9a747e4fSDavid du Colombier 	db->length = length;
43*9a747e4fSDavid du Colombier 	db->uid = user;
44*9a747e4fSDavid du Colombier 	db->gid = eve;
45*9a747e4fSDavid du Colombier 	db->muid = user;
46*9a747e4fSDavid du Colombier }
47*9a747e4fSDavid du Colombier 
48*9a747e4fSDavid du Colombier /*
49*9a747e4fSDavid du Colombier  * the zeroth element of the table MUST be the directory itself for ..
50*9a747e4fSDavid du Colombier */
51*9a747e4fSDavid du Colombier int
devgen(Chan * c,Dirtab * tab,int ntab,int i,Dir * dp)52*9a747e4fSDavid du Colombier devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
53*9a747e4fSDavid du Colombier {
54*9a747e4fSDavid du Colombier 	if(tab == 0)
55*9a747e4fSDavid du Colombier 		return -1;
56*9a747e4fSDavid du Colombier 	if(i != DEVDOTDOT){
57*9a747e4fSDavid du Colombier 		i++; /* skip first element for . itself */
58*9a747e4fSDavid du Colombier 		if(i >= ntab)
59*9a747e4fSDavid du Colombier 			return -1;
60*9a747e4fSDavid du Colombier 		tab += i;
61*9a747e4fSDavid du Colombier 	}
62*9a747e4fSDavid du Colombier 	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
63*9a747e4fSDavid du Colombier 	return 1;
64*9a747e4fSDavid du Colombier }
65*9a747e4fSDavid du Colombier 
66*9a747e4fSDavid du Colombier void
devreset(void)67*9a747e4fSDavid du Colombier devreset(void)
68*9a747e4fSDavid du Colombier {
69*9a747e4fSDavid du Colombier }
70*9a747e4fSDavid du Colombier 
71*9a747e4fSDavid du Colombier void
devinit(void)72*9a747e4fSDavid du Colombier devinit(void)
73*9a747e4fSDavid du Colombier {
74*9a747e4fSDavid du Colombier }
75*9a747e4fSDavid du Colombier 
76*9a747e4fSDavid du Colombier Chan*
devattach(int tc,char * spec)77*9a747e4fSDavid du Colombier devattach(int tc, char *spec)
78*9a747e4fSDavid du Colombier {
79*9a747e4fSDavid du Colombier 	Chan *c;
80*9a747e4fSDavid du Colombier 	char *buf;
81*9a747e4fSDavid du Colombier 
82*9a747e4fSDavid du Colombier 	c = newchan();
83*9a747e4fSDavid du Colombier 	mkqid(&c->qid, 0, 0, QTDIR);
84*9a747e4fSDavid du Colombier 	c->type = devno(tc, 0);
85*9a747e4fSDavid du Colombier 	if(spec == nil)
86*9a747e4fSDavid du Colombier 		spec = "";
87*9a747e4fSDavid du Colombier 	buf = smalloc(4+strlen(spec)+1);
88*9a747e4fSDavid du Colombier 	sprint(buf, "#%C%s", tc, spec);
89*9a747e4fSDavid du Colombier 	c->name = newcname(buf);
90*9a747e4fSDavid du Colombier 	free(buf);
91*9a747e4fSDavid du Colombier 	return c;
92*9a747e4fSDavid du Colombier }
93*9a747e4fSDavid du Colombier 
94*9a747e4fSDavid du Colombier 
95*9a747e4fSDavid du Colombier Chan*
devclone(Chan * c)96*9a747e4fSDavid du Colombier devclone(Chan *c)
97*9a747e4fSDavid du Colombier {
98*9a747e4fSDavid du Colombier 	Chan *nc;
99*9a747e4fSDavid du Colombier 
100*9a747e4fSDavid du Colombier 	if(c->flag & COPEN)
101*9a747e4fSDavid du Colombier 		panic("clone of open file type %C\n", devtab[c->type]->dc);
102*9a747e4fSDavid du Colombier 
103*9a747e4fSDavid du Colombier 	nc = newchan();
104*9a747e4fSDavid du Colombier 
105*9a747e4fSDavid du Colombier 	nc->type = c->type;
106*9a747e4fSDavid du Colombier 	nc->dev = c->dev;
107*9a747e4fSDavid du Colombier 	nc->mode = c->mode;
108*9a747e4fSDavid du Colombier 	nc->qid = c->qid;
109*9a747e4fSDavid du Colombier 	nc->offset = c->offset;
110*9a747e4fSDavid du Colombier 	nc->aux = c->aux;
111*9a747e4fSDavid du Colombier 	return nc;
112*9a747e4fSDavid du Colombier }
113*9a747e4fSDavid du Colombier 
114*9a747e4fSDavid du Colombier Walkqid*
devwalk(Chan * c,Chan * nc,char ** name,int nname,Dirtab * tab,int ntab,Devgen * gen)115*9a747e4fSDavid du Colombier devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
116*9a747e4fSDavid du Colombier {
117*9a747e4fSDavid du Colombier 	int i, j, alloc;
118*9a747e4fSDavid du Colombier 	Walkqid *wq;
119*9a747e4fSDavid du Colombier 	char *n;
120*9a747e4fSDavid du Colombier 	Dir dir;
121*9a747e4fSDavid du Colombier 
122*9a747e4fSDavid du Colombier 	isdir(c);
123*9a747e4fSDavid du Colombier 
124*9a747e4fSDavid du Colombier 	alloc = 0;
125*9a747e4fSDavid du Colombier 	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
126*9a747e4fSDavid du Colombier 	if(waserror()){
127*9a747e4fSDavid du Colombier 		if(alloc && wq->clone!=nil)
128*9a747e4fSDavid du Colombier 			cclose(wq->clone);
129*9a747e4fSDavid du Colombier 		free(wq);
130*9a747e4fSDavid du Colombier 		return nil;
131*9a747e4fSDavid du Colombier 	}
132*9a747e4fSDavid du Colombier 	if(nc == nil){
133*9a747e4fSDavid du Colombier 		nc = devclone(c);
134*9a747e4fSDavid du Colombier 		nc->type = 0;	/* device doesn't know about this channel yet */
135*9a747e4fSDavid du Colombier 		alloc = 1;
136*9a747e4fSDavid du Colombier 	}
137*9a747e4fSDavid du Colombier 	wq->clone = nc;
138*9a747e4fSDavid du Colombier 
139*9a747e4fSDavid du Colombier 	for(j=0; j<nname; j++){
140*9a747e4fSDavid du Colombier 		isdir(nc);
141*9a747e4fSDavid du Colombier 		n = name[j];
142*9a747e4fSDavid du Colombier 		if(strcmp(n, ".") == 0){
143*9a747e4fSDavid du Colombier     Accept:
144*9a747e4fSDavid du Colombier 			wq->qid[wq->nqid++] = nc->qid;
145*9a747e4fSDavid du Colombier 			continue;
146*9a747e4fSDavid du Colombier 		}
147*9a747e4fSDavid du Colombier 		if(strcmp(n, "..") == 0){
148*9a747e4fSDavid du Colombier 			(*gen)(nc, tab, ntab, DEVDOTDOT, &dir);
149*9a747e4fSDavid du Colombier 			nc->qid = dir.qid;
150*9a747e4fSDavid du Colombier 			goto Accept;
151*9a747e4fSDavid du Colombier 		}
152*9a747e4fSDavid du Colombier 		for(i=0;; i++){
153*9a747e4fSDavid du Colombier 			switch((*gen)(nc, tab, ntab, i, &dir)){
154*9a747e4fSDavid du Colombier 			case -1:
155*9a747e4fSDavid du Colombier 				if(j == 0)
156*9a747e4fSDavid du Colombier 					error(Enonexist);
157*9a747e4fSDavid du Colombier 				strncpy(up->error, Enonexist, ERRMAX);
158*9a747e4fSDavid du Colombier 				goto Done;
159*9a747e4fSDavid du Colombier 			case 0:
160*9a747e4fSDavid du Colombier 				continue;
161*9a747e4fSDavid du Colombier 			case 1:
162*9a747e4fSDavid du Colombier 				if(strcmp(n, dir.name) == 0){
163*9a747e4fSDavid du Colombier 					nc->qid = dir.qid;
164*9a747e4fSDavid du Colombier 					goto Accept;
165*9a747e4fSDavid du Colombier 				}
166*9a747e4fSDavid du Colombier 				continue;
167*9a747e4fSDavid du Colombier 			}
168*9a747e4fSDavid du Colombier 		}
169*9a747e4fSDavid du Colombier 	}
170*9a747e4fSDavid du Colombier 	/*
171*9a747e4fSDavid du Colombier 	 * We processed at least one name, so will return some data.
172*9a747e4fSDavid du Colombier 	 * If we didn't process all nname entries succesfully, we drop
173*9a747e4fSDavid du Colombier 	 * the cloned channel and return just the Qids of the walks.
174*9a747e4fSDavid du Colombier 	 */
175*9a747e4fSDavid du Colombier Done:
176*9a747e4fSDavid du Colombier 	poperror();
177*9a747e4fSDavid du Colombier 	if(wq->nqid < nname){
178*9a747e4fSDavid du Colombier 		if(alloc)
179*9a747e4fSDavid du Colombier 			cclose(wq->clone);
180*9a747e4fSDavid du Colombier 		wq->clone = nil;
181*9a747e4fSDavid du Colombier 	}else if(wq->clone){
182*9a747e4fSDavid du Colombier 		/* attach cloned channel to same device */
183*9a747e4fSDavid du Colombier 		wq->clone->type = c->type;
184*9a747e4fSDavid du Colombier 	}
185*9a747e4fSDavid du Colombier 	return wq;
186*9a747e4fSDavid du Colombier }
187*9a747e4fSDavid du Colombier 
188*9a747e4fSDavid du Colombier int
devstat(Chan * c,uchar * db,int n,Dirtab * tab,int ntab,Devgen * gen)189*9a747e4fSDavid du Colombier devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
190*9a747e4fSDavid du Colombier {
191*9a747e4fSDavid du Colombier 	int i;
192*9a747e4fSDavid du Colombier 	Dir dir;
193*9a747e4fSDavid du Colombier 	char *p, *elem;
194*9a747e4fSDavid du Colombier 
195*9a747e4fSDavid du Colombier 	for(i=0;; i++)
196*9a747e4fSDavid du Colombier 		switch((*gen)(c, tab, ntab, i, &dir)){
197*9a747e4fSDavid du Colombier 		case -1:
198*9a747e4fSDavid du Colombier 			if(c->qid.type & QTDIR){
199*9a747e4fSDavid du Colombier 				if(c->name == nil)
200*9a747e4fSDavid du Colombier 					elem = "???";
201*9a747e4fSDavid du Colombier 				else if(strcmp(c->name->s, "/") == 0)
202*9a747e4fSDavid du Colombier 					elem = "/";
203*9a747e4fSDavid du Colombier 				else
204*9a747e4fSDavid du Colombier 					for(elem=p=c->name->s; *p; p++)
205*9a747e4fSDavid du Colombier 						if(*p == '/')
206*9a747e4fSDavid du Colombier 							elem = p+1;
207*9a747e4fSDavid du Colombier 				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
208*9a747e4fSDavid du Colombier 				return convD2M(&dir, db, n);
209*9a747e4fSDavid du Colombier 			}
210*9a747e4fSDavid du Colombier 
211*9a747e4fSDavid du Colombier 			error(Enonexist);
212*9a747e4fSDavid du Colombier 		case 0:
213*9a747e4fSDavid du Colombier 			break;
214*9a747e4fSDavid du Colombier 		case 1:
215*9a747e4fSDavid du Colombier 			if(c->qid.path == dir.qid.path){
216*9a747e4fSDavid du Colombier 				return convD2M(&dir, db, n);
217*9a747e4fSDavid du Colombier 			}
218*9a747e4fSDavid du Colombier 			break;
219*9a747e4fSDavid du Colombier 		}
220*9a747e4fSDavid du Colombier }
221*9a747e4fSDavid du Colombier 
222*9a747e4fSDavid du Colombier long
devdirread(Chan * c,char * d,long n,Dirtab * tab,int ntab,Devgen * gen)223*9a747e4fSDavid du Colombier devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
224*9a747e4fSDavid du Colombier {
225*9a747e4fSDavid du Colombier 	long k, m, dsz;
226*9a747e4fSDavid du Colombier 	struct{
227*9a747e4fSDavid du Colombier 		Dir;
228*9a747e4fSDavid du Colombier 		char slop[100];
229*9a747e4fSDavid du Colombier 	}dir;
230*9a747e4fSDavid du Colombier 
231*9a747e4fSDavid du Colombier 	k = c->offset;
232*9a747e4fSDavid du Colombier 	for(m=0; m<n; k++){
233*9a747e4fSDavid du Colombier 		switch((*gen)(c, tab, ntab, k, &dir)){
234*9a747e4fSDavid du Colombier 		case -1:
235*9a747e4fSDavid du Colombier 			return m;
236*9a747e4fSDavid du Colombier 
237*9a747e4fSDavid du Colombier 		case 0:
238*9a747e4fSDavid du Colombier 			c->offset++;	/* BUG??? (was DIRLEN: skip entry) */
239*9a747e4fSDavid du Colombier 			break;
240*9a747e4fSDavid du Colombier 
241*9a747e4fSDavid du Colombier 		case 1:
242*9a747e4fSDavid du Colombier 			dsz = convD2M(&dir, (uchar*)d, n-m);
243*9a747e4fSDavid du Colombier 			if(dsz <= BIT16SZ){	/* <= not < because this isn't stat; read is stuck */
244*9a747e4fSDavid du Colombier 				if(m == 0)
245*9a747e4fSDavid du Colombier 					return -1;
246*9a747e4fSDavid du Colombier 				return m;
247*9a747e4fSDavid du Colombier 			}
248*9a747e4fSDavid du Colombier 			m += dsz;
249*9a747e4fSDavid du Colombier 			d += dsz;
250*9a747e4fSDavid du Colombier 			break;
251*9a747e4fSDavid du Colombier 		}
252*9a747e4fSDavid du Colombier 	}
253*9a747e4fSDavid du Colombier 
254*9a747e4fSDavid du Colombier 	return m;
255*9a747e4fSDavid du Colombier }
256*9a747e4fSDavid du Colombier 
257*9a747e4fSDavid du Colombier /*
258*9a747e4fSDavid du Colombier  * error(Eperm) if open permission not granted for up->user.
259*9a747e4fSDavid du Colombier  */
260*9a747e4fSDavid du Colombier void
devpermcheck(char * fileuid,ulong perm,int omode)261*9a747e4fSDavid du Colombier devpermcheck(char *fileuid, ulong perm, int omode)
262*9a747e4fSDavid du Colombier {
263*9a747e4fSDavid du Colombier 	ulong t;
264*9a747e4fSDavid du Colombier 	static int access[] = { 0400, 0200, 0600, 0100 };
265*9a747e4fSDavid du Colombier 
266*9a747e4fSDavid du Colombier 	if(strcmp(up->user, fileuid) == 0)
267*9a747e4fSDavid du Colombier 		perm <<= 0;
268*9a747e4fSDavid du Colombier 	else
269*9a747e4fSDavid du Colombier 	if(strcmp(up->user, eve) == 0)
270*9a747e4fSDavid du Colombier 		perm <<= 3;
271*9a747e4fSDavid du Colombier 	else
272*9a747e4fSDavid du Colombier 		perm <<= 6;
273*9a747e4fSDavid du Colombier 
274*9a747e4fSDavid du Colombier 	t = access[omode&3];
275*9a747e4fSDavid du Colombier 	if((t&perm) != t)
276*9a747e4fSDavid du Colombier 		error(Eperm);
277*9a747e4fSDavid du Colombier }
278*9a747e4fSDavid du Colombier 
279*9a747e4fSDavid du Colombier Chan*
devopen(Chan * c,int omode,Dirtab * tab,int ntab,Devgen * gen)280*9a747e4fSDavid du Colombier devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
281*9a747e4fSDavid du Colombier {
282*9a747e4fSDavid du Colombier 	int i;
283*9a747e4fSDavid du Colombier 	Dir dir;
284*9a747e4fSDavid du Colombier 
285*9a747e4fSDavid du Colombier 	for(i=0;; i++){
286*9a747e4fSDavid du Colombier 		switch((*gen)(c, tab, ntab, i, &dir)){
287*9a747e4fSDavid du Colombier 		case -1:
288*9a747e4fSDavid du Colombier 			goto Return;
289*9a747e4fSDavid du Colombier 		case 0:
290*9a747e4fSDavid du Colombier 			break;
291*9a747e4fSDavid du Colombier 		case 1:
292*9a747e4fSDavid du Colombier 			if(c->qid.path == dir.qid.path){
293*9a747e4fSDavid du Colombier 				devpermcheck(dir.uid, dir.mode, omode);
294*9a747e4fSDavid du Colombier 				goto Return;
295*9a747e4fSDavid du Colombier 			}
296*9a747e4fSDavid du Colombier 			break;
297*9a747e4fSDavid du Colombier 		}
298*9a747e4fSDavid du Colombier 	}
299*9a747e4fSDavid du Colombier Return:
300*9a747e4fSDavid du Colombier 	c->offset = 0;
301*9a747e4fSDavid du Colombier 	if((c->qid.type&QTDIR) && omode!=OREAD)
302*9a747e4fSDavid du Colombier 		error(Eperm);
303*9a747e4fSDavid du Colombier 	c->mode = openmode(omode);
304*9a747e4fSDavid du Colombier 	c->flag |= COPEN;
305*9a747e4fSDavid du Colombier 	return c;
306*9a747e4fSDavid du Colombier }
307*9a747e4fSDavid du Colombier 
308*9a747e4fSDavid du Colombier void
devcreate(Chan *,char *,int,ulong)309*9a747e4fSDavid du Colombier devcreate(Chan*, char*, int, ulong)
310*9a747e4fSDavid du Colombier {
311*9a747e4fSDavid du Colombier 	error(Eperm);
312*9a747e4fSDavid du Colombier }
313*9a747e4fSDavid du Colombier 
314*9a747e4fSDavid du Colombier Block*
devbread(Chan *,long,ulong)315*9a747e4fSDavid du Colombier devbread(Chan *, long, ulong)
316*9a747e4fSDavid du Colombier {
317*9a747e4fSDavid du Colombier 	panic("no block read");
318*9a747e4fSDavid du Colombier 	return nil;
319*9a747e4fSDavid du Colombier }
320*9a747e4fSDavid du Colombier 
321*9a747e4fSDavid du Colombier long
devbwrite(Chan *,Block *,ulong)322*9a747e4fSDavid du Colombier devbwrite(Chan *, Block *, ulong)
323*9a747e4fSDavid du Colombier {
324*9a747e4fSDavid du Colombier 	panic("no block write");
325*9a747e4fSDavid du Colombier 	return 0;
326*9a747e4fSDavid du Colombier }
327*9a747e4fSDavid du Colombier 
328*9a747e4fSDavid du Colombier void
devremove(Chan *)329*9a747e4fSDavid du Colombier devremove(Chan*)
330*9a747e4fSDavid du Colombier {
331*9a747e4fSDavid du Colombier 	error(Eperm);
332*9a747e4fSDavid du Colombier }
333*9a747e4fSDavid du Colombier 
334*9a747e4fSDavid du Colombier int
devwstat(Chan *,uchar *,int)335*9a747e4fSDavid du Colombier devwstat(Chan*, uchar*, int)
336*9a747e4fSDavid du Colombier {
337*9a747e4fSDavid du Colombier 	error(Eperm);
338*9a747e4fSDavid du Colombier 	return 0;
339*9a747e4fSDavid du Colombier }
340