mntgen.c 4.0 KB

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