xref: /plan9/sys/src/cmd/aux/flashfs/dreq.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->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