xref: /plan9/sys/src/cmd/aux/flashfs/request.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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 *
state(Entry * e)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
destroy(Fid * f)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
trace(Req *)50 trace(Req *)
51 {
52 	edump();
53 }
54 
55 /** T_ **/
56 
57 static void
flattach(Req * r)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
flopen(Req * r)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
flcreate(Req * r)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
flread(Req * r)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
flwrite(Req * r)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
flremove(Req * r)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
flstat(Req * r)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
flwstat(Req * r)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
flwalk(Req * r)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
serve(char * mount)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 }
423