Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 *
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
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
46
trace(Req *)
47
{
48
	edump();
49
}
50
 
51
/** T_ **/
52
 
53
static void
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
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
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
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
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
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
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
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
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
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
}