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