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