Blame


1 b8c14089 2003-11-23 devnull #include <u.h>
2 b8c14089 2003-11-23 devnull #include <libc.h>
3 b8c14089 2003-11-23 devnull #include <bio.h>
4 b8c14089 2003-11-23 devnull #include <regexp.h>
5 b8c14089 2003-11-23 devnull #include <thread.h>
6 b8c14089 2003-11-23 devnull #include <auth.h>
7 b8c14089 2003-11-23 devnull #include <fcall.h>
8 b8c14089 2003-11-23 devnull #include <plumb.h>
9 b8c14089 2003-11-23 devnull #include "plumber.h"
10 b8c14089 2003-11-23 devnull
11 b8c14089 2003-11-23 devnull enum
12 b8c14089 2003-11-23 devnull {
13 b8c14089 2003-11-23 devnull Stack = 8*1024
14 b8c14089 2003-11-23 devnull };
15 b8c14089 2003-11-23 devnull
16 b8c14089 2003-11-23 devnull typedef struct Dirtab Dirtab;
17 b8c14089 2003-11-23 devnull typedef struct Fid Fid;
18 b8c14089 2003-11-23 devnull typedef struct Holdq Holdq;
19 b8c14089 2003-11-23 devnull typedef struct Readreq Readreq;
20 b8c14089 2003-11-23 devnull typedef struct Sendreq Sendreq;
21 b8c14089 2003-11-23 devnull
22 b8c14089 2003-11-23 devnull struct Dirtab
23 b8c14089 2003-11-23 devnull {
24 b8c14089 2003-11-23 devnull char *name;
25 b8c14089 2003-11-23 devnull uchar type;
26 b8c14089 2003-11-23 devnull uint qid;
27 b8c14089 2003-11-23 devnull uint perm;
28 b8c14089 2003-11-23 devnull int nopen; /* #fids open on this port */
29 b8c14089 2003-11-23 devnull Fid *fopen;
30 b8c14089 2003-11-23 devnull Holdq *holdq;
31 b8c14089 2003-11-23 devnull Readreq *readq;
32 b8c14089 2003-11-23 devnull Sendreq *sendq;
33 b8c14089 2003-11-23 devnull };
34 b8c14089 2003-11-23 devnull
35 b8c14089 2003-11-23 devnull struct Fid
36 b8c14089 2003-11-23 devnull {
37 b8c14089 2003-11-23 devnull int fid;
38 b8c14089 2003-11-23 devnull int busy;
39 b8c14089 2003-11-23 devnull int open;
40 b8c14089 2003-11-23 devnull int mode;
41 b8c14089 2003-11-23 devnull Qid qid;
42 b8c14089 2003-11-23 devnull Dirtab *dir;
43 b8c14089 2003-11-23 devnull long offset; /* zeroed at beginning of each message, read or write */
44 b8c14089 2003-11-23 devnull char *writebuf; /* partial message written so far; offset tells how much */
45 b8c14089 2003-11-23 devnull Fid *next;
46 b8c14089 2003-11-23 devnull Fid *nextopen;
47 b8c14089 2003-11-23 devnull };
48 b8c14089 2003-11-23 devnull
49 b8c14089 2003-11-23 devnull struct Readreq
50 b8c14089 2003-11-23 devnull {
51 b8c14089 2003-11-23 devnull Fid *fid;
52 b8c14089 2003-11-23 devnull Fcall *fcall;
53 b8c14089 2003-11-23 devnull uchar *buf;
54 b8c14089 2003-11-23 devnull Readreq *next;
55 b8c14089 2003-11-23 devnull };
56 b8c14089 2003-11-23 devnull
57 b8c14089 2003-11-23 devnull struct Sendreq
58 b8c14089 2003-11-23 devnull {
59 b8c14089 2003-11-23 devnull int nfid; /* number of fids that should receive this message */
60 b8c14089 2003-11-23 devnull int nleft; /* number left that haven't received it */
61 b8c14089 2003-11-23 devnull Fid **fid; /* fid[nfid] */
62 b8c14089 2003-11-23 devnull Plumbmsg *msg;
63 b8c14089 2003-11-23 devnull char *pack; /* plumbpack()ed message */
64 b8c14089 2003-11-23 devnull int npack; /* length of pack */
65 b8c14089 2003-11-23 devnull Sendreq *next;
66 b8c14089 2003-11-23 devnull };
67 b8c14089 2003-11-23 devnull
68 b8c14089 2003-11-23 devnull struct Holdq
69 b8c14089 2003-11-23 devnull {
70 b8c14089 2003-11-23 devnull Plumbmsg *msg;
71 b8c14089 2003-11-23 devnull Holdq *next;
72 b8c14089 2003-11-23 devnull };
73 b8c14089 2003-11-23 devnull
74 b8c14089 2003-11-23 devnull struct /* needed because incref() doesn't return value */
75 b8c14089 2003-11-23 devnull {
76 b8c14089 2003-11-23 devnull Lock;
77 b8c14089 2003-11-23 devnull int ref;
78 b8c14089 2003-11-23 devnull } rulesref;
79 b8c14089 2003-11-23 devnull
80 b8c14089 2003-11-23 devnull enum
81 b8c14089 2003-11-23 devnull {
82 b8c14089 2003-11-23 devnull DEBUG = 0,
83 b8c14089 2003-11-23 devnull NDIR = 50,
84 b8c14089 2003-11-23 devnull Nhash = 16,
85 b8c14089 2003-11-23 devnull
86 b8c14089 2003-11-23 devnull Qdir = 0,
87 b8c14089 2003-11-23 devnull Qrules = 1,
88 b8c14089 2003-11-23 devnull Qsend = 2,
89 b8c14089 2003-11-23 devnull Qport = 3,
90 b8c14089 2003-11-23 devnull NQID = Qport
91 b8c14089 2003-11-23 devnull };
92 b8c14089 2003-11-23 devnull
93 b8c14089 2003-11-23 devnull static Dirtab dir[NDIR] =
94 b8c14089 2003-11-23 devnull {
95 b8c14089 2003-11-23 devnull { ".", QTDIR, Qdir, 0500|DMDIR },
96 b8c14089 2003-11-23 devnull { "rules", QTFILE, Qrules, 0600 },
97 b8c14089 2003-11-23 devnull { "send", QTFILE, Qsend, 0200 },
98 b8c14089 2003-11-23 devnull };
99 b8c14089 2003-11-23 devnull static int ndir = NQID;
100 b8c14089 2003-11-23 devnull
101 b8c14089 2003-11-23 devnull static int srvfd;
102 b8c14089 2003-11-23 devnull static int srvclosefd; /* rock for end of pipe to close */
103 b8c14089 2003-11-23 devnull static int clockfd;
104 b8c14089 2003-11-23 devnull static int clock;
105 b8c14089 2003-11-23 devnull static Fid *fids[Nhash];
106 b8c14089 2003-11-23 devnull static QLock readlock;
107 b8c14089 2003-11-23 devnull static QLock queue;
108 b8c14089 2003-11-23 devnull static char srvfile[128];
109 b8c14089 2003-11-23 devnull static int messagesize = 8192+IOHDRSZ; /* good start */
110 b8c14089 2003-11-23 devnull
111 b8c14089 2003-11-23 devnull static void fsysproc(void*);
112 b8c14089 2003-11-23 devnull static void fsysrespond(Fcall*, uchar*, char*);
113 b8c14089 2003-11-23 devnull static Fid* newfid(int);
114 b8c14089 2003-11-23 devnull
115 b8c14089 2003-11-23 devnull static Fcall* fsysflush(Fcall*, uchar*, Fid*);
116 b8c14089 2003-11-23 devnull static Fcall* fsysversion(Fcall*, uchar*, Fid*);
117 b8c14089 2003-11-23 devnull static Fcall* fsysauth(Fcall*, uchar*, Fid*);
118 b8c14089 2003-11-23 devnull static Fcall* fsysattach(Fcall*, uchar*, Fid*);
119 b8c14089 2003-11-23 devnull static Fcall* fsyswalk(Fcall*, uchar*, Fid*);
120 b8c14089 2003-11-23 devnull static Fcall* fsysopen(Fcall*, uchar*, Fid*);
121 b8c14089 2003-11-23 devnull static Fcall* fsyscreate(Fcall*, uchar*, Fid*);
122 b8c14089 2003-11-23 devnull static Fcall* fsysread(Fcall*, uchar*, Fid*);
123 b8c14089 2003-11-23 devnull static Fcall* fsyswrite(Fcall*, uchar*, Fid*);
124 b8c14089 2003-11-23 devnull static Fcall* fsysclunk(Fcall*, uchar*, Fid*);
125 b8c14089 2003-11-23 devnull static Fcall* fsysremove(Fcall*, uchar*, Fid*);
126 b8c14089 2003-11-23 devnull static Fcall* fsysstat(Fcall*, uchar*, Fid*);
127 b8c14089 2003-11-23 devnull static Fcall* fsyswstat(Fcall*, uchar*, Fid*);
128 b8c14089 2003-11-23 devnull
129 b8c14089 2003-11-23 devnull Fcall* (*fcall[Tmax])(Fcall*, uchar*, Fid*) =
130 b8c14089 2003-11-23 devnull {
131 b8c14089 2003-11-23 devnull [Tflush] = fsysflush,
132 b8c14089 2003-11-23 devnull [Tversion] = fsysversion,
133 b8c14089 2003-11-23 devnull [Tauth] = fsysauth,
134 b8c14089 2003-11-23 devnull [Tattach] = fsysattach,
135 b8c14089 2003-11-23 devnull [Twalk] = fsyswalk,
136 b8c14089 2003-11-23 devnull [Topen] = fsysopen,
137 b8c14089 2003-11-23 devnull [Tcreate] = fsyscreate,
138 b8c14089 2003-11-23 devnull [Tread] = fsysread,
139 b8c14089 2003-11-23 devnull [Twrite] = fsyswrite,
140 b8c14089 2003-11-23 devnull [Tclunk] = fsysclunk,
141 b8c14089 2003-11-23 devnull [Tremove]= fsysremove,
142 b8c14089 2003-11-23 devnull [Tstat] = fsysstat,
143 b8c14089 2003-11-23 devnull [Twstat] = fsyswstat,
144 b8c14089 2003-11-23 devnull };
145 b8c14089 2003-11-23 devnull
146 b8c14089 2003-11-23 devnull char Ebadfcall[] = "bad fcall type";
147 b8c14089 2003-11-23 devnull char Eperm[] = "permission denied";
148 b8c14089 2003-11-23 devnull char Enomem[] = "malloc failed for buffer";
149 b8c14089 2003-11-23 devnull char Enotdir[] = "not a directory";
150 b8c14089 2003-11-23 devnull char Enoexist[] = "plumb file does not exist";
151 b8c14089 2003-11-23 devnull char Eisdir[] = "file is a directory";
152 b8c14089 2003-11-23 devnull char Ebadmsg[] = "bad plumb message format";
153 b8c14089 2003-11-23 devnull char Enosuchport[] ="no such plumb port";
154 b8c14089 2003-11-23 devnull char Enoport[] = "couldn't find destination for message";
155 b8c14089 2003-11-23 devnull char Einuse[] = "file already open";
156 b8c14089 2003-11-23 devnull
157 b8c14089 2003-11-23 devnull /*
158 b8c14089 2003-11-23 devnull * Add new port. A no-op if port already exists or is the null string
159 b8c14089 2003-11-23 devnull */
160 b8c14089 2003-11-23 devnull void
161 b8c14089 2003-11-23 devnull addport(char *port)
162 b8c14089 2003-11-23 devnull {
163 b8c14089 2003-11-23 devnull int i;
164 b8c14089 2003-11-23 devnull
165 b8c14089 2003-11-23 devnull if(port == nil)
166 b8c14089 2003-11-23 devnull return;
167 b8c14089 2003-11-23 devnull for(i=NQID; i<ndir; i++)
168 b8c14089 2003-11-23 devnull if(strcmp(port, dir[i].name) == 0)
169 b8c14089 2003-11-23 devnull return;
170 b8c14089 2003-11-23 devnull if(i == NDIR){
171 b8c14089 2003-11-23 devnull fprint(2, "plumb: too many ports; max %d\n", NDIR);
172 b8c14089 2003-11-23 devnull return;
173 b8c14089 2003-11-23 devnull }
174 b8c14089 2003-11-23 devnull ndir++;
175 b8c14089 2003-11-23 devnull dir[i].name = estrdup(port);
176 b8c14089 2003-11-23 devnull dir[i].qid = i;
177 b8c14089 2003-11-23 devnull dir[i].perm = 0400;
178 b8c14089 2003-11-23 devnull nports++;
179 b8c14089 2003-11-23 devnull ports = erealloc(ports, nports*sizeof(char*));
180 b8c14089 2003-11-23 devnull ports[nports-1] = dir[i].name;
181 b8c14089 2003-11-23 devnull }
182 b8c14089 2003-11-23 devnull
183 b8c14089 2003-11-23 devnull static ulong
184 b8c14089 2003-11-23 devnull getclock(void)
185 b8c14089 2003-11-23 devnull {
186 b8c14089 2003-11-23 devnull char buf[32];
187 b8c14089 2003-11-23 devnull
188 b8c14089 2003-11-23 devnull seek(clockfd, 0, 0);
189 b8c14089 2003-11-23 devnull read(clockfd, buf, sizeof buf);
190 b8c14089 2003-11-23 devnull return atoi(buf);
191 b8c14089 2003-11-23 devnull }
192 b8c14089 2003-11-23 devnull
193 b8c14089 2003-11-23 devnull void
194 b8c14089 2003-11-23 devnull startfsys(void)
195 b8c14089 2003-11-23 devnull {
196 b8c14089 2003-11-23 devnull int p[2], fd;
197 b8c14089 2003-11-23 devnull
198 b8c14089 2003-11-23 devnull fmtinstall('F', fcallfmt);
199 b8c14089 2003-11-23 devnull clockfd = open("/dev/time", OREAD|OCEXEC);
200 b8c14089 2003-11-23 devnull clock = getclock();
201 b8c14089 2003-11-23 devnull if(pipe(p) < 0)
202 b8c14089 2003-11-23 devnull error("can't create pipe: %r");
203 b8c14089 2003-11-23 devnull /* 0 will be server end, 1 will be client end */
204 b8c14089 2003-11-23 devnull srvfd = p[0];
205 b8c14089 2003-11-23 devnull srvclosefd = p[1];
206 b8c14089 2003-11-23 devnull sprint(srvfile, "/srv/plumb.%s.%d", user, getpid());
207 b8c14089 2003-11-23 devnull if(putenv("plumbsrv", srvfile) < 0)
208 b8c14089 2003-11-23 devnull error("can't write $plumbsrv: %r");
209 b8c14089 2003-11-23 devnull fd = create(srvfile, OWRITE|OCEXEC|ORCLOSE, 0600);
210 b8c14089 2003-11-23 devnull if(fd < 0)
211 b8c14089 2003-11-23 devnull error("can't create /srv file: %r");
212 b8c14089 2003-11-23 devnull if(fprint(fd, "%d", p[1]) <= 0)
213 b8c14089 2003-11-23 devnull error("can't write /srv/file: %r");
214 b8c14089 2003-11-23 devnull /* leave fd open; ORCLOSE will take care of it */
215 b8c14089 2003-11-23 devnull
216 b8c14089 2003-11-23 devnull procrfork(fsysproc, nil, Stack, RFFDG);
217 b8c14089 2003-11-23 devnull
218 b8c14089 2003-11-23 devnull close(p[0]);
219 b8c14089 2003-11-23 devnull if(mount(p[1], -1, "/mnt/plumb", MREPL, "") < 0)
220 b8c14089 2003-11-23 devnull error("can't mount /mnt/plumb: %r");
221 b8c14089 2003-11-23 devnull close(p[1]);
222 b8c14089 2003-11-23 devnull }
223 b8c14089 2003-11-23 devnull
224 b8c14089 2003-11-23 devnull static void
225 b8c14089 2003-11-23 devnull fsysproc(void*)
226 b8c14089 2003-11-23 devnull {
227 b8c14089 2003-11-23 devnull int n;
228 b8c14089 2003-11-23 devnull Fcall *t;
229 b8c14089 2003-11-23 devnull Fid *f;
230 b8c14089 2003-11-23 devnull uchar *buf;
231 b8c14089 2003-11-23 devnull
232 b8c14089 2003-11-23 devnull close(srvclosefd);
233 b8c14089 2003-11-23 devnull srvclosefd = -1;
234 b8c14089 2003-11-23 devnull t = nil;
235 b8c14089 2003-11-23 devnull for(;;){
236 b8c14089 2003-11-23 devnull buf = malloc(messagesize); /* avoid memset of emalloc */
237 b8c14089 2003-11-23 devnull if(buf == nil)
238 b8c14089 2003-11-23 devnull error("malloc failed: %r");
239 b8c14089 2003-11-23 devnull qlock(&readlock);
240 b8c14089 2003-11-23 devnull n = read9pmsg(srvfd, buf, messagesize);
241 b8c14089 2003-11-23 devnull if(n <= 0){
242 b8c14089 2003-11-23 devnull if(n < 0)
243 b8c14089 2003-11-23 devnull error("i/o error on server channel");
244 b8c14089 2003-11-23 devnull threadexitsall("unmounted");
245 b8c14089 2003-11-23 devnull }
246 b8c14089 2003-11-23 devnull if(readlock.head == nil) /* no other processes waiting to read; start one */
247 b8c14089 2003-11-23 devnull proccreate(fsysproc, nil, Stack);
248 b8c14089 2003-11-23 devnull qunlock(&readlock);
249 b8c14089 2003-11-23 devnull if(t == nil)
250 b8c14089 2003-11-23 devnull t = emalloc(sizeof(Fcall));
251 b8c14089 2003-11-23 devnull if(convM2S(buf, n, t) != n)
252 b8c14089 2003-11-23 devnull error("convert error in convM2S");
253 b8c14089 2003-11-23 devnull if(DEBUG)
254 b8c14089 2003-11-23 devnull fprint(2, "<= %F\n", t);
255 b8c14089 2003-11-23 devnull if(fcall[t->type] == nil)
256 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Ebadfcall);
257 b8c14089 2003-11-23 devnull else{
258 b8c14089 2003-11-23 devnull if(t->type==Tversion || t->type==Tauth)
259 b8c14089 2003-11-23 devnull f = nil;
260 b8c14089 2003-11-23 devnull else
261 b8c14089 2003-11-23 devnull f = newfid(t->fid);
262 b8c14089 2003-11-23 devnull t = (*fcall[t->type])(t, buf, f);
263 b8c14089 2003-11-23 devnull }
264 b8c14089 2003-11-23 devnull }
265 b8c14089 2003-11-23 devnull }
266 b8c14089 2003-11-23 devnull
267 b8c14089 2003-11-23 devnull static void
268 b8c14089 2003-11-23 devnull fsysrespond(Fcall *t, uchar *buf, char *err)
269 b8c14089 2003-11-23 devnull {
270 b8c14089 2003-11-23 devnull int n;
271 b8c14089 2003-11-23 devnull
272 b8c14089 2003-11-23 devnull if(err){
273 b8c14089 2003-11-23 devnull t->type = Rerror;
274 b8c14089 2003-11-23 devnull t->ename = err;
275 b8c14089 2003-11-23 devnull }else
276 b8c14089 2003-11-23 devnull t->type++;
277 b8c14089 2003-11-23 devnull if(buf == nil)
278 b8c14089 2003-11-23 devnull buf = emalloc(messagesize);
279 b8c14089 2003-11-23 devnull n = convS2M(t, buf, messagesize);
280 b8c14089 2003-11-23 devnull if(n < 0)
281 b8c14089 2003-11-23 devnull error("convert error in convS2M");
282 b8c14089 2003-11-23 devnull if(write(srvfd, buf, n) != n)
283 b8c14089 2003-11-23 devnull error("write error in respond");
284 b8c14089 2003-11-23 devnull if(DEBUG)
285 b8c14089 2003-11-23 devnull fprint(2, "=> %F\n", t);
286 b8c14089 2003-11-23 devnull free(buf);
287 b8c14089 2003-11-23 devnull }
288 b8c14089 2003-11-23 devnull
289 b8c14089 2003-11-23 devnull static
290 b8c14089 2003-11-23 devnull Fid*
291 b8c14089 2003-11-23 devnull newfid(int fid)
292 b8c14089 2003-11-23 devnull {
293 b8c14089 2003-11-23 devnull Fid *f, *ff, **fh;
294 b8c14089 2003-11-23 devnull
295 b8c14089 2003-11-23 devnull qlock(&queue);
296 b8c14089 2003-11-23 devnull ff = nil;
297 b8c14089 2003-11-23 devnull fh = &fids[fid&(Nhash-1)];
298 b8c14089 2003-11-23 devnull for(f=*fh; f; f=f->next)
299 b8c14089 2003-11-23 devnull if(f->fid == fid)
300 b8c14089 2003-11-23 devnull goto Return;
301 b8c14089 2003-11-23 devnull else if(ff==nil && !f->busy)
302 b8c14089 2003-11-23 devnull ff = f;
303 b8c14089 2003-11-23 devnull if(ff){
304 b8c14089 2003-11-23 devnull ff->fid = fid;
305 b8c14089 2003-11-23 devnull f = ff;
306 b8c14089 2003-11-23 devnull goto Return;
307 b8c14089 2003-11-23 devnull }
308 b8c14089 2003-11-23 devnull f = emalloc(sizeof *f);
309 b8c14089 2003-11-23 devnull f->fid = fid;
310 b8c14089 2003-11-23 devnull f->next = *fh;
311 b8c14089 2003-11-23 devnull *fh = f;
312 b8c14089 2003-11-23 devnull Return:
313 b8c14089 2003-11-23 devnull qunlock(&queue);
314 b8c14089 2003-11-23 devnull return f;
315 b8c14089 2003-11-23 devnull }
316 b8c14089 2003-11-23 devnull
317 b8c14089 2003-11-23 devnull static uint
318 b8c14089 2003-11-23 devnull dostat(Dirtab *dir, uchar *buf, uint nbuf, uint clock)
319 b8c14089 2003-11-23 devnull {
320 b8c14089 2003-11-23 devnull Dir d;
321 b8c14089 2003-11-23 devnull
322 b8c14089 2003-11-23 devnull d.qid.type = dir->type;
323 b8c14089 2003-11-23 devnull d.qid.path = dir->qid;
324 b8c14089 2003-11-23 devnull d.qid.vers = 0;
325 b8c14089 2003-11-23 devnull d.mode = dir->perm;
326 b8c14089 2003-11-23 devnull d.length = 0; /* would be nice to do better */
327 b8c14089 2003-11-23 devnull d.name = dir->name;
328 b8c14089 2003-11-23 devnull d.uid = user;
329 b8c14089 2003-11-23 devnull d.gid = user;
330 b8c14089 2003-11-23 devnull d.muid = user;
331 b8c14089 2003-11-23 devnull d.atime = clock;
332 b8c14089 2003-11-23 devnull d.mtime = clock;
333 b8c14089 2003-11-23 devnull return convD2M(&d, buf, nbuf);
334 b8c14089 2003-11-23 devnull }
335 b8c14089 2003-11-23 devnull
336 b8c14089 2003-11-23 devnull static void
337 b8c14089 2003-11-23 devnull queuesend(Dirtab *d, Plumbmsg *m)
338 b8c14089 2003-11-23 devnull {
339 b8c14089 2003-11-23 devnull Sendreq *s, *t;
340 b8c14089 2003-11-23 devnull Fid *f;
341 b8c14089 2003-11-23 devnull int i;
342 b8c14089 2003-11-23 devnull
343 b8c14089 2003-11-23 devnull s = emalloc(sizeof(Sendreq));
344 b8c14089 2003-11-23 devnull s->nfid = d->nopen;
345 b8c14089 2003-11-23 devnull s->nleft = s->nfid;
346 b8c14089 2003-11-23 devnull s->fid = emalloc(s->nfid*sizeof(Fid*));
347 b8c14089 2003-11-23 devnull i = 0;
348 b8c14089 2003-11-23 devnull /* build array of fids open on this channel */
349 b8c14089 2003-11-23 devnull for(f=d->fopen; f!=nil; f=f->nextopen)
350 b8c14089 2003-11-23 devnull s->fid[i++] = f;
351 b8c14089 2003-11-23 devnull s->msg = m;
352 b8c14089 2003-11-23 devnull s->next = nil;
353 b8c14089 2003-11-23 devnull /* link to end of queue; drainqueue() searches in sender order so this implements a FIFO */
354 b8c14089 2003-11-23 devnull for(t=d->sendq; t!=nil; t=t->next)
355 b8c14089 2003-11-23 devnull if(t->next == nil)
356 b8c14089 2003-11-23 devnull break;
357 b8c14089 2003-11-23 devnull if(t == nil)
358 b8c14089 2003-11-23 devnull d->sendq = s;
359 b8c14089 2003-11-23 devnull else
360 b8c14089 2003-11-23 devnull t->next = s;
361 b8c14089 2003-11-23 devnull }
362 b8c14089 2003-11-23 devnull
363 b8c14089 2003-11-23 devnull static void
364 b8c14089 2003-11-23 devnull queueread(Dirtab *d, Fcall *t, uchar *buf, Fid *f)
365 b8c14089 2003-11-23 devnull {
366 b8c14089 2003-11-23 devnull Readreq *r;
367 b8c14089 2003-11-23 devnull
368 b8c14089 2003-11-23 devnull r = emalloc(sizeof(Readreq));
369 b8c14089 2003-11-23 devnull r->fcall = t;
370 b8c14089 2003-11-23 devnull r->buf = buf;
371 b8c14089 2003-11-23 devnull r->fid = f;
372 b8c14089 2003-11-23 devnull r->next = d->readq;
373 b8c14089 2003-11-23 devnull d->readq = r;
374 b8c14089 2003-11-23 devnull }
375 b8c14089 2003-11-23 devnull
376 b8c14089 2003-11-23 devnull static void
377 b8c14089 2003-11-23 devnull drainqueue(Dirtab *d)
378 b8c14089 2003-11-23 devnull {
379 b8c14089 2003-11-23 devnull Readreq *r, *nextr, *prevr;
380 b8c14089 2003-11-23 devnull Sendreq *s, *nexts, *prevs;
381 b8c14089 2003-11-23 devnull int i, n;
382 b8c14089 2003-11-23 devnull
383 b8c14089 2003-11-23 devnull prevs = nil;
384 b8c14089 2003-11-23 devnull for(s=d->sendq; s!=nil; s=nexts){
385 b8c14089 2003-11-23 devnull nexts = s->next;
386 b8c14089 2003-11-23 devnull for(i=0; i<s->nfid; i++){
387 b8c14089 2003-11-23 devnull prevr = nil;
388 b8c14089 2003-11-23 devnull for(r=d->readq; r!=nil; r=nextr){
389 b8c14089 2003-11-23 devnull nextr = r->next;
390 b8c14089 2003-11-23 devnull if(r->fid == s->fid[i]){
391 b8c14089 2003-11-23 devnull /* pack the message if necessary */
392 b8c14089 2003-11-23 devnull if(s->pack == nil)
393 b8c14089 2003-11-23 devnull s->pack = plumbpack(s->msg, &s->npack);
394 b8c14089 2003-11-23 devnull /* exchange the stuff... */
395 b8c14089 2003-11-23 devnull r->fcall->data = s->pack+r->fid->offset;
396 b8c14089 2003-11-23 devnull n = s->npack - r->fid->offset;
397 b8c14089 2003-11-23 devnull if(n > messagesize-IOHDRSZ)
398 b8c14089 2003-11-23 devnull n = messagesize-IOHDRSZ;
399 b8c14089 2003-11-23 devnull if(n > r->fcall->count)
400 b8c14089 2003-11-23 devnull n = r->fcall->count;
401 b8c14089 2003-11-23 devnull r->fcall->count = n;
402 b8c14089 2003-11-23 devnull fsysrespond(r->fcall, r->buf, nil);
403 b8c14089 2003-11-23 devnull r->fid->offset += n;
404 b8c14089 2003-11-23 devnull if(r->fid->offset >= s->npack){
405 b8c14089 2003-11-23 devnull /* message transferred; delete this fid from send queue */
406 b8c14089 2003-11-23 devnull r->fid->offset = 0;
407 b8c14089 2003-11-23 devnull s->fid[i] = nil;
408 b8c14089 2003-11-23 devnull s->nleft--;
409 b8c14089 2003-11-23 devnull }
410 b8c14089 2003-11-23 devnull /* delete read request from queue */
411 b8c14089 2003-11-23 devnull if(prevr)
412 b8c14089 2003-11-23 devnull prevr->next = r->next;
413 b8c14089 2003-11-23 devnull else
414 b8c14089 2003-11-23 devnull d->readq = r->next;
415 b8c14089 2003-11-23 devnull free(r->fcall);
416 b8c14089 2003-11-23 devnull free(r);
417 b8c14089 2003-11-23 devnull break;
418 b8c14089 2003-11-23 devnull }else
419 b8c14089 2003-11-23 devnull prevr = r;
420 b8c14089 2003-11-23 devnull }
421 b8c14089 2003-11-23 devnull }
422 b8c14089 2003-11-23 devnull /* if no fids left, delete this send from queue */
423 b8c14089 2003-11-23 devnull if(s->nleft == 0){
424 b8c14089 2003-11-23 devnull free(s->fid);
425 b8c14089 2003-11-23 devnull plumbfree(s->msg);
426 b8c14089 2003-11-23 devnull free(s->pack);
427 b8c14089 2003-11-23 devnull if(prevs)
428 b8c14089 2003-11-23 devnull prevs->next = s->next;
429 b8c14089 2003-11-23 devnull else
430 b8c14089 2003-11-23 devnull d->sendq = s->next;
431 b8c14089 2003-11-23 devnull free(s);
432 b8c14089 2003-11-23 devnull }else
433 b8c14089 2003-11-23 devnull prevs = s;
434 b8c14089 2003-11-23 devnull }
435 b8c14089 2003-11-23 devnull }
436 b8c14089 2003-11-23 devnull
437 b8c14089 2003-11-23 devnull /* can't flush a send because they are always answered synchronously */
438 b8c14089 2003-11-23 devnull static void
439 b8c14089 2003-11-23 devnull flushqueue(Dirtab *d, int oldtag)
440 b8c14089 2003-11-23 devnull {
441 b8c14089 2003-11-23 devnull Readreq *r, *prevr;
442 b8c14089 2003-11-23 devnull
443 b8c14089 2003-11-23 devnull prevr = nil;
444 b8c14089 2003-11-23 devnull for(r=d->readq; r!=nil; r=r->next){
445 b8c14089 2003-11-23 devnull if(oldtag == r->fcall->tag){
446 b8c14089 2003-11-23 devnull /* delete read request from queue */
447 b8c14089 2003-11-23 devnull if(prevr)
448 b8c14089 2003-11-23 devnull prevr->next = r->next;
449 b8c14089 2003-11-23 devnull else
450 b8c14089 2003-11-23 devnull d->readq = r->next;
451 b8c14089 2003-11-23 devnull free(r->fcall);
452 b8c14089 2003-11-23 devnull free(r->buf);
453 b8c14089 2003-11-23 devnull free(r);
454 b8c14089 2003-11-23 devnull return;
455 b8c14089 2003-11-23 devnull }
456 b8c14089 2003-11-23 devnull prevr = r;
457 b8c14089 2003-11-23 devnull }
458 b8c14089 2003-11-23 devnull }
459 b8c14089 2003-11-23 devnull
460 b8c14089 2003-11-23 devnull /* remove messages awaiting delivery to now-closing fid */
461 b8c14089 2003-11-23 devnull static void
462 b8c14089 2003-11-23 devnull removesenders(Dirtab *d, Fid *fid)
463 b8c14089 2003-11-23 devnull {
464 b8c14089 2003-11-23 devnull Sendreq *s, *nexts, *prevs;
465 b8c14089 2003-11-23 devnull int i;
466 b8c14089 2003-11-23 devnull
467 b8c14089 2003-11-23 devnull prevs = nil;
468 b8c14089 2003-11-23 devnull for(s=d->sendq; s!=nil; s=nexts){
469 b8c14089 2003-11-23 devnull nexts = s->next;
470 b8c14089 2003-11-23 devnull for(i=0; i<s->nfid; i++)
471 b8c14089 2003-11-23 devnull if(fid == s->fid[i]){
472 b8c14089 2003-11-23 devnull /* delete this fid from send queue */
473 b8c14089 2003-11-23 devnull s->fid[i] = nil;
474 b8c14089 2003-11-23 devnull s->nleft--;
475 b8c14089 2003-11-23 devnull break;
476 b8c14089 2003-11-23 devnull }
477 b8c14089 2003-11-23 devnull /* if no fids left, delete this send from queue */
478 b8c14089 2003-11-23 devnull if(s->nleft == 0){
479 b8c14089 2003-11-23 devnull free(s->fid);
480 b8c14089 2003-11-23 devnull plumbfree(s->msg);
481 b8c14089 2003-11-23 devnull free(s->pack);
482 b8c14089 2003-11-23 devnull if(prevs)
483 b8c14089 2003-11-23 devnull prevs->next = s->next;
484 b8c14089 2003-11-23 devnull else
485 b8c14089 2003-11-23 devnull d->sendq = s->next;
486 b8c14089 2003-11-23 devnull free(s);
487 b8c14089 2003-11-23 devnull }else
488 b8c14089 2003-11-23 devnull prevs = s;
489 b8c14089 2003-11-23 devnull }
490 b8c14089 2003-11-23 devnull }
491 b8c14089 2003-11-23 devnull
492 b8c14089 2003-11-23 devnull static void
493 b8c14089 2003-11-23 devnull hold(Plumbmsg *m, Dirtab *d)
494 b8c14089 2003-11-23 devnull {
495 b8c14089 2003-11-23 devnull Holdq *h, *q;
496 b8c14089 2003-11-23 devnull
497 b8c14089 2003-11-23 devnull h = emalloc(sizeof(Holdq));
498 b8c14089 2003-11-23 devnull h->msg = m;
499 b8c14089 2003-11-23 devnull /* add to end of queue */
500 b8c14089 2003-11-23 devnull if(d->holdq == nil)
501 b8c14089 2003-11-23 devnull d->holdq = h;
502 b8c14089 2003-11-23 devnull else{
503 b8c14089 2003-11-23 devnull for(q=d->holdq; q->next!=nil; q=q->next)
504 b8c14089 2003-11-23 devnull ;
505 b8c14089 2003-11-23 devnull q->next = h;
506 b8c14089 2003-11-23 devnull }
507 b8c14089 2003-11-23 devnull }
508 b8c14089 2003-11-23 devnull
509 b8c14089 2003-11-23 devnull static void
510 b8c14089 2003-11-23 devnull queueheld(Dirtab *d)
511 b8c14089 2003-11-23 devnull {
512 b8c14089 2003-11-23 devnull Holdq *h;
513 b8c14089 2003-11-23 devnull
514 b8c14089 2003-11-23 devnull while(d->holdq != nil){
515 b8c14089 2003-11-23 devnull h = d->holdq;
516 b8c14089 2003-11-23 devnull d->holdq = h->next;
517 b8c14089 2003-11-23 devnull queuesend(d, h->msg);
518 b8c14089 2003-11-23 devnull /* no need to drain queue because we know no-one is reading yet */
519 b8c14089 2003-11-23 devnull free(h);
520 b8c14089 2003-11-23 devnull }
521 b8c14089 2003-11-23 devnull }
522 b8c14089 2003-11-23 devnull
523 b8c14089 2003-11-23 devnull static void
524 b8c14089 2003-11-23 devnull dispose(Fcall *t, uchar *buf, Plumbmsg *m, Ruleset *rs, Exec *e)
525 b8c14089 2003-11-23 devnull {
526 b8c14089 2003-11-23 devnull int i;
527 b8c14089 2003-11-23 devnull char *err;
528 b8c14089 2003-11-23 devnull
529 b8c14089 2003-11-23 devnull qlock(&queue);
530 b8c14089 2003-11-23 devnull err = nil;
531 b8c14089 2003-11-23 devnull if(m->dst==nil || m->dst[0]=='\0'){
532 b8c14089 2003-11-23 devnull err = Enoport;
533 b8c14089 2003-11-23 devnull if(rs != nil)
534 b8c14089 2003-11-23 devnull err = startup(rs, e);
535 b8c14089 2003-11-23 devnull plumbfree(m);
536 b8c14089 2003-11-23 devnull }else
537 b8c14089 2003-11-23 devnull for(i=NQID; i<ndir; i++)
538 b8c14089 2003-11-23 devnull if(strcmp(m->dst, dir[i].name) == 0){
539 b8c14089 2003-11-23 devnull if(dir[i].nopen == 0){
540 b8c14089 2003-11-23 devnull err = startup(rs, e);
541 b8c14089 2003-11-23 devnull if(e!=nil && e->holdforclient)
542 b8c14089 2003-11-23 devnull hold(m, &dir[i]);
543 b8c14089 2003-11-23 devnull else
544 b8c14089 2003-11-23 devnull plumbfree(m);
545 b8c14089 2003-11-23 devnull }else{
546 b8c14089 2003-11-23 devnull queuesend(&dir[i], m);
547 b8c14089 2003-11-23 devnull drainqueue(&dir[i]);
548 b8c14089 2003-11-23 devnull }
549 b8c14089 2003-11-23 devnull break;
550 b8c14089 2003-11-23 devnull }
551 b8c14089 2003-11-23 devnull freeexec(e);
552 b8c14089 2003-11-23 devnull qunlock(&queue);
553 b8c14089 2003-11-23 devnull fsysrespond(t, buf, err);
554 b8c14089 2003-11-23 devnull free(t);
555 b8c14089 2003-11-23 devnull }
556 b8c14089 2003-11-23 devnull
557 b8c14089 2003-11-23 devnull static Fcall*
558 b8c14089 2003-11-23 devnull fsysversion(Fcall *t, uchar *buf, Fid*)
559 b8c14089 2003-11-23 devnull {
560 b8c14089 2003-11-23 devnull if(t->msize < 256){
561 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "version: message size too small");
562 b8c14089 2003-11-23 devnull return t;
563 b8c14089 2003-11-23 devnull }
564 b8c14089 2003-11-23 devnull if(t->msize < messagesize)
565 b8c14089 2003-11-23 devnull messagesize = t->msize;
566 b8c14089 2003-11-23 devnull t->msize = messagesize;
567 b8c14089 2003-11-23 devnull if(strncmp(t->version, "9P2000", 6) != 0){
568 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "unrecognized 9P version");
569 b8c14089 2003-11-23 devnull return t;
570 b8c14089 2003-11-23 devnull }
571 b8c14089 2003-11-23 devnull t->version = "9P2000";
572 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
573 b8c14089 2003-11-23 devnull return t;
574 b8c14089 2003-11-23 devnull }
575 b8c14089 2003-11-23 devnull
576 b8c14089 2003-11-23 devnull static Fcall*
577 b8c14089 2003-11-23 devnull fsysauth(Fcall *t, uchar *buf, Fid*)
578 b8c14089 2003-11-23 devnull {
579 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "plumber: authentication not required");
580 b8c14089 2003-11-23 devnull return t;
581 b8c14089 2003-11-23 devnull }
582 b8c14089 2003-11-23 devnull
583 b8c14089 2003-11-23 devnull static Fcall*
584 b8c14089 2003-11-23 devnull fsysattach(Fcall *t, uchar *buf, Fid *f)
585 b8c14089 2003-11-23 devnull {
586 b8c14089 2003-11-23 devnull Fcall out;
587 b8c14089 2003-11-23 devnull
588 b8c14089 2003-11-23 devnull if(strcmp(t->uname, user) != 0){
589 b8c14089 2003-11-23 devnull fsysrespond(&out, buf, Eperm);
590 b8c14089 2003-11-23 devnull return t;
591 b8c14089 2003-11-23 devnull }
592 b8c14089 2003-11-23 devnull f->busy = 1;
593 b8c14089 2003-11-23 devnull f->open = 0;
594 b8c14089 2003-11-23 devnull f->qid.type = QTDIR;
595 b8c14089 2003-11-23 devnull f->qid.path = Qdir;
596 b8c14089 2003-11-23 devnull f->qid.vers = 0;
597 b8c14089 2003-11-23 devnull f->dir = dir;
598 b8c14089 2003-11-23 devnull memset(&out, 0, sizeof(Fcall));
599 b8c14089 2003-11-23 devnull out.type = t->type;
600 b8c14089 2003-11-23 devnull out.tag = t->tag;
601 b8c14089 2003-11-23 devnull out.fid = f->fid;
602 b8c14089 2003-11-23 devnull out.qid = f->qid;
603 b8c14089 2003-11-23 devnull fsysrespond(&out, buf, nil);
604 b8c14089 2003-11-23 devnull return t;
605 b8c14089 2003-11-23 devnull }
606 b8c14089 2003-11-23 devnull
607 b8c14089 2003-11-23 devnull static Fcall*
608 b8c14089 2003-11-23 devnull fsysflush(Fcall *t, uchar *buf, Fid*)
609 b8c14089 2003-11-23 devnull {
610 b8c14089 2003-11-23 devnull int i;
611 b8c14089 2003-11-23 devnull
612 b8c14089 2003-11-23 devnull qlock(&queue);
613 b8c14089 2003-11-23 devnull for(i=NQID; i<ndir; i++)
614 b8c14089 2003-11-23 devnull flushqueue(&dir[i], t->oldtag);
615 b8c14089 2003-11-23 devnull qunlock(&queue);
616 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
617 b8c14089 2003-11-23 devnull return t;
618 b8c14089 2003-11-23 devnull }
619 b8c14089 2003-11-23 devnull
620 b8c14089 2003-11-23 devnull static Fcall*
621 b8c14089 2003-11-23 devnull fsyswalk(Fcall *t, uchar *buf, Fid *f)
622 b8c14089 2003-11-23 devnull {
623 b8c14089 2003-11-23 devnull Fcall out;
624 b8c14089 2003-11-23 devnull Fid *nf;
625 b8c14089 2003-11-23 devnull ulong path;
626 b8c14089 2003-11-23 devnull Dirtab *d, *dir;
627 b8c14089 2003-11-23 devnull Qid q;
628 b8c14089 2003-11-23 devnull int i;
629 b8c14089 2003-11-23 devnull uchar type;
630 b8c14089 2003-11-23 devnull char *err;
631 b8c14089 2003-11-23 devnull
632 b8c14089 2003-11-23 devnull if(f->open){
633 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "clone of an open fid");
634 b8c14089 2003-11-23 devnull return t;
635 b8c14089 2003-11-23 devnull }
636 b8c14089 2003-11-23 devnull
637 b8c14089 2003-11-23 devnull nf = nil;
638 b8c14089 2003-11-23 devnull if(t->fid != t->newfid){
639 b8c14089 2003-11-23 devnull nf = newfid(t->newfid);
640 b8c14089 2003-11-23 devnull if(nf->busy){
641 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "clone to a busy fid");
642 b8c14089 2003-11-23 devnull return t;
643 b8c14089 2003-11-23 devnull }
644 b8c14089 2003-11-23 devnull nf->busy = 1;
645 b8c14089 2003-11-23 devnull nf->open = 0;
646 b8c14089 2003-11-23 devnull nf->dir = f->dir;
647 b8c14089 2003-11-23 devnull nf->qid = f->qid;
648 b8c14089 2003-11-23 devnull f = nf; /* walk f */
649 b8c14089 2003-11-23 devnull }
650 b8c14089 2003-11-23 devnull
651 b8c14089 2003-11-23 devnull out.nwqid = 0;
652 b8c14089 2003-11-23 devnull err = nil;
653 b8c14089 2003-11-23 devnull dir = f->dir;
654 b8c14089 2003-11-23 devnull q = f->qid;
655 b8c14089 2003-11-23 devnull
656 b8c14089 2003-11-23 devnull if(t->nwname > 0){
657 b8c14089 2003-11-23 devnull for(i=0; i<t->nwname; i++){
658 b8c14089 2003-11-23 devnull if((q.type & QTDIR) == 0){
659 b8c14089 2003-11-23 devnull err = Enotdir;
660 b8c14089 2003-11-23 devnull break;
661 b8c14089 2003-11-23 devnull }
662 b8c14089 2003-11-23 devnull if(strcmp(t->wname[i], "..") == 0){
663 b8c14089 2003-11-23 devnull type = QTDIR;
664 b8c14089 2003-11-23 devnull path = Qdir;
665 b8c14089 2003-11-23 devnull Accept:
666 b8c14089 2003-11-23 devnull q.type = type;
667 b8c14089 2003-11-23 devnull q.vers = 0;
668 b8c14089 2003-11-23 devnull q.path = path;
669 b8c14089 2003-11-23 devnull out.wqid[out.nwqid++] = q;
670 b8c14089 2003-11-23 devnull continue;
671 b8c14089 2003-11-23 devnull }
672 b8c14089 2003-11-23 devnull d = dir;
673 b8c14089 2003-11-23 devnull d++; /* skip '.' */
674 b8c14089 2003-11-23 devnull for(; d->name; d++)
675 b8c14089 2003-11-23 devnull if(strcmp(t->wname[i], d->name) == 0){
676 b8c14089 2003-11-23 devnull type = d->type;
677 b8c14089 2003-11-23 devnull path = d->qid;
678 b8c14089 2003-11-23 devnull dir = d;
679 b8c14089 2003-11-23 devnull goto Accept;
680 b8c14089 2003-11-23 devnull }
681 b8c14089 2003-11-23 devnull err = Enoexist;
682 b8c14089 2003-11-23 devnull break;
683 b8c14089 2003-11-23 devnull }
684 b8c14089 2003-11-23 devnull }
685 b8c14089 2003-11-23 devnull
686 b8c14089 2003-11-23 devnull out.type = t->type;
687 b8c14089 2003-11-23 devnull out.tag = t->tag;
688 b8c14089 2003-11-23 devnull if(err!=nil || out.nwqid<t->nwname){
689 b8c14089 2003-11-23 devnull if(nf)
690 b8c14089 2003-11-23 devnull nf->busy = 0;
691 b8c14089 2003-11-23 devnull }else if(out.nwqid == t->nwname){
692 b8c14089 2003-11-23 devnull f->qid = q;
693 b8c14089 2003-11-23 devnull f->dir = dir;
694 b8c14089 2003-11-23 devnull }
695 b8c14089 2003-11-23 devnull
696 b8c14089 2003-11-23 devnull fsysrespond(&out, buf, err);
697 b8c14089 2003-11-23 devnull return t;
698 b8c14089 2003-11-23 devnull }
699 b8c14089 2003-11-23 devnull
700 b8c14089 2003-11-23 devnull static Fcall*
701 b8c14089 2003-11-23 devnull fsysopen(Fcall *t, uchar *buf, Fid *f)
702 b8c14089 2003-11-23 devnull {
703 b8c14089 2003-11-23 devnull int m, clearrules, mode;
704 b8c14089 2003-11-23 devnull
705 b8c14089 2003-11-23 devnull clearrules = 0;
706 b8c14089 2003-11-23 devnull if(t->mode & OTRUNC){
707 b8c14089 2003-11-23 devnull if(f->qid.path != Qrules)
708 b8c14089 2003-11-23 devnull goto Deny;
709 b8c14089 2003-11-23 devnull clearrules = 1;
710 b8c14089 2003-11-23 devnull }
711 b8c14089 2003-11-23 devnull /* can't truncate anything, so just disregard */
712 b8c14089 2003-11-23 devnull mode = t->mode & ~(OTRUNC|OCEXEC);
713 b8c14089 2003-11-23 devnull /* can't execute or remove anything */
714 b8c14089 2003-11-23 devnull if(mode==OEXEC || (mode&ORCLOSE))
715 b8c14089 2003-11-23 devnull goto Deny;
716 b8c14089 2003-11-23 devnull switch(mode){
717 b8c14089 2003-11-23 devnull default:
718 b8c14089 2003-11-23 devnull goto Deny;
719 b8c14089 2003-11-23 devnull case OREAD:
720 b8c14089 2003-11-23 devnull m = 0400;
721 b8c14089 2003-11-23 devnull break;
722 b8c14089 2003-11-23 devnull case OWRITE:
723 b8c14089 2003-11-23 devnull m = 0200;
724 b8c14089 2003-11-23 devnull break;
725 b8c14089 2003-11-23 devnull case ORDWR:
726 b8c14089 2003-11-23 devnull m = 0600;
727 b8c14089 2003-11-23 devnull break;
728 b8c14089 2003-11-23 devnull }
729 b8c14089 2003-11-23 devnull if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
730 b8c14089 2003-11-23 devnull goto Deny;
731 b8c14089 2003-11-23 devnull if(f->qid.path==Qrules && (mode==OWRITE || mode==ORDWR)){
732 b8c14089 2003-11-23 devnull lock(&rulesref);
733 b8c14089 2003-11-23 devnull if(rulesref.ref++ != 0){
734 b8c14089 2003-11-23 devnull rulesref.ref--;
735 b8c14089 2003-11-23 devnull unlock(&rulesref);
736 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Einuse);
737 b8c14089 2003-11-23 devnull return t;
738 b8c14089 2003-11-23 devnull }
739 b8c14089 2003-11-23 devnull unlock(&rulesref);
740 b8c14089 2003-11-23 devnull }
741 b8c14089 2003-11-23 devnull if(clearrules){
742 b8c14089 2003-11-23 devnull writerules(nil, 0);
743 b8c14089 2003-11-23 devnull rules[0] = nil;
744 b8c14089 2003-11-23 devnull }
745 b8c14089 2003-11-23 devnull t->qid = f->qid;
746 b8c14089 2003-11-23 devnull t->iounit = 0;
747 b8c14089 2003-11-23 devnull qlock(&queue);
748 b8c14089 2003-11-23 devnull f->mode = mode;
749 b8c14089 2003-11-23 devnull f->open = 1;
750 b8c14089 2003-11-23 devnull f->dir->nopen++;
751 b8c14089 2003-11-23 devnull f->nextopen = f->dir->fopen;
752 b8c14089 2003-11-23 devnull f->dir->fopen = f;
753 b8c14089 2003-11-23 devnull queueheld(f->dir);
754 b8c14089 2003-11-23 devnull qunlock(&queue);
755 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
756 b8c14089 2003-11-23 devnull return t;
757 b8c14089 2003-11-23 devnull
758 b8c14089 2003-11-23 devnull Deny:
759 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Eperm);
760 b8c14089 2003-11-23 devnull return t;
761 b8c14089 2003-11-23 devnull }
762 b8c14089 2003-11-23 devnull
763 b8c14089 2003-11-23 devnull static Fcall*
764 b8c14089 2003-11-23 devnull fsyscreate(Fcall *t, uchar *buf, Fid*)
765 b8c14089 2003-11-23 devnull {
766 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Eperm);
767 b8c14089 2003-11-23 devnull return t;
768 b8c14089 2003-11-23 devnull }
769 b8c14089 2003-11-23 devnull
770 b8c14089 2003-11-23 devnull static Fcall*
771 b8c14089 2003-11-23 devnull fsysreadrules(Fcall *t, uchar *buf)
772 b8c14089 2003-11-23 devnull {
773 b8c14089 2003-11-23 devnull char *p;
774 b8c14089 2003-11-23 devnull int n;
775 b8c14089 2003-11-23 devnull
776 b8c14089 2003-11-23 devnull p = printrules();
777 b8c14089 2003-11-23 devnull n = strlen(p);
778 b8c14089 2003-11-23 devnull t->data = p;
779 b8c14089 2003-11-23 devnull if(t->offset >= n)
780 b8c14089 2003-11-23 devnull t->count = 0;
781 b8c14089 2003-11-23 devnull else{
782 b8c14089 2003-11-23 devnull t->data = p+t->offset;
783 b8c14089 2003-11-23 devnull if(t->offset+t->count > n)
784 b8c14089 2003-11-23 devnull t->count = n-t->offset;
785 b8c14089 2003-11-23 devnull }
786 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
787 b8c14089 2003-11-23 devnull free(p);
788 b8c14089 2003-11-23 devnull return t;
789 b8c14089 2003-11-23 devnull }
790 b8c14089 2003-11-23 devnull
791 b8c14089 2003-11-23 devnull static Fcall*
792 b8c14089 2003-11-23 devnull fsysread(Fcall *t, uchar *buf, Fid *f)
793 b8c14089 2003-11-23 devnull {
794 b8c14089 2003-11-23 devnull uchar *b;
795 b8c14089 2003-11-23 devnull int i, n, o, e;
796 b8c14089 2003-11-23 devnull uint len;
797 b8c14089 2003-11-23 devnull Dirtab *d;
798 b8c14089 2003-11-23 devnull uint clock;
799 b8c14089 2003-11-23 devnull
800 b8c14089 2003-11-23 devnull if(f->qid.path != Qdir){
801 b8c14089 2003-11-23 devnull if(f->qid.path == Qrules)
802 b8c14089 2003-11-23 devnull return fsysreadrules(t, buf);
803 b8c14089 2003-11-23 devnull /* read from port */
804 b8c14089 2003-11-23 devnull if(f->qid.path < NQID){
805 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "internal error: unknown read port");
806 b8c14089 2003-11-23 devnull return t;
807 b8c14089 2003-11-23 devnull }
808 b8c14089 2003-11-23 devnull qlock(&queue);
809 b8c14089 2003-11-23 devnull queueread(f->dir, t, buf, f);
810 b8c14089 2003-11-23 devnull drainqueue(f->dir);
811 b8c14089 2003-11-23 devnull qunlock(&queue);
812 b8c14089 2003-11-23 devnull return nil;
813 b8c14089 2003-11-23 devnull }
814 b8c14089 2003-11-23 devnull o = t->offset;
815 b8c14089 2003-11-23 devnull e = t->offset+t->count;
816 b8c14089 2003-11-23 devnull clock = getclock();
817 b8c14089 2003-11-23 devnull b = malloc(messagesize-IOHDRSZ);
818 b8c14089 2003-11-23 devnull if(b == nil){
819 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Enomem);
820 b8c14089 2003-11-23 devnull return t;
821 b8c14089 2003-11-23 devnull }
822 b8c14089 2003-11-23 devnull n = 0;
823 b8c14089 2003-11-23 devnull d = dir;
824 b8c14089 2003-11-23 devnull d++; /* first entry is '.' */
825 b8c14089 2003-11-23 devnull for(i=0; d->name!=nil && i<e; i+=len){
826 b8c14089 2003-11-23 devnull len = dostat(d, b+n, messagesize-IOHDRSZ-n, clock);
827 b8c14089 2003-11-23 devnull if(len <= BIT16SZ)
828 b8c14089 2003-11-23 devnull break;
829 b8c14089 2003-11-23 devnull if(i >= o)
830 b8c14089 2003-11-23 devnull n += len;
831 b8c14089 2003-11-23 devnull d++;
832 b8c14089 2003-11-23 devnull }
833 b8c14089 2003-11-23 devnull t->data = (char*)b;
834 b8c14089 2003-11-23 devnull t->count = n;
835 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
836 b8c14089 2003-11-23 devnull free(b);
837 b8c14089 2003-11-23 devnull return t;
838 b8c14089 2003-11-23 devnull }
839 b8c14089 2003-11-23 devnull
840 b8c14089 2003-11-23 devnull static Fcall*
841 b8c14089 2003-11-23 devnull fsyswrite(Fcall *t, uchar *buf, Fid *f)
842 b8c14089 2003-11-23 devnull {
843 b8c14089 2003-11-23 devnull Plumbmsg *m;
844 b8c14089 2003-11-23 devnull int i, n;
845 b8c14089 2003-11-23 devnull long count;
846 b8c14089 2003-11-23 devnull char *data;
847 b8c14089 2003-11-23 devnull Exec *e;
848 b8c14089 2003-11-23 devnull
849 b8c14089 2003-11-23 devnull switch((int)f->qid.path){
850 b8c14089 2003-11-23 devnull case Qdir:
851 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Eisdir);
852 b8c14089 2003-11-23 devnull return t;
853 b8c14089 2003-11-23 devnull case Qrules:
854 b8c14089 2003-11-23 devnull clock = getclock();
855 b8c14089 2003-11-23 devnull fsysrespond(t, buf, writerules(t->data, t->count));
856 b8c14089 2003-11-23 devnull return t;
857 b8c14089 2003-11-23 devnull case Qsend:
858 b8c14089 2003-11-23 devnull if(f->offset == 0){
859 b8c14089 2003-11-23 devnull data = t->data;
860 b8c14089 2003-11-23 devnull count = t->count;
861 b8c14089 2003-11-23 devnull }else{
862 b8c14089 2003-11-23 devnull /* partial message already assembled */
863 b8c14089 2003-11-23 devnull f->writebuf = erealloc(f->writebuf, f->offset + t->count);
864 b8c14089 2003-11-23 devnull memmove(f->writebuf+f->offset, t->data, t->count);
865 b8c14089 2003-11-23 devnull data = f->writebuf;
866 b8c14089 2003-11-23 devnull count = f->offset+t->count;
867 b8c14089 2003-11-23 devnull }
868 b8c14089 2003-11-23 devnull m = plumbunpackpartial(data, count, &n);
869 b8c14089 2003-11-23 devnull if(m == nil){
870 b8c14089 2003-11-23 devnull if(n == 0){
871 b8c14089 2003-11-23 devnull f->offset = 0;
872 b8c14089 2003-11-23 devnull free(f->writebuf);
873 b8c14089 2003-11-23 devnull f->writebuf = nil;
874 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Ebadmsg);
875 b8c14089 2003-11-23 devnull return t;
876 b8c14089 2003-11-23 devnull }
877 b8c14089 2003-11-23 devnull /* can read more... */
878 b8c14089 2003-11-23 devnull if(f->offset == 0){
879 b8c14089 2003-11-23 devnull f->writebuf = emalloc(t->count);
880 b8c14089 2003-11-23 devnull memmove(f->writebuf, t->data, t->count);
881 b8c14089 2003-11-23 devnull }
882 b8c14089 2003-11-23 devnull /* else buffer has already been grown */
883 b8c14089 2003-11-23 devnull f->offset += t->count;
884 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
885 b8c14089 2003-11-23 devnull return t;
886 b8c14089 2003-11-23 devnull }
887 b8c14089 2003-11-23 devnull /* release partial buffer */
888 b8c14089 2003-11-23 devnull f->offset = 0;
889 b8c14089 2003-11-23 devnull free(f->writebuf);
890 b8c14089 2003-11-23 devnull f->writebuf = nil;
891 b8c14089 2003-11-23 devnull for(i=0; rules[i]; i++)
892 b8c14089 2003-11-23 devnull if((e=matchruleset(m, rules[i])) != nil){
893 b8c14089 2003-11-23 devnull dispose(t, buf, m, rules[i], e);
894 b8c14089 2003-11-23 devnull return nil;
895 b8c14089 2003-11-23 devnull }
896 b8c14089 2003-11-23 devnull if(m->dst != nil){
897 b8c14089 2003-11-23 devnull dispose(t, buf, m, nil, nil);
898 b8c14089 2003-11-23 devnull return nil;
899 b8c14089 2003-11-23 devnull }
900 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "no matching plumb rule");
901 b8c14089 2003-11-23 devnull return t;
902 b8c14089 2003-11-23 devnull }
903 b8c14089 2003-11-23 devnull fsysrespond(t, buf, "internal error: write to unknown file");
904 b8c14089 2003-11-23 devnull return t;
905 b8c14089 2003-11-23 devnull }
906 b8c14089 2003-11-23 devnull
907 b8c14089 2003-11-23 devnull static Fcall*
908 b8c14089 2003-11-23 devnull fsysstat(Fcall *t, uchar *buf, Fid *f)
909 b8c14089 2003-11-23 devnull {
910 b8c14089 2003-11-23 devnull t->stat = emalloc(messagesize-IOHDRSZ);
911 b8c14089 2003-11-23 devnull t->nstat = dostat(f->dir, t->stat, messagesize-IOHDRSZ, clock);
912 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
913 b8c14089 2003-11-23 devnull free(t->stat);
914 b8c14089 2003-11-23 devnull t->stat = nil;
915 b8c14089 2003-11-23 devnull return t;
916 b8c14089 2003-11-23 devnull }
917 b8c14089 2003-11-23 devnull
918 b8c14089 2003-11-23 devnull static Fcall*
919 b8c14089 2003-11-23 devnull fsyswstat(Fcall *t, uchar *buf, Fid*)
920 b8c14089 2003-11-23 devnull {
921 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Eperm);
922 b8c14089 2003-11-23 devnull return t;
923 b8c14089 2003-11-23 devnull }
924 b8c14089 2003-11-23 devnull
925 b8c14089 2003-11-23 devnull static Fcall*
926 b8c14089 2003-11-23 devnull fsysremove(Fcall *t, uchar *buf, Fid*)
927 b8c14089 2003-11-23 devnull {
928 b8c14089 2003-11-23 devnull fsysrespond(t, buf, Eperm);
929 b8c14089 2003-11-23 devnull return t;
930 b8c14089 2003-11-23 devnull }
931 b8c14089 2003-11-23 devnull
932 b8c14089 2003-11-23 devnull static Fcall*
933 b8c14089 2003-11-23 devnull fsysclunk(Fcall *t, uchar *buf, Fid *f)
934 b8c14089 2003-11-23 devnull {
935 b8c14089 2003-11-23 devnull Fid *prev, *p;
936 b8c14089 2003-11-23 devnull Dirtab *d;
937 b8c14089 2003-11-23 devnull
938 b8c14089 2003-11-23 devnull qlock(&queue);
939 b8c14089 2003-11-23 devnull if(f->open){
940 b8c14089 2003-11-23 devnull d = f->dir;
941 b8c14089 2003-11-23 devnull d->nopen--;
942 b8c14089 2003-11-23 devnull if(d->qid==Qrules && (f->mode==OWRITE || f->mode==ORDWR)){
943 b8c14089 2003-11-23 devnull /*
944 b8c14089 2003-11-23 devnull * just to be sure last rule is parsed; error messages will be lost, though,
945 b8c14089 2003-11-23 devnull * unless last write ended with a blank line
946 b8c14089 2003-11-23 devnull */
947 b8c14089 2003-11-23 devnull writerules(nil, 0);
948 b8c14089 2003-11-23 devnull lock(&rulesref);
949 b8c14089 2003-11-23 devnull rulesref.ref--;
950 b8c14089 2003-11-23 devnull unlock(&rulesref);
951 b8c14089 2003-11-23 devnull }
952 b8c14089 2003-11-23 devnull prev = nil;
953 b8c14089 2003-11-23 devnull for(p=d->fopen; p; p=p->nextopen){
954 b8c14089 2003-11-23 devnull if(p == f){
955 b8c14089 2003-11-23 devnull if(prev)
956 b8c14089 2003-11-23 devnull prev->nextopen = f->nextopen;
957 b8c14089 2003-11-23 devnull else
958 b8c14089 2003-11-23 devnull d->fopen = f->nextopen;
959 b8c14089 2003-11-23 devnull removesenders(d, f);
960 b8c14089 2003-11-23 devnull break;
961 b8c14089 2003-11-23 devnull }
962 b8c14089 2003-11-23 devnull prev = p;
963 b8c14089 2003-11-23 devnull }
964 b8c14089 2003-11-23 devnull }
965 b8c14089 2003-11-23 devnull f->busy = 0;
966 b8c14089 2003-11-23 devnull f->open = 0;
967 b8c14089 2003-11-23 devnull f->offset = 0;
968 b8c14089 2003-11-23 devnull if(f->writebuf != nil){
969 b8c14089 2003-11-23 devnull free(f->writebuf);
970 b8c14089 2003-11-23 devnull f->writebuf = nil;
971 b8c14089 2003-11-23 devnull }
972 b8c14089 2003-11-23 devnull qunlock(&queue);
973 b8c14089 2003-11-23 devnull fsysrespond(t, buf, nil);
974 b8c14089 2003-11-23 devnull return t;
975 b8c14089 2003-11-23 devnull }