Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/cmd/unix/drawterm/kern/dev.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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