fcall.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include "9p1.h"
  6. #define MAXFDATA (8*1024)
  7. #define MAXRPC (MAXFDATA+160)
  8. /*
  9. * reassemble 9P messages for stream based protocols
  10. * interposed between devmnt and the network by srv for tcp connections
  11. * fcall expects devmnt on fd0, network fd1
  12. */
  13. uchar msglen[256] =
  14. {
  15. [Tnop9p1] 3,
  16. [Rnop9p1] 3,
  17. [Tsession9p1] 3+CHALLEN,
  18. [Rsession9p1] 3+NAMEREC+DOMLEN+CHALLEN,
  19. [Terror9p1] 0,
  20. [Rerror9p1] 67,
  21. [Tflush9p1] 5,
  22. [Rflush9p1] 3,
  23. [Tattach9p1] 5+2*NAMEREC+TICKETLEN+AUTHENTLEN,
  24. [Rattach9p1] 13+AUTHENTLEN,
  25. [Tclone9p1] 7,
  26. [Rclone9p1] 5,
  27. [Twalk9p1] 33,
  28. [Rwalk9p1] 13,
  29. [Topen9p1] 6,
  30. [Ropen9p1] 13,
  31. [Tcreate9p1] 38,
  32. [Rcreate9p1] 13,
  33. [Tread9p1] 15,
  34. [Rread9p1] 8,
  35. [Twrite9p1] 16,
  36. [Rwrite9p1] 7,
  37. [Tclunk9p1] 5,
  38. [Rclunk9p1] 5,
  39. [Tremove9p1] 5,
  40. [Rremove9p1] 5,
  41. [Tstat9p1] 5,
  42. [Rstat9p1] 121,
  43. [Twstat9p1] 121,
  44. [Rwstat9p1] 5,
  45. [Tclwalk9p1] 35,
  46. [Rclwalk9p1] 13,
  47. };
  48. enum
  49. {
  50. Twritehdr = 16, /* Min bytes for Twrite */
  51. Rreadhdr = 8, /* Min bytes for Rread */
  52. Twritecnt = 13, /* Offset in byte stream of write count */
  53. Rreadcnt = 5, /* Offset for Readcnt */
  54. };
  55. int
  56. mntrpclen(uchar *d, int n)
  57. {
  58. uchar t;
  59. int len, off;
  60. if(n < 1)
  61. return 0;
  62. t = d[0];
  63. switch(t) { /* This is the type */
  64. default:
  65. len = msglen[t];
  66. if(len == 0) /* Illegal type so consume */
  67. return n;
  68. if(n < len)
  69. return 0;
  70. return len;
  71. case Twrite9p1: /* Fmt: TGGFFOOOOOOOOCC */
  72. len = Twritehdr; /* T = type, G = tag, F = fid */
  73. off = Twritecnt; /* O = offset, C = count */
  74. break;
  75. case Rread9p1: /* Fmt: TGGFFCC */
  76. len = Rreadhdr;
  77. off = Rreadcnt;
  78. break;
  79. }
  80. if(n < off+2)
  81. return 0;
  82. len += d[off]|(d[off+1]<<8);
  83. if(n < len)
  84. return 0;
  85. return len;
  86. }
  87. int
  88. fcall(int fd)
  89. {
  90. int i, r, n, l;
  91. uchar *p, *buf;
  92. int pipefd[2];
  93. if(pipe(pipefd) < 0)
  94. fatal("fcall pipe: %r");
  95. buf = malloc(MAXRPC);
  96. if(buf == nil)
  97. fatal("fcall malloc");
  98. switch(rfork(RFPROC|RFMEM|RFFDG|RFCNAMEG)){
  99. default:
  100. return pipefd[0]; /* parent returns fd */
  101. case 0:
  102. break; /* child builds buffers */
  103. case -1:
  104. fatal("fcall fork: %r");
  105. }
  106. /* close file descriptors */
  107. for(i=0; i<20; i++)
  108. if(i!=fd && i!=pipefd[1])
  109. close(i);
  110. l = MAXRPC;
  111. p = buf;
  112. for(;;) {
  113. n = read(fd, p, l);
  114. if(n < 0)
  115. break;
  116. p += n;
  117. l -= n;
  118. for(;;) {
  119. r = mntrpclen(buf, p - buf);
  120. if(r == 0)
  121. break;
  122. if(write(pipefd[1], buf, r) < 0)
  123. break;
  124. n = (p - buf) - r;
  125. memmove(buf, buf+r, n);
  126. p = buf+n;
  127. l = MAXRPC - n;
  128. }
  129. }
  130. close(pipefd[1]);
  131. fatal(nil);
  132. return -1;
  133. }