xfssrv.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include "iotrack.h"
  6. #include "dat.h"
  7. #include "dosfs.h"
  8. #include "fns.h"
  9. #include "errstr.h"
  10. #define Reqsize (sizeof(Fcall)+Maxfdata)
  11. Fcall *req;
  12. Fcall *rep;
  13. uchar mdata[Maxiosize];
  14. char repdata[Maxfdata];
  15. uchar statbuf[STATMAX];
  16. int errno;
  17. char errbuf[ERRMAX];
  18. void rmservice(void);
  19. char srvfile[64];
  20. char *deffile;
  21. int doabort;
  22. int trspaces;
  23. void (*fcalls[])(void) = {
  24. [Tversion] rversion,
  25. [Tflush] rflush,
  26. [Tauth] rauth,
  27. [Tattach] rattach,
  28. [Twalk] rwalk,
  29. [Topen] ropen,
  30. [Tcreate] rcreate,
  31. [Tread] rread,
  32. [Twrite] rwrite,
  33. [Tclunk] rclunk,
  34. [Tremove] rremove,
  35. [Tstat] rstat,
  36. [Twstat] rwstat,
  37. };
  38. void
  39. usage(void)
  40. {
  41. fprint(2, "usage: %s [-v] [-s] [-f devicefile] [srvname]\n", argv0);
  42. exits("usage");
  43. }
  44. void
  45. main(int argc, char **argv)
  46. {
  47. int stdio, srvfd, pipefd[2];
  48. rep = malloc(sizeof(Fcall));
  49. req = malloc(Reqsize);
  50. if(rep == nil || req == nil)
  51. panic("out of memory");
  52. stdio = 0;
  53. ARGBEGIN{
  54. case ':':
  55. trspaces = 1;
  56. break;
  57. case 'r':
  58. readonly = 1;
  59. break;
  60. case 'v':
  61. ++chatty;
  62. break;
  63. case 'f':
  64. deffile = ARGF();
  65. break;
  66. case 's':
  67. stdio = 1;
  68. break;
  69. case 'p':
  70. doabort = 1;
  71. break;
  72. default:
  73. usage();
  74. }ARGEND
  75. if(argc == 0)
  76. strcpy(srvfile, "#s/dos");
  77. else if(argc == 1)
  78. snprint(srvfile, sizeof srvfile, "#s/%s", argv[0]);
  79. else
  80. usage();
  81. if(stdio){
  82. pipefd[0] = 0;
  83. pipefd[1] = 1;
  84. }else{
  85. close(0);
  86. close(1);
  87. open("/dev/null", OREAD);
  88. open("/dev/null", OWRITE);
  89. if(pipe(pipefd) < 0)
  90. panic("pipe");
  91. srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
  92. if(srvfd < 0)
  93. panic(srvfile);
  94. fprint(srvfd, "%d", pipefd[0]);
  95. close(pipefd[0]);
  96. atexit(rmservice);
  97. fprint(2, "%s: serving %s\n", argv0, srvfile);
  98. }
  99. srvfd = pipefd[1];
  100. switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){
  101. case -1:
  102. panic("fork");
  103. default:
  104. _exits(0);
  105. case 0:
  106. break;
  107. }
  108. iotrack_init();
  109. if(!chatty){
  110. close(2);
  111. open("#c/cons", OWRITE);
  112. }
  113. io(srvfd);
  114. exits(0);
  115. }
  116. void
  117. io(int srvfd)
  118. {
  119. int n, pid;
  120. pid = getpid();
  121. fmtinstall('F', fcallfmt);
  122. for(;;){
  123. /*
  124. * reading from a pipe or a network device
  125. * will give an error after a few eof reads.
  126. * however, we cannot tell the difference
  127. * between a zero-length read and an interrupt
  128. * on the processes writing to us,
  129. * so we wait for the error.
  130. */
  131. n = read9pmsg(srvfd, mdata, sizeof mdata);
  132. if(n < 0)
  133. break;
  134. if(n == 0)
  135. continue;
  136. if(convM2S(mdata, n, req) == 0)
  137. continue;
  138. if(chatty)
  139. fprint(2, "dossrv %d:<-%F\n", pid, req);
  140. errno = 0;
  141. if(!fcalls[req->type])
  142. errno = Ebadfcall;
  143. else
  144. (*fcalls[req->type])();
  145. if(errno){
  146. rep->type = Rerror;
  147. rep->ename = xerrstr(errno);
  148. }else{
  149. rep->type = req->type + 1;
  150. rep->fid = req->fid;
  151. }
  152. rep->tag = req->tag;
  153. if(chatty)
  154. fprint(2, "dossrv %d:->%F\n", pid, rep);
  155. n = convS2M(rep, mdata, sizeof mdata);
  156. if(n == 0)
  157. panic("convS2M error on write");
  158. if(write(srvfd, mdata, n) != n)
  159. panic("mount write");
  160. }
  161. chat("server shut down");
  162. }
  163. void
  164. rmservice(void)
  165. {
  166. remove(srvfile);
  167. }
  168. char *
  169. xerrstr(int e)
  170. {
  171. if (e < 0 || e >= sizeof errmsg/sizeof errmsg[0])
  172. return "no such error";
  173. if(e == Eerrstr){
  174. errstr(errbuf, sizeof errbuf);
  175. return errbuf;
  176. }
  177. return errmsg[e];
  178. }
  179. int
  180. eqqid(Qid q1, Qid q2)
  181. {
  182. return q1.path == q2.path && q1.type == q2.type && q1.vers == q2.vers;
  183. }