123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include "dat.h"
- #include "fns.h"
- enum
- {
- Maxfdata = 8192,
- Maxiosize = IOHDRSZ+Maxfdata,
- };
- void io(int);
- void rversion(void);
- void rattach(void);
- void rauth(void);
- void rclunk(void);
- void rcreate(void);
- void rflush(void);
- void ropen(void);
- void rread(void);
- void rremove(void);
- void rsession(void);
- void rstat(void);
- void rwalk(void);
- void rwrite(void);
- void rwstat(void);
- static int openflags(int);
- static void rmservice(void);
- static void usage(void);
- #define Reqsize (sizeof(Fcall)+Maxfdata)
- Fcall *req;
- Fcall *rep;
- uchar mdata[Maxiosize];
- char fdata[Maxfdata];
- uchar statbuf[STATMAX];
- int errno;
- static char srvfile[64];
- extern Xfsub *xsublist[];
- extern int nclust;
- jmp_buf err_lab[16];
- int nerr_lab;
- char err_msg[ERRMAX];
- int chatty;
- int nojoliet;
- int noplan9;
- int norock;
- void (*fcalls[])(void) = {
- [Tversion] rversion,
- [Tflush] rflush,
- [Tauth] rauth,
- [Tattach] rattach,
- [Twalk] rwalk,
- [Topen] ropen,
- [Tcreate] rcreate,
- [Tread] rread,
- [Twrite] rwrite,
- [Tclunk] rclunk,
- [Tremove] rremove,
- [Tstat] rstat,
- [Twstat] rwstat,
- };
- void
- main(int argc, char **argv)
- {
- int srvfd, pipefd[2], stdio;
- Xfsub **xs;
- stdio = 0;
- ARGBEGIN {
- case '9':
- noplan9 = 1;
- break;
- case 'c':
- nclust = atoi(EARGF(usage()));
- if (nclust <= 0)
- sysfatal("nclust %d non-positive", nclust);
- break;
- case 'f':
- deffile = EARGF(usage());
- break;
- case 'r':
- norock = 1;
- break;
- case 's':
- stdio = 1;
- break;
- case 'v':
- chatty = 1;
- break;
- case 'J':
- nojoliet = 1;
- break;
- default:
- usage();
- } ARGEND
- switch(argc) {
- case 0:
- break;
- case 1:
- srvname = argv[0];
- break;
- default:
- usage();
- }
- iobuf_init();
- for(xs=xsublist; *xs; xs++)
- (*(*xs)->reset)();
- if(stdio) {
- pipefd[0] = 0;
- pipefd[1] = 1;
- } else {
- close(0);
- close(1);
- open("/dev/null", OREAD);
- open("/dev/null", OWRITE);
- if(pipe(pipefd) < 0)
- panic(1, "pipe");
- sprint(srvfile, "/srv/%s", srvname);
- srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
- if(srvfd < 0)
- panic(1, srvfile);
- fprint(srvfd, "%d", pipefd[0]);
- close(pipefd[0]);
- fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);
- }
- srvfd = pipefd[1];
- switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
- case -1:
- panic(1, "fork");
- default:
- _exits(0);
- case 0:
- break;
- }
- io(srvfd);
- exits(0);
- }
- void
- io(int srvfd)
- {
- int n, pid;
- Fcall xreq, xrep;
- req = &xreq;
- rep = &xrep;
- pid = getpid();
- fmtinstall('F', fcallfmt);
- for(;;){
- /*
- * reading from a pipe or a network device
- * will give an error after a few eof reads.
- * however, we cannot tell the difference
- * between a zero-length read and an interrupt
- * on the processes writing to us,
- * so we wait for the error.
- */
- n = read9pmsg(srvfd, mdata, sizeof mdata);
- if(n < 0)
- break;
- if(n == 0)
- continue;
- if(convM2S(mdata, n, req) == 0)
- continue;
- if(chatty)
- fprint(2, "9660srv %d:<-%F\n", pid, req);
- errno = 0;
- if(!waserror()){
- err_msg[0] = 0;
- if(req->type >= nelem(fcalls) || !fcalls[req->type])
- error("bad fcall type");
- (*fcalls[req->type])();
- poperror();
- }
- if(err_msg[0]){
- rep->type = Rerror;
- rep->ename = err_msg;
- }else{
- rep->type = req->type + 1;
- rep->fid = req->fid;
- }
- rep->tag = req->tag;
- if(chatty)
- fprint(2, "9660srv %d:->%F\n", pid, rep);
- n = convS2M(rep, mdata, sizeof mdata);
- if(n == 0)
- panic(1, "convS2M error on write");
- if(write(srvfd, mdata, n) != n)
- panic(1, "mount write");
- if(nerr_lab != 0)
- panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", nerr_lab,
- err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],
- err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],
- err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);
- }
- chat("server shut down");
- }
- static void
- usage(void)
- {
- fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
- exits("usage");
- }
- void
- error(char *p)
- {
- strecpy(err_msg, err_msg+sizeof err_msg, p);
- nexterror();
- }
- void
- nexterror(void)
- {
- longjmp(err_lab[--nerr_lab], 1);
- }
- void*
- ealloc(long n)
- {
- void *p;
- p = malloc(n);
- if(p == 0)
- error("no memory");
- return p;
- }
- void
- setnames(Dir *d, char *n)
- {
- d->name = n;
- d->uid = n+Maxname;
- d->gid = n+Maxname*2;
- d->muid = n+Maxname*3;
- d->name[0] = '\0';
- d->uid[0] = '\0';
- d->gid[0] = '\0';
- d->muid[0] = '\0';
- }
- void
- rversion(void)
- {
- if(req->msize > Maxiosize)
- rep->msize = Maxiosize;
- else
- rep->msize = req->msize;
- rep->version = "9P2000";
- }
- void
- rauth(void)
- {
- error("9660srv: authentication not required");
- }
- void
- rflush(void)
- {
- }
- void
- rattach(void)
- {
- Xfs *xf;
- Xfile *root;
- Xfsub **xs;
- chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
- req->fid, req->uname, req->aname);
- if(waserror()){
- xfile(req->fid, Clunk);
- nexterror();
- }
- root = xfile(req->fid, Clean);
- root->qid = (Qid){0, 0, QTDIR};
- root->xf = xf = ealloc(sizeof(Xfs));
- memset(xf, 0, sizeof(Xfs));
- xf->ref = 1;
- xf->d = getxdata(req->aname);
- for(xs=xsublist; *xs; xs++)
- if((*(*xs)->attach)(root) >= 0){
- poperror();
- xf->s = *xs;
- xf->rootqid = root->qid;
- rep->qid = root->qid;
- return;
- }
- error("unknown format");
- }
- Xfile*
- doclone(Xfile *of, int newfid)
- {
- Xfile *nf, *next;
- nf = xfile(newfid, Clean);
- if(waserror()){
- xfile(newfid, Clunk);
- nexterror();
- }
- next = nf->next;
- *nf = *of;
- nf->next = next;
- nf->fid = newfid;
- refxfs(nf->xf, 1);
- if(nf->len){
- nf->ptr = ealloc(nf->len);
- memmove(nf->ptr, of->ptr, nf->len);
- }else
- nf->ptr = of->ptr;
- (*of->xf->s->clone)(of, nf);
- poperror();
- return nf;
- }
- void
- rwalk(void)
- {
- Xfile *f, *nf;
- Isofile *oldptr;
- int oldlen;
- Qid oldqid;
- rep->nwqid = 0;
- nf = nil;
- f = xfile(req->fid, Asis);
- if(req->fid != req->newfid)
- f = nf = doclone(f, req->newfid);
- /* save old state in case of error */
- oldqid = f->qid;
- oldlen = f->len;
- oldptr = f->ptr;
- if(oldlen){
- oldptr = ealloc(oldlen);
- memmove(oldptr, f->ptr, oldlen);
- }
- if(waserror()){
- if(nf != nil)
- xfile(req->newfid, Clunk);
- if(rep->nwqid == req->nwname){
- if(oldlen)
- free(oldptr);
- }else{
- /* restore previous state */
- f->qid = oldqid;
- if(f->len)
- free(f->ptr);
- f->ptr = oldptr;
- f->len = oldlen;
- }
- if(rep->nwqid==req->nwname || rep->nwqid > 0){
- err_msg[0] = '\0';
- return;
- }
- nexterror();
- }
- for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
- chat("\twalking %s\n", req->wname[rep->nwqid]);
- if(!(f->qid.type & QTDIR)){
- chat("\tnot dir: type=%#x\n", f->qid.type);
- error("walk in non-directory");
- }
- if(strcmp(req->wname[rep->nwqid], "..")==0){
- if(f->qid.path != f->xf->rootqid.path)
- (*f->xf->s->walkup)(f);
- }else
- (*f->xf->s->walk)(f, req->wname[rep->nwqid]);
- rep->wqid[rep->nwqid] = f->qid;
- }
- poperror();
- if(oldlen)
- free(oldptr);
- }
- void
- ropen(void)
- {
- Xfile *f;
- f = xfile(req->fid, Asis);
- if(f->flags&Omodes)
- error("open on open file");
- if(req->mode&ORCLOSE)
- error("no removes");
- (*f->xf->s->open)(f, req->mode);
- f->flags = openflags(req->mode);
- rep->qid = f->qid;
- rep->iounit = 0;
- }
- void
- rcreate(void)
- {
- error("no creates");
- /*
- Xfile *f;
- if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
- error("create . or ..");
- f = xfile(req->fid, Asis);
- if(f->flags&Omodes)
- error("create on open file");
- if(!(f->qid.path&CHDIR))
- error("create in non-directory");
- (*f->xf->s->create)(f, req->name, req->perm, req->mode);
- chat("f->qid=0x%8.8lux...", f->qid.path);
- f->flags = openflags(req->mode);
- rep->qid = f->qid;
- */
- }
- void
- rread(void)
- {
- Xfile *f;
- f=xfile(req->fid, Asis);
- if (!(f->flags&Oread))
- error("file not opened for reading");
- if(f->qid.type & QTDIR)
- rep->count = (*f->xf->s->readdir)(f, (uchar*)fdata, req->offset, req->count);
- else
- rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
- rep->data = fdata;
- }
- void
- rwrite(void)
- {
- Xfile *f;
- f=xfile(req->fid, Asis);
- if(!(f->flags&Owrite))
- error("file not opened for writing");
- rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
- }
- void
- rclunk(void)
- {
- Xfile *f;
- if(!waserror()){
- f = xfile(req->fid, Asis);
- (*f->xf->s->clunk)(f);
- poperror();
- }
- xfile(req->fid, Clunk);
- }
- void
- rremove(void)
- {
- error("no removes");
- }
- void
- rstat(void)
- {
- Xfile *f;
- Dir dir;
- chat("stat(fid=%d)...", req->fid);
- f=xfile(req->fid, Asis);
- setnames(&dir, fdata);
- (*f->xf->s->stat)(f, &dir);
- if(chatty)
- showdir(2, &dir);
- rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
- rep->stat = statbuf;
- }
- void
- rwstat(void)
- {
- error("no wstat");
- }
- static int
- openflags(int mode)
- {
- int flags = 0;
- switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
- case OREAD:
- case OEXEC:
- flags = Oread; break;
- case OWRITE:
- flags = Owrite; break;
- case ORDWR:
- flags = Oread|Owrite; break;
- }
- if(mode & ORCLOSE)
- flags |= Orclose;
- return flags;
- }
- void
- showdir(int fd, Dir *s)
- {
- char a_time[32], m_time[32];
- char *p;
- strcpy(a_time, ctime(s->atime));
- if(p=strchr(a_time, '\n')) /* assign = */
- *p = 0;
- strcpy(m_time, ctime(s->mtime));
- if(p=strchr(m_time, '\n')) /* assign = */
- *p = 0;
- fprint(fd, "name=\"%s\" qid=(0x%llux,%lud) type=%d dev=%d \
- mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
- s->name, s->qid.path, s->qid.vers, s->type, s->dev,
- s->mode, s->mode,
- a_time, m_time, s->length, s->uid, s->gid);
- }
- #define SIZE 1024
- void
- chat(char *fmt, ...)
- {
- va_list arg;
- if(chatty){
- va_start(arg, fmt);
- vfprint(2, fmt, arg);
- va_end(arg);
- }
- }
- void
- panic(int rflag, char *fmt, ...)
- {
- va_list arg;
- char buf[SIZE]; int n;
- n = sprint(buf, "%s %d: ", argv0, getpid());
- va_start(arg, fmt);
- vseprint(buf+n, buf+SIZE, fmt, arg);
- va_end(arg);
- fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
- if(chatty){
- fprint(2, "abort\n");
- abort();
- }
- exits("panic");
- }
|