mntgen.c 3.3 KB

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