mntgen.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <fcall.h>
  4. #include <thread.h>
  5. #include <9p.h>
  6. #include <mp.h>
  7. #include <libsec.h>
  8. static void
  9. usage(void)
  10. {
  11. fprint(2, "mntgen [-s srvname] [mtpt]\n");
  12. exits("usage");
  13. }
  14. ulong time0;
  15. typedef struct Tab Tab;
  16. struct Tab
  17. {
  18. char *name;
  19. vlong qid;
  20. ulong time;
  21. int ref;
  22. };
  23. Tab *tab;
  24. int ntab;
  25. int mtab;
  26. static Tab*
  27. findtab(vlong path)
  28. {
  29. int i;
  30. for(i=0; i<ntab; i++)
  31. if(tab[i].qid == path)
  32. return &tab[i];
  33. return nil;
  34. }
  35. static vlong
  36. hash(char *name)
  37. {
  38. vlong digest[MD5dlen / sizeof(vlong) + 1];
  39. md5((uchar *)name, strlen(name), (uchar *)digest, nil);
  40. return digest[0] & ((1ULL<<48)-1);
  41. }
  42. static void
  43. fsopen(Req *r)
  44. {
  45. if(r->ifcall.mode != OREAD)
  46. respond(r, "permission denied");
  47. else
  48. respond(r, nil);
  49. }
  50. static int
  51. dirgen(int i, Dir *d, void*)
  52. {
  53. if(i >= ntab)
  54. return -1;
  55. memset(d, 0, sizeof *d);
  56. d->qid.type = QTDIR;
  57. d->uid = estrdup9p("sys");
  58. d->gid = estrdup9p("sys");
  59. d->mode = DMDIR|0555;
  60. d->length = 0;
  61. if(i == -1){
  62. d->name = estrdup9p("/");
  63. d->atime = d->mtime = time0;
  64. }else{
  65. d->qid.path = tab[i].qid;
  66. d->name = estrdup9p(tab[i].name);
  67. d->atime = d->mtime = tab[i].time;
  68. }
  69. return 0;
  70. }
  71. static void
  72. fsread(Req *r)
  73. {
  74. if(r->fid->qid.path == 0)
  75. dirread9p(r, dirgen, nil);
  76. else
  77. r->ofcall.count = 0;
  78. respond(r, nil);
  79. }
  80. static void
  81. fsstat(Req *r)
  82. {
  83. Tab *t;
  84. vlong qid;
  85. qid = r->fid->qid.path;
  86. if(qid == 0)
  87. dirgen(-1, &r->d, nil);
  88. else{
  89. if((t = findtab(qid)) == nil){
  90. respond(r, "path not found (???)");
  91. return;
  92. }
  93. dirgen(t-tab, &r->d, nil);
  94. }
  95. respond(r, nil);
  96. }
  97. static char*
  98. fswalk1(Fid *fid, char *name, void*)
  99. {
  100. int i;
  101. Tab *t;
  102. vlong h;
  103. if(fid->qid.path != 0){
  104. /* nothing in child directory */
  105. if(strcmp(name, "..") == 0){
  106. if((t = findtab(fid->qid.path)) != nil)
  107. t->ref--;
  108. fid->qid.path = 0;
  109. return nil;
  110. }
  111. return "path not found";
  112. }
  113. /* root */
  114. if(strcmp(name, "..") == 0)
  115. return nil;
  116. for(i=0; i<ntab; i++)
  117. if(strcmp(tab[i].name, name) == 0){
  118. tab[i].ref++;
  119. fid->qid.path = tab[i].qid;
  120. return nil;
  121. }
  122. h = hash(name);
  123. if(findtab(h) != nil)
  124. return "hash collision";
  125. /* create it */
  126. if(ntab == mtab){
  127. if(mtab == 0)
  128. mtab = 16;
  129. else
  130. mtab *= 2;
  131. tab = erealloc9p(tab, sizeof(tab[0])*mtab);
  132. }
  133. tab[ntab].qid = h;
  134. fid->qid.path = tab[ntab].qid;
  135. tab[ntab].name = estrdup9p(name);
  136. tab[ntab].time = time(0);
  137. tab[ntab].ref = 1;
  138. ntab++;
  139. return nil;
  140. }
  141. static char*
  142. fsclone(Fid *fid, Fid*, void*)
  143. {
  144. Tab *t;
  145. if((t = findtab(fid->qid.path)) != nil)
  146. t->ref++;
  147. return nil;
  148. }
  149. static void
  150. fswalk(Req *r)
  151. {
  152. walkandclone(r, fswalk1, fsclone, nil);
  153. }
  154. static void
  155. fsclunk(Fid *fid)
  156. {
  157. Tab *t;
  158. vlong qid;
  159. qid = fid->qid.path;
  160. if(qid == 0)
  161. return;
  162. if((t = findtab(qid)) == nil){
  163. fprint(2, "warning: cannot find %llux\n", qid);
  164. return;
  165. }
  166. if(--t->ref == 0){
  167. free(t->name);
  168. tab[t-tab] = tab[--ntab];
  169. }else if(t->ref < 0)
  170. fprint(2, "warning: negative ref count for %s\n", t->name);
  171. }
  172. static void
  173. fsattach(Req *r)
  174. {
  175. char *spec;
  176. spec = r->ifcall.aname;
  177. if(spec && spec[0]){
  178. respond(r, "invalid attach specifier");
  179. return;
  180. }
  181. r->ofcall.qid = (Qid){0, 0, QTDIR};
  182. r->fid->qid = r->ofcall.qid;
  183. respond(r, nil);
  184. }
  185. Srv fs=
  186. {
  187. .attach= fsattach,
  188. .open= fsopen,
  189. .read= fsread,
  190. .stat= fsstat,
  191. .walk= fswalk,
  192. .destroyfid= fsclunk
  193. };
  194. void
  195. main(int argc, char **argv)
  196. {
  197. char *service;
  198. time0 = time(0);
  199. service = nil;
  200. ARGBEGIN{
  201. case 'D':
  202. chatty9p++;
  203. break;
  204. case 's':
  205. service = EARGF(usage());
  206. break;
  207. default:
  208. usage();
  209. }ARGEND
  210. if(argc > 1)
  211. usage();
  212. postmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER);
  213. exits(nil);
  214. }