diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/dossrv/xfssrv.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/dossrv/xfssrv.c')
-rwxr-xr-x | sys/src/cmd/dossrv/xfssrv.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/sys/src/cmd/dossrv/xfssrv.c b/sys/src/cmd/dossrv/xfssrv.c new file mode 100755 index 000000000..3766a170d --- /dev/null +++ b/sys/src/cmd/dossrv/xfssrv.c @@ -0,0 +1,204 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <fcall.h> +#include "iotrack.h" +#include "dat.h" +#include "dosfs.h" +#include "fns.h" + +#include "errstr.h" + +#define Reqsize (sizeof(Fcall)+Maxfdata) +Fcall *req; +Fcall *rep; + +uchar mdata[Maxiosize]; +char repdata[Maxfdata]; +uchar statbuf[STATMAX]; +int errno; +char errbuf[ERRMAX]; +void rmservice(void); +char srvfile[64]; +char *deffile; +int doabort; +int trspaces; + +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 +usage(void) +{ + fprint(2, "usage: %s [-v] [-s] [-f devicefile] [srvname]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int stdio, srvfd, pipefd[2]; + + rep = malloc(sizeof(Fcall)); + req = malloc(Reqsize); + if(rep == nil || req == nil) + panic("out of memory"); + stdio = 0; + ARGBEGIN{ + case ':': + trspaces = 1; + break; + case 'r': + readonly = 1; + break; + case 'v': + ++chatty; + break; + case 'f': + deffile = ARGF(); + break; + case 's': + stdio = 1; + break; + case 'p': + doabort = 1; + break; + default: + usage(); + }ARGEND + + if(argc == 0) + strcpy(srvfile, "#s/dos"); + else if(argc == 1) + snprint(srvfile, sizeof srvfile, "#s/%s", argv[0]); + else + usage(); + + 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("pipe"); + srvfd = create(srvfile, OWRITE|ORCLOSE, 0600); + if(srvfd < 0) + panic(srvfile); + fprint(srvfd, "%d", pipefd[0]); + close(pipefd[0]); + atexit(rmservice); + fprint(2, "%s: serving %s\n", argv0, srvfile); + } + srvfd = pipefd[1]; + + switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){ + case -1: + panic("fork"); + default: + _exits(0); + case 0: + break; + } + + iotrack_init(); + + if(!chatty){ + close(2); + open("#c/cons", OWRITE); + } + + io(srvfd); + exits(0); +} + +void +io(int srvfd) +{ + int n, pid; + + 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, "dossrv %d:<-%F\n", pid, req); + + errno = 0; + if(!fcalls[req->type]) + errno = Ebadfcall; + else + (*fcalls[req->type])(); + if(errno){ + rep->type = Rerror; + rep->ename = xerrstr(errno); + }else{ + rep->type = req->type + 1; + rep->fid = req->fid; + } + rep->tag = req->tag; + if(chatty) + fprint(2, "dossrv %d:->%F\n", pid, rep); + n = convS2M(rep, mdata, sizeof mdata); + if(n == 0) + panic("convS2M error on write"); + if(write(srvfd, mdata, n) != n) + panic("mount write"); + } + chat("server shut down"); +} + +void +rmservice(void) +{ + remove(srvfile); +} + +char * +xerrstr(int e) +{ + if (e < 0 || e >= sizeof errmsg/sizeof errmsg[0]) + return "no such error"; + if(e == Eerrstr){ + errstr(errbuf, sizeof errbuf); + return errbuf; + } + return errmsg[e]; +} + +int +eqqid(Qid q1, Qid q2) +{ + return q1.path == q2.path && q1.type == q2.type && q1.vers == q2.vers; +} |