11 Maxiosize = IOHDRSZ+Maxfdata,
30 static int openflags(int);
31 static void usage(void);
33 #define Reqsize (sizeof(Fcall)+Maxfdata)
38 uchar mdata[Maxiosize];
40 uchar statbuf[STATMAX];
44 extern Xfsub *xsublist[];
56 void (*fcalls[Tmax])(void);
61 fcalls[Tversion]= rversion;
62 fcalls[Tflush]= rflush;
64 fcalls[Tattach]= rattach;
67 fcalls[Tcreate]= rcreate;
69 fcalls[Twrite]= rwrite;
70 fcalls[Tclunk]= rclunk;
71 fcalls[Tremove]= rremove;
73 fcalls[Twstat]= rwstat;
77 main(int argc, char **argv)
79 int srvfd, pipefd[2], stdio;
91 nclust = atoi(EARGF(usage()));
93 sysfatal("nclust %d non-positive", nclust);
96 deffile = EARGF(usage());
111 mtpt = EARGF(usage());
128 for(xs=xsublist; *xs; xs++)
137 open("/dev/null", OREAD);
138 open("/dev/null", OWRITE);
142 if(post9pservice(pipefd[0], srvname, mtpt) < 0)
143 sysfatal("post9pservice: %r");
148 switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
170 fmtinstall('F', fcallfmt);
174 * reading from a pipe or a network device
175 * will give an error after a few eof reads.
176 * however, we cannot tell the difference
177 * between a zero-length read and an interrupt
178 * on the processes writing to us,
179 * so we wait for the error.
181 n = read9pmsg(srvfd, mdata, sizeof mdata);
186 if(convM2S(mdata, n, req) == 0)
190 fprint(2, "9660srv %d:<-%F\n", pid, req);
195 if(req->type >= nelem(fcalls) || !fcalls[req->type])
196 error("bad fcall type");
197 (*fcalls[req->type])();
203 rep->ename = err_msg;
205 rep->type = req->type + 1;
211 fprint(2, "9660srv %d:->%F\n", pid, rep);
212 n = convS2M(rep, mdata, sizeof mdata);
214 panic(1, "convS2M error on write");
215 if(write(srvfd, mdata, n) != n)
216 panic(1, "mount write");
218 panic(0, "err stack %d");
220 chat("server shut down");
226 fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
233 strecpy(err_msg, err_msg+sizeof err_msg, p);
240 longjmp(err_lab[--nerr_lab], 1);
255 setnames(Dir *d, char *n)
259 d->gid = n+Maxname*2;
260 d->muid = n+Maxname*3;
271 if(req->msize > Maxiosize)
272 rep->msize = Maxiosize;
274 rep->msize = req->msize;
275 rep->version = "9P2000";
281 error("9660srv: authentication not required");
296 chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
297 req->fid, req->uname, req->aname);
300 xfile(req->fid, Clunk);
303 root = xfile(req->fid, Clean);
304 root->qid = (Qid){0, 0, QTDIR};
305 root->xf = xf = ealloc(sizeof(Xfs));
306 memset(xf, 0, sizeof(Xfs));
308 xf->d = getxdata(req->aname);
310 for(xs=xsublist; *xs; xs++)
311 if((*(*xs)->attach)(root) >= 0){
314 xf->rootqid = root->qid;
315 rep->qid = root->qid;
318 error("unknown format");
322 doclone(Xfile *of, int newfid)
326 nf = xfile(newfid, Clean);
328 xfile(newfid, Clunk);
337 nf->ptr = ealloc(nf->len);
338 memmove(nf->ptr, of->ptr, nf->len);
341 (*of->xf->s->clone)(of, nf);
356 f = xfile(req->fid, Asis);
357 if(req->fid != req->newfid)
358 f = nf = doclone(f, req->newfid);
360 /* save old state in case of error */
365 oldptr = ealloc(oldlen);
366 memmove(oldptr, f->ptr, oldlen);
371 xfile(req->newfid, Clunk);
372 if(rep->nwqid == req->nwname){
376 /* restore previous state */
383 if(rep->nwqid==req->nwname || rep->nwqid > 0){
390 for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
391 chat("\twalking %s\n", req->wname[rep->nwqid]);
392 if(!(f->qid.type & QTDIR)){
393 chat("\tnot dir: type=%#x\n", f->qid.type);
394 error("walk in non-directory");
397 if(strcmp(req->wname[rep->nwqid], "..")==0){
398 if(f->qid.path != f->xf->rootqid.path)
399 (*f->xf->s->walkup)(f);
401 (*f->xf->s->walk)(f, req->wname[rep->nwqid]);
402 rep->wqid[rep->nwqid] = f->qid;
414 f = xfile(req->fid, Asis);
416 error("open on open file");
417 if(req->mode&ORCLOSE)
419 (*f->xf->s->open)(f, req->mode);
420 f->flags = openflags(req->mode);
432 if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
433 error("create . or ..");
434 f = xfile(req->fid, Asis);
436 error("create on open file");
437 if(!(f->qid.path&CHDIR))
438 error("create in non-directory");
439 (*f->xf->s->create)(f, req->name, req->perm, req->mode);
440 chat("f->qid=0x%8.8lux...", f->qid.path);
441 f->flags = openflags(req->mode);
451 f=xfile(req->fid, Asis);
452 if (!(f->flags&Oread))
453 error("file not opened for reading");
454 if(f->qid.type & QTDIR)
455 rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
457 rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
466 f=xfile(req->fid, Asis);
467 if(!(f->flags&Owrite))
468 error("file not opened for writing");
469 rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
478 f = xfile(req->fid, Asis);
479 (*f->xf->s->clunk)(f);
482 xfile(req->fid, Clunk);
497 chat("stat(fid=%d)...", req->fid);
498 f=xfile(req->fid, Asis);
499 setnames(&dir, fdata);
500 (*f->xf->s->stat)(f, &dir);
503 rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
518 switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
521 flags = Oread; break;
523 flags = Owrite; break;
525 flags = Oread|Owrite; break;
533 showdir(int fd, Dir *s)
535 char a_time[32], m_time[32];
538 strcpy(a_time, ctime(s->atime));
539 if(p=strchr(a_time, '\n')) /* assign = */
541 strcpy(m_time, ctime(s->mtime));
542 if(p=strchr(m_time, '\n')) /* assign = */
544 fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
545 mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
546 s->name, s->qid.path, s->qid.vers, s->type, s->dev,
548 a_time, m_time, s->length, s->uid, s->gid);
560 vfprint(2, fmt, arg);
566 panic(int rflag, char *fmt, ...)
569 char buf[SIZE]; int n;
571 n = sprint(buf, "%s %d: ", argv0, getpid());
573 vseprint(buf+n, buf+SIZE, fmt, arg);
575 fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
577 fprint(2, "abort\n");