Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <fcall.h>
5
#include <thread.h>
6
#include <9p.h>
7
#include "flashfs.h"
8
 
9
static	Srv	flashsrv;
10
 
11
typedef struct	State	State;
12
 
13
struct State
14
{
15
	Entry	*e;
16
	Dirr	*r;
17
};
18
 
19
#define	writeable(e)	((e)->mode & 0222)
20
 
21
static State *
22
state(Entry *e)
23
{
24
	State *s;
25
 
26
	s = emalloc9p(sizeof(State));
27
	s->e = e;
28
	s->r = nil;
29
	return s;
30
}
31
 
32
static void
33
destroy(Fid *f)
34
{
35
	State *s;
36
 
37
	s = f->aux;
38
	if(s == nil)		/* Tauth fids have no state */
39
		return;
40
 
41
	f->aux = nil;
42
	if(s->e)
43
		edestroy(s->e);
44
	if(s->r)
45
		edirclose(s->r);
46
	free(s);
47
}
48
 
49
static void
50
trace(Req *)
51
{
52
	edump();
53
}
54
 
55
/** T_ **/
56
 
57
static void
58
flattach(Req *r)
59
{
60
	root->ref++;
61
	r->ofcall.qid = eqid(root);
62
	r->fid->qid = r->ofcall.qid;
63
	r->fid->aux = state(root);
64
	respond(r, nil);
65
}
66
 
67
static void
68
flopen(Req *r)
69
{
70
	Jrec j;
71
	int m, p;
72
	Entry *e;
73
	State *s;
74
	char *err;
75
 
76
	s = r->fid->aux;
77
	e = s->e;
78
	m = e->mode;
79
	m = (m | (m >> 3) | (m >> 6)) & 7;
80
	switch(r->ifcall.mode & 3) {
81
	case OREAD:
82
		p = AREAD;
83
		break;
84
	case OWRITE:
85
		p = AWRITE;
86
		break;
87
	case ORDWR:
88
		p = AREAD|AWRITE;
89
		break;
90
	case OEXEC:
91
		p = AEXEC;
92
		break;
93
	default:
94
		p = 0;
95
		break;
96
	}
97
 
98
	if((p & m) != p) {
99
		respond(r, Eperm);
100
		return;
101
	}
102
 
103
	if(readonly && (p & AWRITE) != 0) {
104
		respond(r, Erofs);
105
		return;
106
	}
107
 
108
	r->ofcall.qid = eqid(e);
109
	if(r->ofcall.qid.type & QTDIR) {
110
		if((p & AWRITE) != 0) {
111
			respond(r, Eisdir);
112
			return;
113
		}
114
		s->r = ediropen(s->e);
115
	}
116
	else if(r->ifcall.mode & OTRUNC) {
117
		err = need(Ntrunc);
118
		if(err != nil) {
119
			respond(r, err);
120
			return;
121
		}
122
		j.type = FT_trunc;
123
		j.tnum = e->fnum;
124
		j.mtime = now();
125
		etrunc(e, 0, j.mtime);
126
		j.fnum = e->fnum;
127
		j.parent = e->parent->fnum;
128
		j.mode = e->mode;
129
		strcpy(j.name, e->name);
130
		put(&j, 1);
131
	}
132
 
133
	respond(r, nil);
134
}
135
 
136
static void
137
flcreate(Req *r)
138
{
139
	Jrec j;
140
	State *s;
141
	char *err;
142
	Entry *e, *f;
143
 
144
	if(readonly) {
145
		respond(r, Erofs);
146
		return;
147
	}
148
 
149
	s = r->fid->aux;
150
	e = s->e;
151
	if((e->mode & DMDIR) == 0) {
152
		respond(r, Eisdir);
153
		return;
154
	}
155
 
156
	if(!writeable(e)) {
157
		respond(r, Eperm);
158
		return;
159
	}
160
 
161
	if(strlen(r->ifcall.name) > MAXNSIZE) {
162
		respond(r, "filename too long");
163
		return;
164
	}
165
 
166
	err = need(Ncreate);
167
	if(err != nil) {
168
		respond(r, err);
169
		return;
170
	}
171
 
172
	j.type = FT_create;
173
	j.mtime = now();
174
	j.parent = e->fnum;
175
	j.mode = r->ifcall.perm;
176
	strcpy(j.name, r->ifcall.name);
177
 
178
	f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, j.mtime, &err);
179
	if(f == nil) {
180
		respond(r, err);
181
		return;
182
	}
183
 
184
	j.fnum = f->fnum;
185
	put(&j, 1);
186
	s->e = f;
187
	r->ofcall.qid = eqid(f);
188
	respond(r, nil);
189
}
190
 
191
static void
192
flread(Req *r)
193
{
194
	Entry *e;
195
	State *s;
196
 
197
	s = r->fid->aux;
198
	e = s->e;
199
 
200
	if(e->mode & DMDIR)
201
		r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count);
202
	else
203
		r->ofcall.count = eread(e, eparity, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
204
 
205
	respond(r, nil);
206
}
207
 
208
static void
209
flwrite(Req *r)
210
{
211
	Jrec j;
212
	uchar *a;
213
	Entry *e;
214
	State *s;
215
	Extent *x;
216
	char *err;
217
	ulong c, n, o, mtime;
218
 
219
	c = r->ifcall.count;
220
	o = r->ifcall.offset;
221
	a = (uchar *)r->ifcall.data;
222
 
223
	if(c == 0) {
224
		respond(r, nil);
225
		return;
226
	}
227
 
228
	if(o + c >= MAXFSIZE) {
229
		respond(r, "file too big");
230
		return;
231
	}
232
 
233
	if(used + c > limit) {
234
		respond(r, "filesystem full");
235
		return;
236
	}
237
 
238
	r->ofcall.count = c;
239
	s = r->fid->aux;
240
	e = s->e;
241
	mtime = now();
242
 
243
	for(;;) {
244
		n = c;
245
		if(n > maxwrite)
246
			n = maxwrite;
247
 
248
		err = need(Nwrite + n);
249
		if(err != nil) {
250
			respond(r, err);
251
			return;
252
		}
253
 
254
		x = emalloc9p(sizeof(Extent));
255
		x->size = n;
256
		x->off = o;
257
		ewrite(e, x, eparity, mtime);
258
		j.type = FT_WRITE;
259
		j.fnum = e->fnum;
260
		j.size = n;
261
		j.offset = o;
262
		j.mtime = mtime;
263
		putw(&j, 1, x, a);
264
		c -= n;
265
 
266
		if(c == 0)
267
			break;
268
 
269
		o += n;
270
		a += n;
271
	}
272
 
273
	respond(r, nil);
274
}
275
 
276
static void
277
flremove(Req *r)
278
{
279
	Jrec j;
280
	State *s;
281
	Entry *e;
282
	char *d, *err;
283
 
284
	if(readonly) {
285
		respond(r, Erofs);
286
		return;
287
	}
288
 
289
	s = r->fid->aux;
290
	e = s->e;
291
	if(writeable(e->parent)) {
292
		err = need(Nremove);
293
		if(err != nil) {
294
			respond(r, err);
295
			return;
296
		}
297
 
298
		d = eremove(e);
299
		if(d == nil) {
300
			j.type = FT_REMOVE;
301
			j.fnum = e->fnum;
302
			put(&j, 0);
303
		}
304
		respond(r, d);
305
	}
306
	else
307
		respond(r, Eperm);
308
}
309
 
310
static void
311
flstat(Req *r)
312
{
313
	State *s;
314
 
315
	s = r->fid->aux;
316
	estat(s->e, &r->d, 1);
317
	respond(r, nil);
318
}
319
 
320
static void
321
flwstat(Req *r)
322
{
323
	int m;
324
	Jrec j;
325
	State *s;
326
	Entry *e;
327
	char *err;
328
 
329
	s = r->fid->aux;
330
	e = s->e;
331
 
332
	if(readonly) {
333
		respond(r, Erofs);
334
		return;
335
	}
336
 
337
	if(e->fnum == 0) {
338
		respond(r, Eperm);
339
		return;
340
	}
341
 
342
	m = r->d.mode & 0777;
343
	if(m != (e->mode & 0777)) {
344
		err = need(Nchmod);
345
		if(err != nil) {
346
			respond(r, err);
347
			return;
348
		}
349
 
350
		echmod(e, m, 0);
351
		j.type = FT_chmod;
352
		j.mode = m;
353
		j.fnum = e->fnum;
354
		j.mnum = e->mnum;
355
		put(&j, 0);
356
	}
357
	respond(r, nil);
358
}
359
 
360
static void
361
flwalk(Req *r)
362
{
363
	int i;
364
	State *s;
365
	char *err;
366
	Entry *e, *f;
367
 
368
	if(r->ifcall.fid != r->ifcall.newfid)
369
		r->newfid->aux = state(nil);
370
 
371
	s = r->fid->aux;
372
	e = s->e;
373
	f = e;
374
	e->ref++;
375
	err = nil;
376
	for(i = 0; i < r->ifcall.nwname; i++) {
377
		f = ewalk(e, r->ifcall.wname[i], &err);
378
		if(f) {
379
			r->ofcall.wqid[i] = eqid(f);
380
			e = f;
381
		}
382
		else {
383
			e->ref--;
384
			break;
385
		}
386
	}
387
	r->ofcall.nwqid = i;
388
	if (i) err = nil;
389
 
390
	if(f) {
391
		if(r->ifcall.fid != r->ifcall.newfid) {
392
			s = r->newfid->aux;
393
			s->e = f;
394
			r->newfid->qid = eqid(f);
395
		}
396
		else {
397
			s = r->fid->aux;
398
			s->e->ref--;
399
			s->e = f;
400
			r->fid->qid = eqid(f);
401
		}
402
	}
403
	respond(r, err);
404
}
405
 
406
void
407
serve(char *mount)
408
{
409
	flashsrv.attach = flattach;
410
	flashsrv.open = flopen;
411
	flashsrv.create = flcreate;
412
	flashsrv.read = flread;
413
	flashsrv.write = flwrite;
414
	flashsrv.remove = flremove;
415
	flashsrv.stat = flstat;
416
	flashsrv.wstat = flwstat;
417
	flashsrv.walk = flwalk;
418
 
419
	flashsrv.destroyfid = destroy;
420
	flashsrv.destroyreq = trace;
421
	postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE);
422
}