]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/9660srv/main.c
ndb/dns: remove single-ip-address assuptions
[plan9front.git] / sys / src / cmd / 9660srv / main.c
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include "dat.h"
6 #include "fns.h"
7
8 enum
9 {
10         Maxfdata        = 8192,
11         Maxiosize       = IOHDRSZ+Maxfdata,
12 };
13
14 void io(int);
15 void rversion(void);
16 void    rattach(void);
17 void    rauth(void);
18 void    rclunk(void);
19 void    rcreate(void);
20 void    rflush(void);
21 void    ropen(void);
22 void    rread(void);
23 void    rremove(void);
24 void    rsession(void);
25 void    rstat(void);
26 void    rwalk(void);
27 void    rwrite(void);
28 void    rwstat(void);
29
30 static int      openflags(int);
31 static void     usage(void);
32
33 #define Reqsize (sizeof(Fcall)+Maxfdata)
34
35 Fcall *req;
36 Fcall *rep;
37
38 uchar mdata[Maxiosize];
39 char fdata[Maxfdata];
40 uchar statbuf[STATMAX];
41 int errno;
42
43 static char     srvfile[64];
44
45 extern Xfsub    *xsublist[];
46 extern int      nclust;
47
48 jmp_buf err_lab[16];
49 int     nerr_lab;
50 char    err_msg[ERRMAX];
51
52 int     chatty;
53 int     nojoliet;
54 int     noplan9;
55 int norock;
56
57 void    (*fcalls[])(void) = {
58         [Tversion]      rversion,
59         [Tflush]        rflush,
60         [Tauth] rauth,
61         [Tattach]       rattach,
62         [Twalk]         rwalk,
63         [Topen]         ropen,
64         [Tcreate]       rcreate,
65         [Tread]         rread,
66         [Twrite]        rwrite,
67         [Tclunk]        rclunk,
68         [Tremove]       rremove,
69         [Tstat]         rstat,
70         [Twstat]        rwstat,
71 };
72
73 void
74 main(int argc, char **argv)
75 {
76         int srvfd, pipefd[2], stdio;
77         Xfsub **xs;
78
79         stdio = 0;
80         ARGBEGIN {
81         case '9':
82                 noplan9 = 1;
83                 break;
84         case 'c':
85                 nclust = atoi(EARGF(usage()));
86                 if (nclust <= 0)
87                         sysfatal("nclust %d non-positive", nclust);
88                 break;
89         case 'f':
90                 deffile = EARGF(usage());
91                 break;
92         case 'r':
93                 norock = 1;
94                 break;
95         case 's':
96                 stdio = 1;
97                 break;
98         case 'v':
99                 chatty = 1;
100                 break;
101         case 'J':
102                 nojoliet = 1;
103                 break;
104         default:
105                 usage();
106         } ARGEND
107
108         switch(argc) {
109         case 0:
110                 break;
111         case 1:
112                 srvname = argv[0];
113                 break;
114         default:
115                 usage();
116         }
117
118         iobuf_init();
119         for(xs=xsublist; *xs; xs++)
120                 (*(*xs)->reset)();
121
122         if(stdio) {
123                 pipefd[0] = 0;
124                 pipefd[1] = 1;
125         } else {
126                 close(0);
127                 close(1);
128                 open("/dev/null", OREAD);
129                 open("/dev/null", OWRITE);
130                 if(pipe(pipefd) < 0)
131                         panic(1, "pipe");
132                 sprint(srvfile, "/srv/%s", srvname);
133                 srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
134                 if(srvfd < 0)
135                         panic(1, srvfile);
136                 fprint(srvfd, "%d", pipefd[0]);
137                 close(pipefd[0]);
138                 fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);
139         }
140         srvfd = pipefd[1];
141
142         switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){
143         case -1:
144                 panic(1, "fork");
145         default:
146                 _exits(0);
147         case 0:
148                 break;
149         }
150
151         io(srvfd);
152         exits(0);
153 }
154
155 void
156 io(int srvfd)
157 {
158         int n, pid;
159         Fcall xreq, xrep;
160
161         req = &xreq;
162         rep = &xrep;
163         pid = getpid();
164         fmtinstall('F', fcallfmt);
165
166         while((n = read9pmsg(srvfd, mdata, sizeof mdata)) != 0){
167                 if(n < 0)
168                         panic(1, "mount read");
169                 if(convM2S(mdata, n, req) != n)
170                         panic(1, "convM2S format error");
171
172                 if(chatty)
173                         fprint(2, "9660srv %d:<-%F\n", pid, req);
174
175                 errno = 0;
176                 if(!waserror()){
177                         err_msg[0] = 0;
178                         if(req->type >= nelem(fcalls) || !fcalls[req->type])
179                                 error("bad fcall type");
180                         (*fcalls[req->type])();
181                         poperror();
182                 }
183
184                 if(err_msg[0]){
185                         rep->type = Rerror;
186                         rep->ename = err_msg;
187                 }else{
188                         rep->type = req->type + 1;
189                         rep->fid = req->fid;
190                 }
191                 rep->tag = req->tag;
192
193                 if(chatty)
194                         fprint(2, "9660srv %d:->%F\n", pid, rep);
195                 n = convS2M(rep, mdata, sizeof mdata);
196                 if(n == 0)
197                         panic(1, "convS2M error on write");
198                 if(write(srvfd, mdata, n) != n)
199                         panic(1, "mount write");
200                 if(nerr_lab != 0)
201                         panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", nerr_lab,
202                         err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],
203                         err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],
204                         err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);
205         }
206         chat("server shut down");
207 }
208
209 static void
210 usage(void)
211 {
212         fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
213         exits("usage");
214 }
215
216 void
217 error(char *p)
218 {
219         strecpy(err_msg, err_msg+sizeof err_msg, p);
220         nexterror();
221 }
222
223 void
224 nexterror(void)
225 {
226         longjmp(err_lab[--nerr_lab], 1);
227 }
228
229 void*
230 ealloc(long n)
231 {
232         void *p;
233
234         p = malloc(n);
235         if(p == 0)
236                 error("no memory");
237         setmalloctag(p, getcallerpc(&n));
238         return p;
239 }
240
241 void
242 setnames(Dir *d, char *n)
243 {
244         d->name = n;
245         d->uid = n+Maxname;
246         d->gid = n+Maxname*2;
247         d->muid = n+Maxname*3;
248
249         d->name[0] = '\0';
250         d->uid[0] = '\0';
251         d->gid[0] = '\0';
252         d->muid[0] = '\0';
253 }
254
255 void
256 rversion(void)
257 {
258         if(req->msize > Maxiosize)
259                 rep->msize = Maxiosize;
260         else
261                 rep->msize = req->msize;
262         rep->version = "9P2000";
263 }
264
265 void
266 rauth(void)
267 {
268         error("9660srv: authentication not required");
269 }
270
271 void
272 rflush(void)
273 {
274 }
275
276 void
277 rattach(void)
278 {
279         Xfs *xf;
280         Xfile *root;
281         Xfsub **xs;
282
283         chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
284                 req->fid, req->uname, req->aname);
285
286         if(waserror()){
287                 xfile(req->fid, Clunk);
288                 nexterror();
289         }
290         root = xfile(req->fid, Clean);
291         root->qid = (Qid){0, 0, QTDIR};
292         root->xf = xf = ealloc(sizeof(Xfs));
293         memset(xf, 0, sizeof(Xfs));
294         xf->ref = 1;
295         xf->d = getxdata(req->aname);
296
297         for(xs=xsublist; *xs; xs++)
298                 if((*(*xs)->attach)(root) >= 0){
299                         poperror();
300                         xf->s = *xs;
301                         xf->rootqid = root->qid;
302                         rep->qid = root->qid;
303                         return;
304                 }
305         error("unknown format");
306 }
307
308 Xfile*
309 doclone(Xfile *of, int newfid)
310 {
311         Xfile *nf, *next;
312
313         nf = xfile(newfid, Clean);
314         if(waserror()){
315                 xfile(newfid, Clunk);
316                 nexterror();
317         }
318         next = nf->next;
319         *nf = *of;
320         nf->next = next;
321         nf->fid = newfid;
322         refxfs(nf->xf, 1);
323         if(nf->len){
324                 nf->ptr = ealloc(nf->len);
325                 memmove(nf->ptr, of->ptr, nf->len);
326         }else
327                 nf->ptr = of->ptr;
328         (*of->xf->s->clone)(of, nf);
329         poperror();
330         return nf;
331 }
332
333 void
334 rwalk(void)
335 {
336         Xfile *f, *nf;
337         Isofile *oldptr;
338         int oldlen;
339         Qid oldqid;
340
341         rep->nwqid = 0;
342         nf = nil;
343         f = xfile(req->fid, Asis);
344         if(req->fid != req->newfid)
345                 f = nf = doclone(f, req->newfid);
346
347         /* save old state in case of error */
348         oldqid = f->qid;
349         oldlen = f->len;
350         oldptr = f->ptr;
351         if(oldlen){
352                 oldptr = ealloc(oldlen);
353                 memmove(oldptr, f->ptr, oldlen);
354         }
355
356         if(waserror()){
357                 if(rep->nwqid == req->nwname){
358                         if(oldlen)
359                                 free(oldptr);
360                 }else{
361                         /* restore previous state */
362                         f->qid = oldqid;
363                         if(f->len)
364                                 free(f->ptr);
365                         f->ptr = oldptr;
366                         f->len = oldlen;
367                 }
368                 if(nf != nil)
369                         xfile(req->newfid, Clunk);
370                 if(rep->nwqid==req->nwname || rep->nwqid > 0){
371                         err_msg[0] = '\0';
372                         return;
373                 }
374                 nexterror();
375         }
376
377         for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
378                 chat("\twalking %s\n", req->wname[rep->nwqid]);
379                 if(!(f->qid.type & QTDIR)){
380                         chat("\tnot dir: type=%#x\n", f->qid.type);
381                         error("walk in non-directory");
382                 }
383
384                 if(strcmp(req->wname[rep->nwqid], "..")==0){
385                         if(f->qid.path != f->xf->rootqid.path)
386                                 (*f->xf->s->walkup)(f);
387                 }else
388                         (*f->xf->s->walk)(f, req->wname[rep->nwqid]);
389                 rep->wqid[rep->nwqid] = f->qid;
390         }
391         poperror();
392         if(oldlen)
393                 free(oldptr);
394 }
395
396 void
397 ropen(void)
398 {
399         Xfile *f;
400
401         f = xfile(req->fid, Asis);
402         if(f->flags&Omodes)
403                 error("open on open file");
404         if(req->mode&ORCLOSE)
405                 error("no removes");
406         (*f->xf->s->open)(f, req->mode);
407         f->flags = openflags(req->mode);
408         rep->qid = f->qid;
409         rep->iounit = 0;
410 }
411
412 void
413 rcreate(void)
414 {
415         error("no creates");
416 /*
417         Xfile *f;
418
419         if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
420                 error("create . or ..");
421         f = xfile(req->fid, Asis);
422         if(f->flags&Omodes)
423                 error("create on open file");
424         if(!(f->qid.path&CHDIR))
425                 error("create in non-directory");
426         (*f->xf->s->create)(f, req->name, req->perm, req->mode);
427         chat("f->qid=0x%8.8lux...", f->qid.path);
428         f->flags = openflags(req->mode);
429         rep->qid = f->qid;
430 */
431 }
432
433 void
434 rread(void)
435 {
436         Xfile *f;
437
438         f=xfile(req->fid, Asis);
439         if (!(f->flags&Oread))
440                 error("file not opened for reading");
441         if(f->qid.type & QTDIR)
442                 rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
443         else
444                 rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
445         rep->data = fdata;
446 }
447
448 void
449 rwrite(void)
450 {
451         Xfile *f;
452
453         f=xfile(req->fid, Asis);
454         if(!(f->flags&Owrite))
455                 error("file not opened for writing");
456         rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
457 }
458
459 void
460 rclunk(void)
461 {
462         Xfile *f;
463
464         if(!waserror()){
465                 f = xfile(req->fid, Asis);
466                 (*f->xf->s->clunk)(f);
467                 poperror();
468         }
469         xfile(req->fid, Clunk);
470 }
471
472 void
473 rremove(void)
474 {
475         error("no removes");
476 }
477
478 void
479 rstat(void)
480 {
481         Xfile *f;
482         Dir dir;
483
484         chat("stat(fid=%d)...", req->fid);
485         f=xfile(req->fid, Asis);
486         setnames(&dir, fdata);
487         (*f->xf->s->stat)(f, &dir);
488         if(chatty)
489                 showdir(2, &dir);
490         rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
491         rep->stat = statbuf;
492 }
493
494 void
495 rwstat(void)
496 {
497         error("no wstat");
498 }
499
500 static int
501 openflags(int mode)
502 {
503         int flags = 0;
504
505         switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
506         case OREAD:
507         case OEXEC:
508                 flags = Oread; break;
509         case OWRITE:
510                 flags = Owrite; break;
511         case ORDWR:
512                 flags = Oread|Owrite; break;
513         }
514         if(mode & ORCLOSE)
515                 flags |= Orclose;
516         return flags;
517 }
518
519 void
520 showdir(int fd, Dir *s)
521 {
522         char a_time[32], m_time[32];
523         char *p;
524
525         strcpy(a_time, ctime(s->atime));
526         if(p=strchr(a_time, '\n'))      /* assign = */
527                 *p = 0;
528         strcpy(m_time, ctime(s->mtime));
529         if(p=strchr(m_time, '\n'))      /* assign = */
530                 *p = 0;
531         fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
532 mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
533                 s->name, s->qid.path, s->qid.vers, s->type, s->dev,
534                 s->mode, s->mode,
535                 a_time, m_time, s->length, s->uid, s->gid);
536 }
537
538 #define SIZE    1024
539
540 void
541 chat(char *fmt, ...)
542 {
543         va_list arg;
544
545         if(chatty){
546                 va_start(arg, fmt);
547                 vfprint(2, fmt, arg);
548                 va_end(arg);
549         }
550 }
551
552 void
553 panic(int rflag, char *fmt, ...)
554 {
555         va_list arg;
556         char buf[SIZE]; int n;
557
558         n = sprint(buf, "%s %d: ", argv0, getpid());
559         va_start(arg, fmt);
560         vseprint(buf+n, buf+SIZE, fmt, arg);
561         va_end(arg);
562         fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
563         if(chatty){
564                 fprint(2, "abort\n");
565                 abort();
566         }
567         exits("panic");
568 }