Blame


1 2277c5d7 2004-03-21 devnull #include <u.h>
2 2277c5d7 2004-03-21 devnull #include <libc.h>
3 2277c5d7 2004-03-21 devnull #include <fcall.h>
4 2277c5d7 2004-03-21 devnull #include <thread.h>
5 2277c5d7 2004-03-21 devnull #include <9p.h>
6 8ba38113 2005-03-04 devnull
7 8ba38113 2005-03-04 devnull int chatty9p;
8 2277c5d7 2004-03-21 devnull
9 cbeb0b26 2006-04-01 devnull /* static char Ebadattach[] = "unknown specifier in attach"; */
10 2277c5d7 2004-03-21 devnull static char Ebadoffset[] = "bad offset";
11 cbeb0b26 2006-04-01 devnull /* static char Ebadcount[] = "bad count"; */
12 2277c5d7 2004-03-21 devnull static char Ebotch[] = "9P protocol botch";
13 2277c5d7 2004-03-21 devnull static char Ecreatenondir[] = "create in non-directory";
14 2277c5d7 2004-03-21 devnull static char Edupfid[] = "duplicate fid";
15 2277c5d7 2004-03-21 devnull static char Eduptag[] = "duplicate tag";
16 2277c5d7 2004-03-21 devnull static char Eisdir[] = "is a directory";
17 2277c5d7 2004-03-21 devnull static char Enocreate[] = "create prohibited";
18 cbeb0b26 2006-04-01 devnull /* static char Enomem[] = "out of memory"; */
19 2277c5d7 2004-03-21 devnull static char Enoremove[] = "remove prohibited";
20 2277c5d7 2004-03-21 devnull static char Enostat[] = "stat prohibited";
21 2277c5d7 2004-03-21 devnull static char Enotfound[] = "file not found";
22 cbeb0b26 2006-04-01 devnull /* static char Enowrite[] = "write prohibited"; */
23 2277c5d7 2004-03-21 devnull static char Enowstat[] = "wstat prohibited";
24 2277c5d7 2004-03-21 devnull static char Eperm[] = "permission denied";
25 2277c5d7 2004-03-21 devnull static char Eunknownfid[] = "unknown fid";
26 2277c5d7 2004-03-21 devnull static char Ebaddir[] = "bad directory in wstat";
27 2277c5d7 2004-03-21 devnull static char Ewalknodir[] = "walk in non-directory";
28 2277c5d7 2004-03-21 devnull
29 2277c5d7 2004-03-21 devnull static void
30 2277c5d7 2004-03-21 devnull setfcallerror(Fcall *f, char *err)
31 2277c5d7 2004-03-21 devnull {
32 2277c5d7 2004-03-21 devnull f->ename = err;
33 2277c5d7 2004-03-21 devnull f->type = Rerror;
34 2277c5d7 2004-03-21 devnull }
35 2277c5d7 2004-03-21 devnull
36 2277c5d7 2004-03-21 devnull static void
37 2277c5d7 2004-03-21 devnull changemsize(Srv *srv, int msize)
38 2277c5d7 2004-03-21 devnull {
39 2277c5d7 2004-03-21 devnull if(srv->rbuf && srv->wbuf && srv->msize == msize)
40 2277c5d7 2004-03-21 devnull return;
41 2277c5d7 2004-03-21 devnull qlock(&srv->rlock);
42 2277c5d7 2004-03-21 devnull qlock(&srv->wlock);
43 2277c5d7 2004-03-21 devnull srv->msize = msize;
44 2277c5d7 2004-03-21 devnull free(srv->rbuf);
45 2277c5d7 2004-03-21 devnull free(srv->wbuf);
46 2277c5d7 2004-03-21 devnull srv->rbuf = emalloc9p(msize);
47 2277c5d7 2004-03-21 devnull srv->wbuf = emalloc9p(msize);
48 2277c5d7 2004-03-21 devnull qunlock(&srv->rlock);
49 2277c5d7 2004-03-21 devnull qunlock(&srv->wlock);
50 2277c5d7 2004-03-21 devnull }
51 2277c5d7 2004-03-21 devnull
52 2277c5d7 2004-03-21 devnull static Req*
53 2277c5d7 2004-03-21 devnull getreq(Srv *s)
54 2277c5d7 2004-03-21 devnull {
55 2277c5d7 2004-03-21 devnull long n;
56 2277c5d7 2004-03-21 devnull uchar *buf;
57 2277c5d7 2004-03-21 devnull Fcall f;
58 2277c5d7 2004-03-21 devnull Req *r;
59 2277c5d7 2004-03-21 devnull
60 2277c5d7 2004-03-21 devnull qlock(&s->rlock);
61 2277c5d7 2004-03-21 devnull if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){
62 2277c5d7 2004-03-21 devnull qunlock(&s->rlock);
63 2277c5d7 2004-03-21 devnull return nil;
64 2277c5d7 2004-03-21 devnull }
65 2277c5d7 2004-03-21 devnull
66 943cb39d 2006-02-14 devnull buf = emalloc9p(n+1); /* +1 for NUL in swrite */
67 2277c5d7 2004-03-21 devnull memmove(buf, s->rbuf, n);
68 2277c5d7 2004-03-21 devnull qunlock(&s->rlock);
69 2277c5d7 2004-03-21 devnull
70 90c892d8 2006-01-27 devnull if(convM2Su(buf, n, &f, s->dotu) != n){
71 2277c5d7 2004-03-21 devnull free(buf);
72 2277c5d7 2004-03-21 devnull return nil;
73 2277c5d7 2004-03-21 devnull }
74 2277c5d7 2004-03-21 devnull
75 2277c5d7 2004-03-21 devnull if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */
76 2277c5d7 2004-03-21 devnull r = emalloc9p(sizeof *r);
77 2277c5d7 2004-03-21 devnull incref(&r->ref);
78 2277c5d7 2004-03-21 devnull r->tag = f.tag;
79 2277c5d7 2004-03-21 devnull r->ifcall = f;
80 2277c5d7 2004-03-21 devnull r->error = Eduptag;
81 2277c5d7 2004-03-21 devnull r->buf = buf;
82 2277c5d7 2004-03-21 devnull r->responded = 0;
83 2277c5d7 2004-03-21 devnull r->type = 0;
84 2277c5d7 2004-03-21 devnull r->srv = s;
85 2277c5d7 2004-03-21 devnull r->pool = nil;
86 2277c5d7 2004-03-21 devnull if(chatty9p)
87 2277c5d7 2004-03-21 devnull fprint(2, "<-%d- %F: dup tag\n", s->infd, &f);
88 2277c5d7 2004-03-21 devnull return r;
89 2277c5d7 2004-03-21 devnull }
90 2277c5d7 2004-03-21 devnull
91 2277c5d7 2004-03-21 devnull r->srv = s;
92 2277c5d7 2004-03-21 devnull r->responded = 0;
93 2277c5d7 2004-03-21 devnull r->buf = buf;
94 2277c5d7 2004-03-21 devnull r->ifcall = f;
95 2277c5d7 2004-03-21 devnull memset(&r->ofcall, 0, sizeof r->ofcall);
96 2277c5d7 2004-03-21 devnull r->type = r->ifcall.type;
97 2277c5d7 2004-03-21 devnull
98 2277c5d7 2004-03-21 devnull if(chatty9p)
99 2277c5d7 2004-03-21 devnull if(r->error)
100 2277c5d7 2004-03-21 devnull fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error);
101 2277c5d7 2004-03-21 devnull else
102 2277c5d7 2004-03-21 devnull fprint(2, "<-%d- %F\n", s->infd, &r->ifcall);
103 2277c5d7 2004-03-21 devnull
104 2277c5d7 2004-03-21 devnull return r;
105 2277c5d7 2004-03-21 devnull }
106 2277c5d7 2004-03-21 devnull
107 2277c5d7 2004-03-21 devnull static void
108 2277c5d7 2004-03-21 devnull filewalk(Req *r)
109 2277c5d7 2004-03-21 devnull {
110 2277c5d7 2004-03-21 devnull int i;
111 2277c5d7 2004-03-21 devnull File *f;
112 2277c5d7 2004-03-21 devnull
113 2277c5d7 2004-03-21 devnull f = r->fid->file;
114 2277c5d7 2004-03-21 devnull assert(f != nil);
115 2277c5d7 2004-03-21 devnull
116 2277c5d7 2004-03-21 devnull incref(&f->ref);
117 2277c5d7 2004-03-21 devnull for(i=0; i<r->ifcall.nwname; i++)
118 2277c5d7 2004-03-21 devnull if(f = walkfile(f, r->ifcall.wname[i]))
119 2277c5d7 2004-03-21 devnull r->ofcall.wqid[i] = f->dir.qid;
120 2277c5d7 2004-03-21 devnull else
121 2277c5d7 2004-03-21 devnull break;
122 2277c5d7 2004-03-21 devnull
123 2277c5d7 2004-03-21 devnull r->ofcall.nwqid = i;
124 2277c5d7 2004-03-21 devnull if(f){
125 2277c5d7 2004-03-21 devnull r->newfid->file = f;
126 2277c5d7 2004-03-21 devnull r->newfid->qid = r->newfid->file->dir.qid;
127 2277c5d7 2004-03-21 devnull }
128 2277c5d7 2004-03-21 devnull respond(r, nil);
129 2277c5d7 2004-03-21 devnull }
130 2277c5d7 2004-03-21 devnull
131 2277c5d7 2004-03-21 devnull void
132 2277c5d7 2004-03-21 devnull walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg)
133 2277c5d7 2004-03-21 devnull {
134 2277c5d7 2004-03-21 devnull int i;
135 2277c5d7 2004-03-21 devnull char *e;
136 2277c5d7 2004-03-21 devnull
137 2277c5d7 2004-03-21 devnull if(r->fid == r->newfid && r->ifcall.nwname > 1){
138 2277c5d7 2004-03-21 devnull respond(r, "lib9p: unused documented feature not implemented");
139 2277c5d7 2004-03-21 devnull return;
140 2277c5d7 2004-03-21 devnull }
141 2277c5d7 2004-03-21 devnull
142 2277c5d7 2004-03-21 devnull if(r->fid != r->newfid){
143 2277c5d7 2004-03-21 devnull r->newfid->qid = r->fid->qid;
144 2277c5d7 2004-03-21 devnull if(clone && (e = clone(r->fid, r->newfid, arg))){
145 2277c5d7 2004-03-21 devnull respond(r, e);
146 2277c5d7 2004-03-21 devnull return;
147 2277c5d7 2004-03-21 devnull }
148 2277c5d7 2004-03-21 devnull }
149 2277c5d7 2004-03-21 devnull
150 2277c5d7 2004-03-21 devnull e = nil;
151 2277c5d7 2004-03-21 devnull for(i=0; i<r->ifcall.nwname; i++){
152 2277c5d7 2004-03-21 devnull if(e = walk1(r->newfid, r->ifcall.wname[i], arg))
153 2277c5d7 2004-03-21 devnull break;
154 2277c5d7 2004-03-21 devnull r->ofcall.wqid[i] = r->newfid->qid;
155 2277c5d7 2004-03-21 devnull }
156 2277c5d7 2004-03-21 devnull
157 2277c5d7 2004-03-21 devnull r->ofcall.nwqid = i;
158 2277c5d7 2004-03-21 devnull if(e && i==0)
159 2277c5d7 2004-03-21 devnull respond(r, e);
160 2277c5d7 2004-03-21 devnull else
161 2277c5d7 2004-03-21 devnull respond(r, nil);
162 2277c5d7 2004-03-21 devnull }
163 2277c5d7 2004-03-21 devnull
164 2277c5d7 2004-03-21 devnull static void
165 2277c5d7 2004-03-21 devnull sversion(Srv *srv, Req *r)
166 2277c5d7 2004-03-21 devnull {
167 2277c5d7 2004-03-21 devnull USED(srv);
168 2277c5d7 2004-03-21 devnull
169 2277c5d7 2004-03-21 devnull if(strncmp(r->ifcall.version, "9P", 2) != 0){
170 2277c5d7 2004-03-21 devnull r->ofcall.version = "unknown";
171 2277c5d7 2004-03-21 devnull respond(r, nil);
172 2277c5d7 2004-03-21 devnull return;
173 2277c5d7 2004-03-21 devnull }
174 2277c5d7 2004-03-21 devnull
175 90c892d8 2006-01-27 devnull if(strncmp(r->ifcall.version, "9P2000.u", 8) == 0){
176 90c892d8 2006-01-27 devnull r->ofcall.version = "9P2000.u";
177 90c892d8 2006-01-27 devnull srv->dotu = 1;
178 90c892d8 2006-01-27 devnull }else{
179 90c892d8 2006-01-27 devnull r->ofcall.version = "9P2000";
180 90c892d8 2006-01-27 devnull srv->dotu = 0;
181 90c892d8 2006-01-27 devnull }
182 2277c5d7 2004-03-21 devnull r->ofcall.msize = r->ifcall.msize;
183 2277c5d7 2004-03-21 devnull respond(r, nil);
184 2277c5d7 2004-03-21 devnull }
185 2277c5d7 2004-03-21 devnull static void
186 2277c5d7 2004-03-21 devnull rversion(Req *r, char *error)
187 2277c5d7 2004-03-21 devnull {
188 2277c5d7 2004-03-21 devnull assert(error == nil);
189 2277c5d7 2004-03-21 devnull changemsize(r->srv, r->ofcall.msize);
190 2277c5d7 2004-03-21 devnull }
191 2277c5d7 2004-03-21 devnull
192 2277c5d7 2004-03-21 devnull static void
193 2277c5d7 2004-03-21 devnull sauth(Srv *srv, Req *r)
194 2277c5d7 2004-03-21 devnull {
195 2277c5d7 2004-03-21 devnull char e[ERRMAX];
196 2277c5d7 2004-03-21 devnull
197 2277c5d7 2004-03-21 devnull if((r->afid = allocfid(srv->fpool, r->ifcall.afid)) == nil){
198 2277c5d7 2004-03-21 devnull respond(r, Edupfid);
199 2277c5d7 2004-03-21 devnull return;
200 2277c5d7 2004-03-21 devnull }
201 2277c5d7 2004-03-21 devnull if(srv->auth)
202 2277c5d7 2004-03-21 devnull srv->auth(r);
203 2277c5d7 2004-03-21 devnull else{
204 2277c5d7 2004-03-21 devnull snprint(e, sizeof e, "%s: authentication not required", argv0);
205 2277c5d7 2004-03-21 devnull respond(r, e);
206 2277c5d7 2004-03-21 devnull }
207 2277c5d7 2004-03-21 devnull }
208 2277c5d7 2004-03-21 devnull static void
209 2277c5d7 2004-03-21 devnull rauth(Req *r, char *error)
210 2277c5d7 2004-03-21 devnull {
211 2277c5d7 2004-03-21 devnull if(error && r->afid)
212 2277c5d7 2004-03-21 devnull closefid(removefid(r->srv->fpool, r->afid->fid));
213 2277c5d7 2004-03-21 devnull }
214 2277c5d7 2004-03-21 devnull
215 2277c5d7 2004-03-21 devnull static void
216 2277c5d7 2004-03-21 devnull sattach(Srv *srv, Req *r)
217 2277c5d7 2004-03-21 devnull {
218 2277c5d7 2004-03-21 devnull if((r->fid = allocfid(srv->fpool, r->ifcall.fid)) == nil){
219 2277c5d7 2004-03-21 devnull respond(r, Edupfid);
220 2277c5d7 2004-03-21 devnull return;
221 2277c5d7 2004-03-21 devnull }
222 2277c5d7 2004-03-21 devnull r->afid = nil;
223 2277c5d7 2004-03-21 devnull if(r->ifcall.afid != NOFID && (r->afid = lookupfid(srv->fpool, r->ifcall.afid)) == nil){
224 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
225 2277c5d7 2004-03-21 devnull return;
226 2277c5d7 2004-03-21 devnull }
227 2277c5d7 2004-03-21 devnull r->fid->uid = estrdup9p(r->ifcall.uname);
228 2277c5d7 2004-03-21 devnull if(srv->tree){
229 2277c5d7 2004-03-21 devnull r->fid->file = srv->tree->root;
230 2277c5d7 2004-03-21 devnull /* BUG? incref(r->fid->file) ??? */
231 2277c5d7 2004-03-21 devnull r->ofcall.qid = r->fid->file->dir.qid;
232 2277c5d7 2004-03-21 devnull r->fid->qid = r->ofcall.qid;
233 2277c5d7 2004-03-21 devnull }
234 2277c5d7 2004-03-21 devnull if(srv->attach)
235 2277c5d7 2004-03-21 devnull srv->attach(r);
236 2277c5d7 2004-03-21 devnull else
237 2277c5d7 2004-03-21 devnull respond(r, nil);
238 2277c5d7 2004-03-21 devnull return;
239 2277c5d7 2004-03-21 devnull }
240 2277c5d7 2004-03-21 devnull static void
241 2277c5d7 2004-03-21 devnull rattach(Req *r, char *error)
242 2277c5d7 2004-03-21 devnull {
243 2277c5d7 2004-03-21 devnull if(error && r->fid)
244 2277c5d7 2004-03-21 devnull closefid(removefid(r->srv->fpool, r->fid->fid));
245 2277c5d7 2004-03-21 devnull }
246 2277c5d7 2004-03-21 devnull
247 2277c5d7 2004-03-21 devnull static void
248 2277c5d7 2004-03-21 devnull sflush(Srv *srv, Req *r)
249 2277c5d7 2004-03-21 devnull {
250 2277c5d7 2004-03-21 devnull r->oldreq = lookupreq(srv->rpool, r->ifcall.oldtag);
251 2277c5d7 2004-03-21 devnull if(r->oldreq == nil || r->oldreq == r)
252 2277c5d7 2004-03-21 devnull respond(r, nil);
253 2277c5d7 2004-03-21 devnull else if(srv->flush)
254 2277c5d7 2004-03-21 devnull srv->flush(r);
255 2277c5d7 2004-03-21 devnull else
256 2277c5d7 2004-03-21 devnull respond(r, nil);
257 2277c5d7 2004-03-21 devnull }
258 2277c5d7 2004-03-21 devnull static int
259 2277c5d7 2004-03-21 devnull rflush(Req *r, char *error)
260 2277c5d7 2004-03-21 devnull {
261 2277c5d7 2004-03-21 devnull Req *or;
262 2277c5d7 2004-03-21 devnull
263 2277c5d7 2004-03-21 devnull assert(error == nil);
264 2277c5d7 2004-03-21 devnull or = r->oldreq;
265 2277c5d7 2004-03-21 devnull if(or){
266 2277c5d7 2004-03-21 devnull qlock(&or->lk);
267 2277c5d7 2004-03-21 devnull if(or->responded == 0){
268 2277c5d7 2004-03-21 devnull or->flush = erealloc9p(or->flush, (or->nflush+1)*sizeof(or->flush[0]));
269 2277c5d7 2004-03-21 devnull or->flush[or->nflush++] = r;
270 2277c5d7 2004-03-21 devnull qunlock(&or->lk);
271 2277c5d7 2004-03-21 devnull return -1; /* delay response until or is responded */
272 2277c5d7 2004-03-21 devnull }
273 2277c5d7 2004-03-21 devnull qunlock(&or->lk);
274 2277c5d7 2004-03-21 devnull closereq(or);
275 2277c5d7 2004-03-21 devnull }
276 2277c5d7 2004-03-21 devnull r->oldreq = nil;
277 2277c5d7 2004-03-21 devnull return 0;
278 2277c5d7 2004-03-21 devnull }
279 2277c5d7 2004-03-21 devnull
280 2277c5d7 2004-03-21 devnull static char*
281 2277c5d7 2004-03-21 devnull oldwalk1(Fid *fid, char *name, void *arg)
282 2277c5d7 2004-03-21 devnull {
283 2277c5d7 2004-03-21 devnull char *e;
284 2277c5d7 2004-03-21 devnull Qid qid;
285 2277c5d7 2004-03-21 devnull Srv *srv;
286 2277c5d7 2004-03-21 devnull
287 2277c5d7 2004-03-21 devnull srv = arg;
288 2277c5d7 2004-03-21 devnull e = srv->walk1(fid, name, &qid);
289 2277c5d7 2004-03-21 devnull if(e)
290 2277c5d7 2004-03-21 devnull return e;
291 2277c5d7 2004-03-21 devnull fid->qid = qid;
292 2277c5d7 2004-03-21 devnull return nil;
293 2277c5d7 2004-03-21 devnull }
294 2277c5d7 2004-03-21 devnull
295 2277c5d7 2004-03-21 devnull static char*
296 2277c5d7 2004-03-21 devnull oldclone(Fid *fid, Fid *newfid, void *arg)
297 2277c5d7 2004-03-21 devnull {
298 2277c5d7 2004-03-21 devnull Srv *srv;
299 2277c5d7 2004-03-21 devnull
300 2277c5d7 2004-03-21 devnull srv = arg;
301 2277c5d7 2004-03-21 devnull if(srv->clone == nil)
302 2277c5d7 2004-03-21 devnull return nil;
303 2277c5d7 2004-03-21 devnull return srv->clone(fid, newfid);
304 2277c5d7 2004-03-21 devnull }
305 2277c5d7 2004-03-21 devnull
306 2277c5d7 2004-03-21 devnull static void
307 2277c5d7 2004-03-21 devnull swalk(Srv *srv, Req *r)
308 2277c5d7 2004-03-21 devnull {
309 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
310 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
311 2277c5d7 2004-03-21 devnull return;
312 2277c5d7 2004-03-21 devnull }
313 2277c5d7 2004-03-21 devnull if(r->fid->omode != -1){
314 2277c5d7 2004-03-21 devnull respond(r, "cannot clone open fid");
315 2277c5d7 2004-03-21 devnull return;
316 2277c5d7 2004-03-21 devnull }
317 2277c5d7 2004-03-21 devnull if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)){
318 2277c5d7 2004-03-21 devnull respond(r, Ewalknodir);
319 2277c5d7 2004-03-21 devnull return;
320 2277c5d7 2004-03-21 devnull }
321 2277c5d7 2004-03-21 devnull if(r->ifcall.fid != r->ifcall.newfid){
322 2277c5d7 2004-03-21 devnull if((r->newfid = allocfid(srv->fpool, r->ifcall.newfid)) == nil){
323 2277c5d7 2004-03-21 devnull respond(r, Edupfid);
324 2277c5d7 2004-03-21 devnull return;
325 2277c5d7 2004-03-21 devnull }
326 2277c5d7 2004-03-21 devnull r->newfid->uid = estrdup9p(r->fid->uid);
327 2277c5d7 2004-03-21 devnull }else{
328 2277c5d7 2004-03-21 devnull incref(&r->fid->ref);
329 2277c5d7 2004-03-21 devnull r->newfid = r->fid;
330 2277c5d7 2004-03-21 devnull }
331 2277c5d7 2004-03-21 devnull if(r->fid->file){
332 2277c5d7 2004-03-21 devnull filewalk(r);
333 2277c5d7 2004-03-21 devnull }else if(srv->walk1)
334 2277c5d7 2004-03-21 devnull walkandclone(r, oldwalk1, oldclone, srv);
335 2277c5d7 2004-03-21 devnull else if(srv->walk)
336 2277c5d7 2004-03-21 devnull srv->walk(r);
337 2277c5d7 2004-03-21 devnull else
338 2277c5d7 2004-03-21 devnull sysfatal("no walk function, no file trees");
339 2277c5d7 2004-03-21 devnull }
340 2277c5d7 2004-03-21 devnull static void
341 2277c5d7 2004-03-21 devnull rwalk(Req *r, char *error)
342 2277c5d7 2004-03-21 devnull {
343 2277c5d7 2004-03-21 devnull if(error || r->ofcall.nwqid < r->ifcall.nwname){
344 2277c5d7 2004-03-21 devnull if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
345 2277c5d7 2004-03-21 devnull closefid(removefid(r->srv->fpool, r->newfid->fid));
346 2277c5d7 2004-03-21 devnull if (r->ofcall.nwqid==0){
347 2277c5d7 2004-03-21 devnull if(error==nil && r->ifcall.nwname!=0)
348 2277c5d7 2004-03-21 devnull r->error = Enotfound;
349 2277c5d7 2004-03-21 devnull }else
350 cbeb0b26 2006-04-01 devnull r->error = nil; /* No error on partial walks */
351 2277c5d7 2004-03-21 devnull }else{
352 2277c5d7 2004-03-21 devnull if(r->ofcall.nwqid == 0){
353 2277c5d7 2004-03-21 devnull /* Just a clone */
354 2277c5d7 2004-03-21 devnull r->newfid->qid = r->fid->qid;
355 2277c5d7 2004-03-21 devnull }else{
356 2277c5d7 2004-03-21 devnull /* if file trees are in use, filewalk took care of the rest */
357 2277c5d7 2004-03-21 devnull r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];
358 2277c5d7 2004-03-21 devnull }
359 2277c5d7 2004-03-21 devnull }
360 2277c5d7 2004-03-21 devnull }
361 2277c5d7 2004-03-21 devnull
362 2277c5d7 2004-03-21 devnull static void
363 2277c5d7 2004-03-21 devnull sopen(Srv *srv, Req *r)
364 2277c5d7 2004-03-21 devnull {
365 2277c5d7 2004-03-21 devnull int p;
366 2277c5d7 2004-03-21 devnull
367 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
368 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
369 2277c5d7 2004-03-21 devnull return;
370 2277c5d7 2004-03-21 devnull }
371 2277c5d7 2004-03-21 devnull if(r->fid->omode != -1){
372 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
373 2277c5d7 2004-03-21 devnull return;
374 2277c5d7 2004-03-21 devnull }
375 2277c5d7 2004-03-21 devnull if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != OREAD){
376 2277c5d7 2004-03-21 devnull respond(r, Eisdir);
377 2277c5d7 2004-03-21 devnull return;
378 2277c5d7 2004-03-21 devnull }
379 2277c5d7 2004-03-21 devnull r->ofcall.qid = r->fid->qid;
380 2277c5d7 2004-03-21 devnull switch(r->ifcall.mode&3){
381 2277c5d7 2004-03-21 devnull default:
382 2277c5d7 2004-03-21 devnull assert(0);
383 2277c5d7 2004-03-21 devnull case OREAD:
384 2277c5d7 2004-03-21 devnull p = AREAD;
385 2277c5d7 2004-03-21 devnull break;
386 2277c5d7 2004-03-21 devnull case OWRITE:
387 2277c5d7 2004-03-21 devnull p = AWRITE;
388 2277c5d7 2004-03-21 devnull break;
389 2277c5d7 2004-03-21 devnull case ORDWR:
390 2277c5d7 2004-03-21 devnull p = AREAD|AWRITE;
391 2277c5d7 2004-03-21 devnull break;
392 2277c5d7 2004-03-21 devnull case OEXEC:
393 2277c5d7 2004-03-21 devnull p = AEXEC;
394 2277c5d7 2004-03-21 devnull break;
395 2277c5d7 2004-03-21 devnull }
396 2277c5d7 2004-03-21 devnull if(r->ifcall.mode&OTRUNC)
397 2277c5d7 2004-03-21 devnull p |= AWRITE;
398 2277c5d7 2004-03-21 devnull if((r->fid->qid.type&QTDIR) && p!=AREAD){
399 2277c5d7 2004-03-21 devnull respond(r, Eperm);
400 2277c5d7 2004-03-21 devnull return;
401 2277c5d7 2004-03-21 devnull }
402 2277c5d7 2004-03-21 devnull if(r->fid->file){
403 2277c5d7 2004-03-21 devnull if(!hasperm(r->fid->file, r->fid->uid, p)){
404 2277c5d7 2004-03-21 devnull respond(r, Eperm);
405 2277c5d7 2004-03-21 devnull return;
406 2277c5d7 2004-03-21 devnull }
407 2277c5d7 2004-03-21 devnull /* BUG RACE */
408 2277c5d7 2004-03-21 devnull if((r->ifcall.mode&ORCLOSE)
409 2277c5d7 2004-03-21 devnull && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
410 2277c5d7 2004-03-21 devnull respond(r, Eperm);
411 2277c5d7 2004-03-21 devnull return;
412 2277c5d7 2004-03-21 devnull }
413 2277c5d7 2004-03-21 devnull r->ofcall.qid = r->fid->file->dir.qid;
414 2277c5d7 2004-03-21 devnull if((r->ofcall.qid.type&QTDIR)
415 2277c5d7 2004-03-21 devnull && (r->fid->rdir = opendirfile(r->fid->file)) == nil){
416 2277c5d7 2004-03-21 devnull respond(r, "opendirfile failed");
417 2277c5d7 2004-03-21 devnull return;
418 2277c5d7 2004-03-21 devnull }
419 2277c5d7 2004-03-21 devnull }
420 2277c5d7 2004-03-21 devnull if(srv->open)
421 2277c5d7 2004-03-21 devnull srv->open(r);
422 2277c5d7 2004-03-21 devnull else
423 2277c5d7 2004-03-21 devnull respond(r, nil);
424 2277c5d7 2004-03-21 devnull }
425 2277c5d7 2004-03-21 devnull static void
426 2277c5d7 2004-03-21 devnull ropen(Req *r, char *error)
427 2277c5d7 2004-03-21 devnull {
428 2277c5d7 2004-03-21 devnull char errbuf[ERRMAX];
429 2277c5d7 2004-03-21 devnull if(error)
430 2277c5d7 2004-03-21 devnull return;
431 2277c5d7 2004-03-21 devnull if(chatty9p){
432 2277c5d7 2004-03-21 devnull snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode);
433 2277c5d7 2004-03-21 devnull write(2, errbuf, strlen(errbuf));
434 2277c5d7 2004-03-21 devnull }
435 2277c5d7 2004-03-21 devnull r->fid->omode = r->ifcall.mode;
436 2277c5d7 2004-03-21 devnull r->fid->qid = r->ofcall.qid;
437 2277c5d7 2004-03-21 devnull if(r->ofcall.qid.type&QTDIR)
438 2277c5d7 2004-03-21 devnull r->fid->diroffset = 0;
439 2277c5d7 2004-03-21 devnull }
440 2277c5d7 2004-03-21 devnull
441 2277c5d7 2004-03-21 devnull static void
442 2277c5d7 2004-03-21 devnull screate(Srv *srv, Req *r)
443 2277c5d7 2004-03-21 devnull {
444 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil)
445 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
446 2277c5d7 2004-03-21 devnull else if(r->fid->omode != -1)
447 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
448 2277c5d7 2004-03-21 devnull else if(!(r->fid->qid.type&QTDIR))
449 2277c5d7 2004-03-21 devnull respond(r, Ecreatenondir);
450 2277c5d7 2004-03-21 devnull else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE))
451 2277c5d7 2004-03-21 devnull respond(r, Eperm);
452 2277c5d7 2004-03-21 devnull else if(srv->create)
453 2277c5d7 2004-03-21 devnull srv->create(r);
454 2277c5d7 2004-03-21 devnull else
455 2277c5d7 2004-03-21 devnull respond(r, Enocreate);
456 2277c5d7 2004-03-21 devnull }
457 2277c5d7 2004-03-21 devnull static void
458 2277c5d7 2004-03-21 devnull rcreate(Req *r, char *error)
459 2277c5d7 2004-03-21 devnull {
460 2277c5d7 2004-03-21 devnull if(error)
461 2277c5d7 2004-03-21 devnull return;
462 2277c5d7 2004-03-21 devnull r->fid->omode = r->ifcall.mode;
463 2277c5d7 2004-03-21 devnull r->fid->qid = r->ofcall.qid;
464 2277c5d7 2004-03-21 devnull }
465 2277c5d7 2004-03-21 devnull
466 2277c5d7 2004-03-21 devnull static void
467 2277c5d7 2004-03-21 devnull sread(Srv *srv, Req *r)
468 2277c5d7 2004-03-21 devnull {
469 2277c5d7 2004-03-21 devnull int o;
470 2277c5d7 2004-03-21 devnull
471 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
472 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
473 2277c5d7 2004-03-21 devnull return;
474 2277c5d7 2004-03-21 devnull }
475 2277c5d7 2004-03-21 devnull if(r->ifcall.count < 0){
476 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
477 2277c5d7 2004-03-21 devnull return;
478 2277c5d7 2004-03-21 devnull }
479 2277c5d7 2004-03-21 devnull if(r->ifcall.offset < 0
480 2277c5d7 2004-03-21 devnull || ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){
481 2277c5d7 2004-03-21 devnull respond(r, Ebadoffset);
482 2277c5d7 2004-03-21 devnull return;
483 2277c5d7 2004-03-21 devnull }
484 2277c5d7 2004-03-21 devnull
485 2277c5d7 2004-03-21 devnull if(r->ifcall.count > srv->msize - IOHDRSZ)
486 2277c5d7 2004-03-21 devnull r->ifcall.count = srv->msize - IOHDRSZ;
487 2277c5d7 2004-03-21 devnull r->rbuf = emalloc9p(r->ifcall.count);
488 2277c5d7 2004-03-21 devnull r->ofcall.data = r->rbuf;
489 2277c5d7 2004-03-21 devnull o = r->fid->omode & 3;
490 2277c5d7 2004-03-21 devnull if(o != OREAD && o != ORDWR && o != OEXEC){
491 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
492 2277c5d7 2004-03-21 devnull return;
493 2277c5d7 2004-03-21 devnull }
494 2277c5d7 2004-03-21 devnull if((r->fid->qid.type&QTDIR) && r->fid->file){
495 2277c5d7 2004-03-21 devnull r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count);
496 2277c5d7 2004-03-21 devnull respond(r, nil);
497 2277c5d7 2004-03-21 devnull return;
498 2277c5d7 2004-03-21 devnull }
499 2277c5d7 2004-03-21 devnull if(srv->read)
500 2277c5d7 2004-03-21 devnull srv->read(r);
501 2277c5d7 2004-03-21 devnull else
502 2277c5d7 2004-03-21 devnull respond(r, "no srv->read");
503 2277c5d7 2004-03-21 devnull }
504 2277c5d7 2004-03-21 devnull static void
505 2277c5d7 2004-03-21 devnull rread(Req *r, char *error)
506 2277c5d7 2004-03-21 devnull {
507 2277c5d7 2004-03-21 devnull if(error==nil && (r->fid->qid.type&QTDIR))
508 2277c5d7 2004-03-21 devnull r->fid->diroffset += r->ofcall.count;
509 2277c5d7 2004-03-21 devnull }
510 2277c5d7 2004-03-21 devnull
511 2277c5d7 2004-03-21 devnull static void
512 2277c5d7 2004-03-21 devnull swrite(Srv *srv, Req *r)
513 2277c5d7 2004-03-21 devnull {
514 2277c5d7 2004-03-21 devnull int o;
515 2277c5d7 2004-03-21 devnull char e[ERRMAX];
516 2277c5d7 2004-03-21 devnull
517 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
518 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
519 2277c5d7 2004-03-21 devnull return;
520 2277c5d7 2004-03-21 devnull }
521 2277c5d7 2004-03-21 devnull if(r->ifcall.count < 0){
522 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
523 2277c5d7 2004-03-21 devnull return;
524 2277c5d7 2004-03-21 devnull }
525 2277c5d7 2004-03-21 devnull if(r->ifcall.offset < 0){
526 2277c5d7 2004-03-21 devnull respond(r, Ebotch);
527 2277c5d7 2004-03-21 devnull return;
528 2277c5d7 2004-03-21 devnull }
529 2277c5d7 2004-03-21 devnull if(r->ifcall.count > srv->msize - IOHDRSZ)
530 2277c5d7 2004-03-21 devnull r->ifcall.count = srv->msize - IOHDRSZ;
531 2277c5d7 2004-03-21 devnull o = r->fid->omode & 3;
532 2277c5d7 2004-03-21 devnull if(o != OWRITE && o != ORDWR){
533 2277c5d7 2004-03-21 devnull snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode);
534 2277c5d7 2004-03-21 devnull respond(r, e);
535 2277c5d7 2004-03-21 devnull return;
536 2277c5d7 2004-03-21 devnull }
537 943cb39d 2006-02-14 devnull if(srv->write){
538 943cb39d 2006-02-14 devnull r->ifcall.data[r->ifcall.count] = 0; /* enough room - see getreq */
539 2277c5d7 2004-03-21 devnull srv->write(r);
540 943cb39d 2006-02-14 devnull }else
541 2277c5d7 2004-03-21 devnull respond(r, "no srv->write");
542 2277c5d7 2004-03-21 devnull }
543 2277c5d7 2004-03-21 devnull static void
544 2277c5d7 2004-03-21 devnull rwrite(Req *r, char *error)
545 2277c5d7 2004-03-21 devnull {
546 2277c5d7 2004-03-21 devnull if(error)
547 2277c5d7 2004-03-21 devnull return;
548 2277c5d7 2004-03-21 devnull if(r->fid->file)
549 2277c5d7 2004-03-21 devnull r->fid->file->dir.qid.vers++;
550 2277c5d7 2004-03-21 devnull }
551 2277c5d7 2004-03-21 devnull
552 2277c5d7 2004-03-21 devnull static void
553 2277c5d7 2004-03-21 devnull sclunk(Srv *srv, Req *r)
554 2277c5d7 2004-03-21 devnull {
555 2277c5d7 2004-03-21 devnull if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil)
556 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
557 2277c5d7 2004-03-21 devnull else
558 2277c5d7 2004-03-21 devnull respond(r, nil);
559 2277c5d7 2004-03-21 devnull }
560 2277c5d7 2004-03-21 devnull static void
561 2277c5d7 2004-03-21 devnull rclunk(Req *r, char *msg)
562 2277c5d7 2004-03-21 devnull {
563 2277c5d7 2004-03-21 devnull USED(r);
564 2277c5d7 2004-03-21 devnull USED(msg);
565 2277c5d7 2004-03-21 devnull }
566 2277c5d7 2004-03-21 devnull
567 2277c5d7 2004-03-21 devnull static void
568 2277c5d7 2004-03-21 devnull sremove(Srv *srv, Req *r)
569 2277c5d7 2004-03-21 devnull {
570 2277c5d7 2004-03-21 devnull if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){
571 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
572 2277c5d7 2004-03-21 devnull return;
573 2277c5d7 2004-03-21 devnull }
574 2277c5d7 2004-03-21 devnull /* BUG RACE */
575 2277c5d7 2004-03-21 devnull if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
576 2277c5d7 2004-03-21 devnull respond(r, Eperm);
577 2277c5d7 2004-03-21 devnull return;
578 2277c5d7 2004-03-21 devnull }
579 2277c5d7 2004-03-21 devnull if(srv->remove)
580 2277c5d7 2004-03-21 devnull srv->remove(r);
581 2277c5d7 2004-03-21 devnull else
582 2277c5d7 2004-03-21 devnull respond(r, r->fid->file ? nil : Enoremove);
583 2277c5d7 2004-03-21 devnull }
584 2277c5d7 2004-03-21 devnull static void
585 2277c5d7 2004-03-21 devnull rremove(Req *r, char *error, char *errbuf)
586 2277c5d7 2004-03-21 devnull {
587 2277c5d7 2004-03-21 devnull if(error)
588 2277c5d7 2004-03-21 devnull return;
589 2277c5d7 2004-03-21 devnull if(r->fid->file){
590 2277c5d7 2004-03-21 devnull if(removefile(r->fid->file) < 0){
591 2277c5d7 2004-03-21 devnull snprint(errbuf, ERRMAX, "remove %s: %r",
592 2277c5d7 2004-03-21 devnull r->fid->file->dir.name);
593 2277c5d7 2004-03-21 devnull r->error = errbuf;
594 2277c5d7 2004-03-21 devnull }
595 2277c5d7 2004-03-21 devnull r->fid->file = nil;
596 2277c5d7 2004-03-21 devnull }
597 2277c5d7 2004-03-21 devnull }
598 2277c5d7 2004-03-21 devnull
599 2277c5d7 2004-03-21 devnull static void
600 2277c5d7 2004-03-21 devnull sstat(Srv *srv, Req *r)
601 2277c5d7 2004-03-21 devnull {
602 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
603 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
604 2277c5d7 2004-03-21 devnull return;
605 2277c5d7 2004-03-21 devnull }
606 2277c5d7 2004-03-21 devnull if(r->fid->file){
607 2277c5d7 2004-03-21 devnull r->d = r->fid->file->dir;
608 2277c5d7 2004-03-21 devnull if(r->d.name)
609 2277c5d7 2004-03-21 devnull r->d.name = estrdup9p(r->d.name);
610 2277c5d7 2004-03-21 devnull if(r->d.uid)
611 2277c5d7 2004-03-21 devnull r->d.uid = estrdup9p(r->d.uid);
612 2277c5d7 2004-03-21 devnull if(r->d.gid)
613 2277c5d7 2004-03-21 devnull r->d.gid = estrdup9p(r->d.gid);
614 2277c5d7 2004-03-21 devnull if(r->d.muid)
615 2277c5d7 2004-03-21 devnull r->d.muid = estrdup9p(r->d.muid);
616 2277c5d7 2004-03-21 devnull }
617 2277c5d7 2004-03-21 devnull if(srv->stat)
618 2277c5d7 2004-03-21 devnull srv->stat(r);
619 2277c5d7 2004-03-21 devnull else if(r->fid->file)
620 2277c5d7 2004-03-21 devnull respond(r, nil);
621 2277c5d7 2004-03-21 devnull else
622 2277c5d7 2004-03-21 devnull respond(r, Enostat);
623 2277c5d7 2004-03-21 devnull }
624 2277c5d7 2004-03-21 devnull static void
625 2277c5d7 2004-03-21 devnull rstat(Req *r, char *error)
626 2277c5d7 2004-03-21 devnull {
627 2277c5d7 2004-03-21 devnull int n;
628 2277c5d7 2004-03-21 devnull uchar *statbuf;
629 2277c5d7 2004-03-21 devnull uchar tmp[BIT16SZ];
630 2277c5d7 2004-03-21 devnull
631 2277c5d7 2004-03-21 devnull if(error)
632 2277c5d7 2004-03-21 devnull return;
633 90c892d8 2006-01-27 devnull if(convD2Mu(&r->d, tmp, BIT16SZ, r->srv->dotu) != BIT16SZ){
634 90c892d8 2006-01-27 devnull r->error = "convD2Mu(_,_,BIT16SZ,_) did not return BIT16SZ";
635 2277c5d7 2004-03-21 devnull return;
636 2277c5d7 2004-03-21 devnull }
637 2277c5d7 2004-03-21 devnull n = GBIT16(tmp)+BIT16SZ;
638 2277c5d7 2004-03-21 devnull statbuf = emalloc9p(n);
639 2277c5d7 2004-03-21 devnull if(statbuf == nil){
640 2277c5d7 2004-03-21 devnull r->error = "out of memory";
641 2277c5d7 2004-03-21 devnull return;
642 2277c5d7 2004-03-21 devnull }
643 90c892d8 2006-01-27 devnull r->ofcall.nstat = convD2Mu(&r->d, statbuf, n, r->srv->dotu);
644 2277c5d7 2004-03-21 devnull r->ofcall.stat = statbuf; /* freed in closereq */
645 2277c5d7 2004-03-21 devnull if(r->ofcall.nstat <= BIT16SZ){
646 90c892d8 2006-01-27 devnull r->error = "convD2Mu fails";
647 2277c5d7 2004-03-21 devnull free(statbuf);
648 2277c5d7 2004-03-21 devnull return;
649 2277c5d7 2004-03-21 devnull }
650 2277c5d7 2004-03-21 devnull }
651 2277c5d7 2004-03-21 devnull
652 2277c5d7 2004-03-21 devnull static void
653 2277c5d7 2004-03-21 devnull swstat(Srv *srv, Req *r)
654 2277c5d7 2004-03-21 devnull {
655 2277c5d7 2004-03-21 devnull if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
656 2277c5d7 2004-03-21 devnull respond(r, Eunknownfid);
657 2277c5d7 2004-03-21 devnull return;
658 2277c5d7 2004-03-21 devnull }
659 2277c5d7 2004-03-21 devnull if(srv->wstat == nil){
660 2277c5d7 2004-03-21 devnull respond(r, Enowstat);
661 2277c5d7 2004-03-21 devnull return;
662 2277c5d7 2004-03-21 devnull }
663 90c892d8 2006-01-27 devnull if(convM2Du(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat, srv->dotu) != r->ifcall.nstat){
664 2277c5d7 2004-03-21 devnull respond(r, Ebaddir);
665 2277c5d7 2004-03-21 devnull return;
666 2277c5d7 2004-03-21 devnull }
667 2277c5d7 2004-03-21 devnull if((ushort)~r->d.type){
668 2277c5d7 2004-03-21 devnull respond(r, "wstat -- attempt to change type");
669 2277c5d7 2004-03-21 devnull return;
670 2277c5d7 2004-03-21 devnull }
671 2277c5d7 2004-03-21 devnull if((uint)~r->d.dev){
672 2277c5d7 2004-03-21 devnull respond(r, "wstat -- attempt to change dev");
673 2277c5d7 2004-03-21 devnull return;
674 2277c5d7 2004-03-21 devnull }
675 2277c5d7 2004-03-21 devnull if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){
676 2277c5d7 2004-03-21 devnull respond(r, "wstat -- attempt to change qid");
677 2277c5d7 2004-03-21 devnull return;
678 2277c5d7 2004-03-21 devnull }
679 2277c5d7 2004-03-21 devnull if(r->d.muid && r->d.muid[0]){
680 2277c5d7 2004-03-21 devnull respond(r, "wstat -- attempt to change muid");
681 2277c5d7 2004-03-21 devnull return;
682 2277c5d7 2004-03-21 devnull }
683 2277c5d7 2004-03-21 devnull if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){
684 2277c5d7 2004-03-21 devnull respond(r, "wstat -- attempt to change DMDIR bit");
685 2277c5d7 2004-03-21 devnull return;
686 2277c5d7 2004-03-21 devnull }
687 2277c5d7 2004-03-21 devnull srv->wstat(r);
688 2277c5d7 2004-03-21 devnull }
689 2277c5d7 2004-03-21 devnull static void
690 2277c5d7 2004-03-21 devnull rwstat(Req *r, char *msg)
691 2277c5d7 2004-03-21 devnull {
692 2277c5d7 2004-03-21 devnull USED(r);
693 2277c5d7 2004-03-21 devnull USED(msg);
694 2277c5d7 2004-03-21 devnull }
695 2277c5d7 2004-03-21 devnull
696 2277c5d7 2004-03-21 devnull void
697 2277c5d7 2004-03-21 devnull srv(Srv *srv)
698 2277c5d7 2004-03-21 devnull {
699 2277c5d7 2004-03-21 devnull Req *r;
700 2277c5d7 2004-03-21 devnull
701 2277c5d7 2004-03-21 devnull fmtinstall('D', dirfmt);
702 2277c5d7 2004-03-21 devnull fmtinstall('F', fcallfmt);
703 2277c5d7 2004-03-21 devnull
704 2277c5d7 2004-03-21 devnull if(srv->fpool == nil)
705 2277c5d7 2004-03-21 devnull srv->fpool = allocfidpool(srv->destroyfid);
706 2277c5d7 2004-03-21 devnull if(srv->rpool == nil)
707 2277c5d7 2004-03-21 devnull srv->rpool = allocreqpool(srv->destroyreq);
708 2277c5d7 2004-03-21 devnull if(srv->msize == 0)
709 2277c5d7 2004-03-21 devnull srv->msize = 8192+IOHDRSZ;
710 2277c5d7 2004-03-21 devnull
711 2277c5d7 2004-03-21 devnull changemsize(srv, srv->msize);
712 2277c5d7 2004-03-21 devnull
713 2277c5d7 2004-03-21 devnull srv->fpool->srv = srv;
714 2277c5d7 2004-03-21 devnull srv->rpool->srv = srv;
715 2277c5d7 2004-03-21 devnull
716 2aa7d303 2005-02-11 devnull if(srv->start)
717 2aa7d303 2005-02-11 devnull srv->start(srv);
718 2aa7d303 2005-02-11 devnull
719 2277c5d7 2004-03-21 devnull while(r = getreq(srv)){
720 2277c5d7 2004-03-21 devnull if(r->error){
721 2277c5d7 2004-03-21 devnull respond(r, r->error);
722 2277c5d7 2004-03-21 devnull continue;
723 2277c5d7 2004-03-21 devnull }
724 2277c5d7 2004-03-21 devnull switch(r->ifcall.type){
725 2277c5d7 2004-03-21 devnull default:
726 2277c5d7 2004-03-21 devnull respond(r, "unknown message");
727 2277c5d7 2004-03-21 devnull break;
728 2277c5d7 2004-03-21 devnull case Tversion: sversion(srv, r); break;
729 2277c5d7 2004-03-21 devnull case Tauth: sauth(srv, r); break;
730 2277c5d7 2004-03-21 devnull case Tattach: sattach(srv, r); break;
731 2277c5d7 2004-03-21 devnull case Tflush: sflush(srv, r); break;
732 2277c5d7 2004-03-21 devnull case Twalk: swalk(srv, r); break;
733 2277c5d7 2004-03-21 devnull case Topen: sopen(srv, r); break;
734 2277c5d7 2004-03-21 devnull case Tcreate: screate(srv, r); break;
735 2277c5d7 2004-03-21 devnull case Tread: sread(srv, r); break;
736 2277c5d7 2004-03-21 devnull case Twrite: swrite(srv, r); break;
737 2277c5d7 2004-03-21 devnull case Tclunk: sclunk(srv, r); break;
738 2277c5d7 2004-03-21 devnull case Tremove: sremove(srv, r); break;
739 2277c5d7 2004-03-21 devnull case Tstat: sstat(srv, r); break;
740 2277c5d7 2004-03-21 devnull case Twstat: swstat(srv, r); break;
741 2277c5d7 2004-03-21 devnull }
742 2277c5d7 2004-03-21 devnull }
743 2277c5d7 2004-03-21 devnull
744 2277c5d7 2004-03-21 devnull if(srv->end)
745 2277c5d7 2004-03-21 devnull srv->end(srv);
746 2277c5d7 2004-03-21 devnull }
747 2277c5d7 2004-03-21 devnull
748 2277c5d7 2004-03-21 devnull void
749 2277c5d7 2004-03-21 devnull respond(Req *r, char *error)
750 2277c5d7 2004-03-21 devnull {
751 2277c5d7 2004-03-21 devnull int i, m, n;
752 2277c5d7 2004-03-21 devnull char errbuf[ERRMAX];
753 2277c5d7 2004-03-21 devnull Srv *srv;
754 2277c5d7 2004-03-21 devnull
755 2277c5d7 2004-03-21 devnull srv = r->srv;
756 2277c5d7 2004-03-21 devnull assert(srv != nil);
757 2277c5d7 2004-03-21 devnull
758 39e5957a 2006-02-05 devnull if(r->responded){
759 39e5957a 2006-02-05 devnull assert(r->pool);
760 39e5957a 2006-02-05 devnull goto free;
761 39e5957a 2006-02-05 devnull }
762 39e5957a 2006-02-05 devnull
763 2277c5d7 2004-03-21 devnull assert(r->responded == 0);
764 2277c5d7 2004-03-21 devnull r->error = error;
765 2277c5d7 2004-03-21 devnull
766 2277c5d7 2004-03-21 devnull switch(r->ifcall.type){
767 2277c5d7 2004-03-21 devnull default:
768 2277c5d7 2004-03-21 devnull assert(0);
769 2277c5d7 2004-03-21 devnull /*
770 2277c5d7 2004-03-21 devnull * Flush is special. If the handler says so, we return
771 2277c5d7 2004-03-21 devnull * without further processing. Respond will be called
772 2277c5d7 2004-03-21 devnull * again once it is safe.
773 2277c5d7 2004-03-21 devnull */
774 2277c5d7 2004-03-21 devnull case Tflush:
775 2277c5d7 2004-03-21 devnull if(rflush(r, error)<0)
776 2277c5d7 2004-03-21 devnull return;
777 2277c5d7 2004-03-21 devnull break;
778 2277c5d7 2004-03-21 devnull case Tversion: rversion(r, error); break;
779 2277c5d7 2004-03-21 devnull case Tauth: rauth(r, error); break;
780 2277c5d7 2004-03-21 devnull case Tattach: rattach(r, error); break;
781 2277c5d7 2004-03-21 devnull case Twalk: rwalk(r, error); break;
782 2277c5d7 2004-03-21 devnull case Topen: ropen(r, error); break;
783 2277c5d7 2004-03-21 devnull case Tcreate: rcreate(r, error); break;
784 2277c5d7 2004-03-21 devnull case Tread: rread(r, error); break;
785 2277c5d7 2004-03-21 devnull case Twrite: rwrite(r, error); break;
786 2277c5d7 2004-03-21 devnull case Tclunk: rclunk(r, error); break;
787 2277c5d7 2004-03-21 devnull case Tremove: rremove(r, error, errbuf); break;
788 2277c5d7 2004-03-21 devnull case Tstat: rstat(r, error); break;
789 2277c5d7 2004-03-21 devnull case Twstat: rwstat(r, error); break;
790 2277c5d7 2004-03-21 devnull }
791 2277c5d7 2004-03-21 devnull
792 2277c5d7 2004-03-21 devnull r->ofcall.tag = r->ifcall.tag;
793 2277c5d7 2004-03-21 devnull r->ofcall.type = r->ifcall.type+1;
794 2277c5d7 2004-03-21 devnull if(r->error)
795 2277c5d7 2004-03-21 devnull setfcallerror(&r->ofcall, r->error);
796 2277c5d7 2004-03-21 devnull
797 2277c5d7 2004-03-21 devnull if(chatty9p)
798 2277c5d7 2004-03-21 devnull fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);
799 2277c5d7 2004-03-21 devnull
800 2277c5d7 2004-03-21 devnull qlock(&srv->wlock);
801 90c892d8 2006-01-27 devnull n = convS2Mu(&r->ofcall, srv->wbuf, srv->msize, srv->dotu);
802 2277c5d7 2004-03-21 devnull if(n <= 0){
803 2277c5d7 2004-03-21 devnull fprint(2, "n = %d %F\n", n, &r->ofcall);
804 2277c5d7 2004-03-21 devnull abort();
805 2277c5d7 2004-03-21 devnull }
806 2277c5d7 2004-03-21 devnull assert(n > 2);
807 aff51ee5 2006-03-21 devnull /*
808 aff51ee5 2006-03-21 devnull * There is a race here - we must remove the entry before
809 aff51ee5 2006-03-21 devnull * the write, so that if the client is very fast and reuses the
810 aff51ee5 2006-03-21 devnull * tag, the read loop won't think it is still in use.
811 aff51ee5 2006-03-21 devnull *
812 aff51ee5 2006-03-21 devnull * By removing the entry before the write, we open up a
813 aff51ee5 2006-03-21 devnull * race with incoming Tflush messages. Specifically, an
814 aff51ee5 2006-03-21 devnull * incoming Tflush might not see r even though it has not
815 aff51ee5 2006-03-21 devnull * yet been responded to. It would then send an Rflush
816 aff51ee5 2006-03-21 devnull * immediately, potentially before we do the write. This can't
817 aff51ee5 2006-03-21 devnull * happen because we already old srv->wlock, so nothing
818 aff51ee5 2006-03-21 devnull * is going out on the wire before this write.
819 aff51ee5 2006-03-21 devnull */
820 2277c5d7 2004-03-21 devnull if(r->pool) /* not a fake */
821 2277c5d7 2004-03-21 devnull closereq(removereq(r->pool, r->ifcall.tag));
822 aff51ee5 2006-03-21 devnull
823 aff51ee5 2006-03-21 devnull qlock(&r->lk);
824 aff51ee5 2006-03-21 devnull r->responded = 1;
825 aff51ee5 2006-03-21 devnull if(r->pool)
826 aff51ee5 2006-03-21 devnull if(r->ref.ref == 1+r->nflush)
827 aff51ee5 2006-03-21 devnull if(r->fid){
828 aff51ee5 2006-03-21 devnull /*
829 aff51ee5 2006-03-21 devnull * There are no references other than in our r->flush array,
830 aff51ee5 2006-03-21 devnull * so no one else should be accessing r concurrently.
831 aff51ee5 2006-03-21 devnull * Close the fid now, before responding to the message.
832 aff51ee5 2006-03-21 devnull *
833 aff51ee5 2006-03-21 devnull * If the client is behaving (there are no outstanding T-messages
834 aff51ee5 2006-03-21 devnull * that reference r->fid) and the message is a Tclunk or Tremove,
835 aff51ee5 2006-03-21 devnull * then this closefid will call destroyfid.
836 aff51ee5 2006-03-21 devnull *
837 aff51ee5 2006-03-21 devnull * This means destroyfid can't piddle around
838 aff51ee5 2006-03-21 devnull * indefinitely (we're holding srv->wlock!), but it provides
839 aff51ee5 2006-03-21 devnull * for tighter semantics as to when destroyfid is called.
840 aff51ee5 2006-03-21 devnull *
841 aff51ee5 2006-03-21 devnull * LANL has observed cases where waiting until after the write
842 aff51ee5 2006-03-21 devnull * can delay a closefid on a Twrite for many 9P transactions,
843 aff51ee5 2006-03-21 devnull * so that a handful of transactions can happen including a Tclunk
844 aff51ee5 2006-03-21 devnull * and a Topen, and the original fid will still not be destroyed.
845 aff51ee5 2006-03-21 devnull */
846 aff51ee5 2006-03-21 devnull closefid(r->fid);
847 aff51ee5 2006-03-21 devnull r->fid = nil;
848 aff51ee5 2006-03-21 devnull }
849 aff51ee5 2006-03-21 devnull qunlock(&r->lk);
850 2277c5d7 2004-03-21 devnull m = write(srv->outfd, srv->wbuf, n);
851 2277c5d7 2004-03-21 devnull if(m != n)
852 2277c5d7 2004-03-21 devnull sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);
853 2277c5d7 2004-03-21 devnull qunlock(&srv->wlock);
854 2277c5d7 2004-03-21 devnull
855 39e5957a 2006-02-05 devnull free:
856 2277c5d7 2004-03-21 devnull qlock(&r->lk); /* no one will add flushes now */
857 aff51ee5 2006-03-21 devnull
858 90a35657 2006-04-19 devnull for(i=0; i<r->nflush; i++){
859 90a35657 2006-04-19 devnull r->flush[i]->oldreq = nil; /* so it doesn't try to lock us! */
860 2277c5d7 2004-03-21 devnull respond(r->flush[i], nil);
861 90a35657 2006-04-19 devnull }
862 2277c5d7 2004-03-21 devnull free(r->flush);
863 39e5957a 2006-02-05 devnull r->nflush = 0;
864 39e5957a 2006-02-05 devnull r->flush = nil;
865 39e5957a 2006-02-05 devnull qunlock(&r->lk);
866 2277c5d7 2004-03-21 devnull
867 2277c5d7 2004-03-21 devnull if(r->pool)
868 2277c5d7 2004-03-21 devnull closereq(r);
869 2277c5d7 2004-03-21 devnull else
870 2277c5d7 2004-03-21 devnull free(r);
871 2277c5d7 2004-03-21 devnull }
872 2277c5d7 2004-03-21 devnull
873 2277c5d7 2004-03-21 devnull int
874 2277c5d7 2004-03-21 devnull postfd(char *name, int pfd)
875 2277c5d7 2004-03-21 devnull {
876 2277c5d7 2004-03-21 devnull int fd;
877 2277c5d7 2004-03-21 devnull char buf[80];
878 2277c5d7 2004-03-21 devnull
879 2277c5d7 2004-03-21 devnull snprint(buf, sizeof buf, "/srv/%s", name);
880 2277c5d7 2004-03-21 devnull if(chatty9p)
881 2277c5d7 2004-03-21 devnull fprint(2, "postfd %s\n", buf);
882 2277c5d7 2004-03-21 devnull fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600);
883 2277c5d7 2004-03-21 devnull if(fd < 0){
884 2277c5d7 2004-03-21 devnull if(chatty9p)
885 2277c5d7 2004-03-21 devnull fprint(2, "create fails: %r\n");
886 2277c5d7 2004-03-21 devnull return -1;
887 2277c5d7 2004-03-21 devnull }
888 2277c5d7 2004-03-21 devnull if(fprint(fd, "%d", pfd) < 0){
889 2277c5d7 2004-03-21 devnull if(chatty9p)
890 2277c5d7 2004-03-21 devnull fprint(2, "write fails: %r\n");
891 2277c5d7 2004-03-21 devnull close(fd);
892 2277c5d7 2004-03-21 devnull return -1;
893 2277c5d7 2004-03-21 devnull }
894 2277c5d7 2004-03-21 devnull if(chatty9p)
895 2277c5d7 2004-03-21 devnull fprint(2, "postfd successful\n");
896 2277c5d7 2004-03-21 devnull return 0;
897 2277c5d7 2004-03-21 devnull }
898 2277c5d7 2004-03-21 devnull