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->e)
39 edestroy(s->e);
40 if(s->r)
41 edirclose(s->r);
42 free(s);
43 }
44
45 static void
trace(Req *)46 trace(Req *)
47 {
48 edump();
49 }
50
51 /** T_ **/
52
53 static void
flattach(Req * r)54 flattach(Req *r)
55 {
56 root->ref++;
57 r->ofcall.qid = eqid(root);
58 r->fid->aux = state(root);
59 respond(r, nil);
60 }
61
62 static void
flopen(Req * r)63 flopen(Req *r)
64 {
65 int m, p;
66 Entry *e;
67 State *s;
68
69 s = r->fid->aux;
70 e = s->e;
71 m = e->mode;
72 m = (m | (m >> 3) | (m >> 6)) & 7;
73 switch(r->ifcall.mode & 3) {
74 case OREAD:
75 p = AREAD;
76 break;
77 case OWRITE:
78 p = AWRITE;
79 break;
80 case ORDWR:
81 p = AREAD|AWRITE;
82 break;
83 case OEXEC:
84 p = AEXEC;
85 break;
86 default:
87 p = 0;
88 break;
89 }
90
91 if((p & m) != p) {
92 respond(r, Eperm);
93 return;
94 }
95
96 if(readonly && (p & AWRITE) != 0) {
97 respond(r, Erofs);
98 return;
99 }
100
101 r->ofcall.qid = eqid(e);
102 if(r->ofcall.qid.type & QTDIR)
103 s->r = ediropen(s->e);
104 else if(r->ifcall.mode & OTRUNC)
105 etrunc(e, 0, time(0));
106
107 respond(r, nil);
108 }
109
110 static void
flcreate(Req * r)111 flcreate(Req *r)
112 {
113 State *s;
114 char *err;
115 Entry *e, *f;
116
117 if(readonly) {
118 respond(r, Erofs);
119 return;
120 }
121
122 s = r->fid->aux;
123 e = s->e;
124 if(!writeable(e)) {
125 respond(r, Eperm);
126 return;
127 }
128
129 f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, time(0), &err);
130 if(f == nil) {
131 respond(r, err);
132 return;
133 }
134
135 s->e = f;
136 r->ofcall.qid = eqid(f);
137 respond(r, nil);
138 }
139
140 static void
flread(Req * r)141 flread(Req *r)
142 {
143 Entry *e;
144 State *s;
145
146 s = r->fid->aux;
147 e = s->e;
148
149 if(e->mode & DMDIR)
150 r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count);
151 else
152 r->ofcall.count = 0;
153
154 respond(r, nil);
155 }
156
157 static void
flwrite(Req * r)158 flwrite(Req *r)
159 {
160 if(r->ifcall.offset + r->ifcall.count >= MAXFSIZE) {
161 respond(r, "file too big");
162 return;
163 }
164
165 r->ofcall.count = r->ifcall.count;
166 respond(r, nil);
167 }
168
169 static void
flremove(Req * r)170 flremove(Req *r)
171 {
172 State *s;
173 Entry *e;
174
175 if(readonly) {
176 respond(r, Erofs);
177 return;
178 }
179
180 s = r->fid->aux;
181 e = s->e;
182 if(writeable(e->parent))
183 respond(r, eremove(e));
184 else
185 respond(r, Eperm);
186 }
187
188 static void
flstat(Req * r)189 flstat(Req *r)
190 {
191 State *s;
192
193 s = r->fid->aux;
194 estat(s->e, &r->d, 1);
195 respond(r, nil);
196 }
197
198 static void
flwstat(Req * r)199 flwstat(Req *r)
200 {
201 int m;
202 State *s;
203 Entry *e;
204
205 s = r->fid->aux;
206 e = s->e;
207 m = r->d.mode & 0777;
208 if(m != (e->mode & 0777))
209 echmod(e, m, 0);
210 respond(r, nil);
211 }
212
213 static void
flwalk(Req * r)214 flwalk(Req *r)
215 {
216 int i;
217 State *s;
218 char *err;
219 Entry *e, *f;
220
221 if(readonly) {
222 respond(r, Erofs);
223 return;
224 }
225
226 if(r->ifcall.fid != r->ifcall.newfid)
227 r->newfid->aux = state(nil);
228
229 s = r->fid->aux;
230 e = s->e;
231 f = e;
232 e->ref++;
233 err = nil;
234 for(i = 0; i < r->ifcall.nwname; i++) {
235 f = ewalk(e, r->ifcall.wname[i], &err);
236 if(f) {
237 r->ofcall.wqid[i] = eqid(f);
238 e = f;
239 }
240 else {
241 e->ref--;
242 break;
243 }
244 }
245 r->ofcall.nwqid = i;
246
247 if(f) {
248 if(r->ifcall.fid != r->ifcall.newfid) {
249 s = r->newfid->aux;
250 s->e = f;
251 r->newfid->qid = eqid(f);
252 }
253 else {
254 s = r->fid->aux;
255 s->e->ref--;
256 s->e = f;
257 r->fid->qid = eqid(f);
258 }
259 }
260 respond(r, err);
261 }
262
263 void
serve(char * mount)264 serve(char *mount)
265 {
266 flashsrv.attach = flattach;
267 flashsrv.open = flopen;
268 flashsrv.create = flcreate;
269 flashsrv.read = flread;
270 flashsrv.write = flwrite;
271 flashsrv.remove = flremove;
272 flashsrv.stat = flstat;
273 flashsrv.wstat = flwstat;
274 flashsrv.walk = flwalk;
275
276 flashsrv.destroyfid = destroy;
277 flashsrv.destroyreq = trace;
278 einit();
279 postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE);
280 }
281