Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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