fs.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * ``Exec'' network device. Mounted on net, provides /net/exec.
  3. *
  4. * exec protocol directory
  5. * n connection directory
  6. * ctl control messages (like connect)
  7. * data data
  8. * err errors
  9. * local local address (pid of command)
  10. * remote remote address (command)
  11. * status status
  12. */
  13. #include <u.h>
  14. #include <libc.h>
  15. #include <fcall.h>
  16. #include <thread.h>
  17. #include <9p.h>
  18. #include "dat.h"
  19. int fsdebug;
  20. enum
  21. {
  22. Qroot,
  23. Qexec,
  24. Qclone,
  25. Qn,
  26. Qctl,
  27. Qdata,
  28. Qlocal,
  29. Qremote,
  30. Qstatus,
  31. };
  32. #define PATH(type, n) ((type)|((n)<<8))
  33. #define TYPE(path) ((int)(path) & 0xFF)
  34. #define NUM(path) ((uint)(path)>>8)
  35. typedef struct Tab Tab;
  36. struct Tab
  37. {
  38. char *name;
  39. ulong mode;
  40. };
  41. Tab tab[] =
  42. {
  43. "/", DMDIR|0555,
  44. "exec", DMDIR|0555,
  45. "clone", 0666,
  46. nil, DMDIR|0555,
  47. "ctl", 0666,
  48. "data", 0666,
  49. "local", 0444,
  50. "remote", 0444,
  51. "status", 0444,
  52. };
  53. void
  54. setexecname(char *s)
  55. {
  56. tab[Qexec].name = s;
  57. }
  58. ulong time0;
  59. static void
  60. fillstat(Dir *d, ulong path)
  61. {
  62. Tab *t;
  63. int type;
  64. char buf[32];
  65. memset(d, 0, sizeof(*d));
  66. d->uid = estrdup("exec");
  67. d->gid = estrdup("exec");
  68. d->qid.path = path;
  69. d->atime = d->mtime = time0;
  70. d->length = 0;
  71. type = TYPE(path);
  72. t = &tab[type];
  73. if(t->name)
  74. d->name = estrdup(t->name);
  75. else{
  76. snprint(buf, sizeof buf, "%ud", NUM(path));
  77. d->name = estrdup(buf);
  78. }
  79. d->qid.type = t->mode>>24;
  80. d->mode = t->mode;
  81. }
  82. static void
  83. fsstat(Req *r)
  84. {
  85. fillstat(&r->d, r->fid->qid.path);
  86. respond(r, nil);
  87. }
  88. static int
  89. rootgen(int i, Dir *d, void*)
  90. {
  91. if(i < 1){
  92. fillstat(d, PATH(Qexec, 0));
  93. return 0;
  94. }
  95. return -1;
  96. }
  97. static int
  98. execgen(int i, Dir *d, void*)
  99. {
  100. if(i < 1){
  101. fillstat(d, PATH(Qclone, 0));
  102. return 0;
  103. }
  104. i -= 1;
  105. if(i < nclient){
  106. fillstat(d, PATH(Qn, i));
  107. return 0;
  108. }
  109. return -1;
  110. }
  111. static int
  112. conngen(int i, Dir *d, void *aux)
  113. {
  114. Client *c;
  115. c = aux;
  116. i += Qn+1;
  117. if(i <= Qstatus){
  118. fillstat(d, PATH(i, c->num));
  119. return 0;
  120. }
  121. return -1;
  122. }
  123. char *statusstr[] =
  124. {
  125. "Closed",
  126. "Exec",
  127. "Established",
  128. "Hangup",
  129. };
  130. static void
  131. fsread(Req *r)
  132. {
  133. char e[ERRMAX], *s;
  134. ulong path;
  135. path = r->fid->qid.path;
  136. switch(TYPE(path)){
  137. default:
  138. snprint(e, sizeof e, "bug in execnet path=%lux", path);
  139. respond(r, e);
  140. break;
  141. case Qroot:
  142. dirread9p(r, rootgen, nil);
  143. respond(r, nil);
  144. break;
  145. case Qexec:
  146. dirread9p(r, execgen, nil);
  147. respond(r, nil);
  148. break;
  149. case Qn:
  150. dirread9p(r, conngen, client[NUM(path)]);
  151. respond(r, nil);
  152. break;
  153. case Qctl:
  154. snprint(e, sizeof e, "%ud", NUM(path));
  155. readstr(r, e);
  156. respond(r, nil);
  157. break;
  158. case Qdata:
  159. dataread(r, client[NUM(path)]);
  160. break;
  161. case Qlocal:
  162. snprint(e, sizeof e, "%d", client[NUM(path)]->pid);
  163. readstr(r, e);
  164. respond(r, nil);
  165. break;
  166. case Qremote:
  167. s = client[NUM(path)]->cmd;
  168. if(strlen(s) >= 5) /* "exec " */
  169. readstr(r, s+5);
  170. else
  171. readstr(r, s);
  172. respond(r, nil);
  173. break;
  174. case Qstatus:
  175. readstr(r, statusstr[client[NUM(path)]->status]);
  176. respond(r, nil);
  177. break;
  178. }
  179. }
  180. static void
  181. fswrite(Req *r)
  182. {
  183. char e[ERRMAX];
  184. ulong path;
  185. path = r->fid->qid.path;
  186. switch(TYPE(path)){
  187. default:
  188. snprint(e, sizeof e, "bug in execnet path=%lux", path);
  189. respond(r, e);
  190. break;
  191. case Qctl:
  192. ctlwrite(r, client[NUM(path)]);
  193. break;
  194. case Qdata:
  195. datawrite(r, client[NUM(path)]);
  196. break;
  197. }
  198. }
  199. static void
  200. fsflush(Req *r)
  201. {
  202. ulong path;
  203. Req *or;
  204. for(or=r; or->ifcall.type==Tflush; or=or->oldreq)
  205. ;
  206. if(or->ifcall.type != Tread && or->ifcall.type != Twrite)
  207. abort();
  208. path = or->fid->qid.path;
  209. if(TYPE(path) != Qdata)
  210. abort();
  211. clientflush(or, client[NUM(path)]);
  212. }
  213. static void
  214. fsattach(Req *r)
  215. {
  216. if(r->ifcall.aname && r->ifcall.aname[0]){
  217. respond(r, "invalid attach specifier");
  218. return;
  219. }
  220. r->fid->qid.path = PATH(Qroot, 0);
  221. r->fid->qid.type = QTDIR;
  222. r->fid->qid.vers = 0;
  223. r->ofcall.qid = r->fid->qid;
  224. respond(r, nil);
  225. }
  226. static char*
  227. fswalk1(Fid *fid, char *name, Qid *qid)
  228. {
  229. char buf[32];
  230. int i, n;
  231. ulong path;
  232. if(!(fid->qid.type&QTDIR))
  233. return "walk in non-directory";
  234. path = fid->qid.path;
  235. if(strcmp(name, "..") == 0){
  236. switch(TYPE(path)){
  237. case Qn:
  238. qid->path = PATH(Qexec, 0);
  239. qid->type = QTDIR;
  240. return nil;
  241. case Qroot:
  242. case Qexec:
  243. qid->path = PATH(Qroot, 0);
  244. qid->type = QTDIR;
  245. return nil;
  246. default:
  247. return "bug in fswalk1";
  248. }
  249. }
  250. i = TYPE(path)+1;
  251. for(; i<nelem(tab); i++){
  252. if(i==Qn){
  253. n = atoi(name);
  254. snprint(buf, sizeof buf, "%d", n);
  255. if(n < nclient && strcmp(buf, name) == 0){
  256. qid->path = PATH(Qn, n);
  257. qid->type = QTDIR;
  258. return nil;
  259. }
  260. break;
  261. }
  262. if(strcmp(tab[i].name, name) == 0){
  263. qid->path = PATH(i, NUM(path));
  264. qid->type = tab[i].mode>>24;
  265. return nil;
  266. }
  267. if(tab[i].mode&DMDIR)
  268. break;
  269. }
  270. return "directory entry not found";
  271. }
  272. static void
  273. fsopen(Req *r)
  274. {
  275. static int need[4] = { 4, 2, 6, 1 };
  276. ulong path;
  277. int n;
  278. Tab *t;
  279. /*
  280. * lib9p already handles the blatantly obvious.
  281. * we just have to enforce the permissions we have set.
  282. */
  283. path = r->fid->qid.path;
  284. t = &tab[TYPE(path)];
  285. n = need[r->ifcall.mode&3];
  286. if((n&t->mode) != n){
  287. respond(r, "permission denied");
  288. return;
  289. }
  290. switch(TYPE(path)){
  291. case Qclone:
  292. n = newclient();
  293. path = PATH(Qctl, n);
  294. r->fid->qid.path = path;
  295. r->ofcall.qid.path = path;
  296. if(fsdebug)
  297. fprint(2, "open clone => path=%lux\n", path);
  298. t = &tab[Qctl];
  299. /* fall through */
  300. default:
  301. if(t-tab >= Qn)
  302. client[NUM(path)]->ref++;
  303. respond(r, nil);
  304. break;
  305. }
  306. }
  307. Channel *cclunk;
  308. Channel *cclunkwait;
  309. Channel *creq;
  310. Channel *creqwait;
  311. static void
  312. fsthread(void*)
  313. {
  314. ulong path;
  315. Alt a[3];
  316. Fid *fid;
  317. Req *r;
  318. threadsetname("fsthread");
  319. a[0].op = CHANRCV;
  320. a[0].c = cclunk;
  321. a[0].v = &fid;
  322. a[1].op = CHANRCV;
  323. a[1].c = creq;
  324. a[1].v = &r;
  325. a[2].op = CHANEND;
  326. for(;;){
  327. switch(alt(a)){
  328. case 0:
  329. path = fid->qid.path;
  330. if(fid->omode != -1 && TYPE(path) >= Qn)
  331. closeclient(client[NUM(path)]);
  332. sendp(cclunkwait, nil);
  333. break;
  334. case 1:
  335. switch(r->ifcall.type){
  336. case Tattach:
  337. fsattach(r);
  338. break;
  339. case Topen:
  340. fsopen(r);
  341. break;
  342. case Tread:
  343. fsread(r);
  344. break;
  345. case Twrite:
  346. fswrite(r);
  347. break;
  348. case Tstat:
  349. fsstat(r);
  350. break;
  351. case Tflush:
  352. fsflush(r);
  353. break;
  354. default:
  355. respond(r, "bug in fsthread");
  356. break;
  357. }
  358. sendp(creqwait, 0);
  359. break;
  360. }
  361. }
  362. }
  363. static void
  364. fsdestroyfid(Fid *fid)
  365. {
  366. sendp(cclunk, fid);
  367. recvp(cclunkwait);
  368. }
  369. static void
  370. fssend(Req *r)
  371. {
  372. sendp(creq, r);
  373. recvp(creqwait); /* avoids need to deal with spurious flushes */
  374. }
  375. void
  376. initfs(void)
  377. {
  378. time0 = time(0);
  379. creq = chancreate(sizeof(void*), 0);
  380. creqwait = chancreate(sizeof(void*), 0);
  381. cclunk = chancreate(sizeof(void*), 0);
  382. cclunkwait = chancreate(sizeof(void*), 0);
  383. procrfork(fsthread, nil, STACK, RFNAMEG);
  384. }
  385. Srv fs =
  386. {
  387. .attach= fssend,
  388. .destroyfid= fsdestroyfid,
  389. .walk1= fswalk1,
  390. .open= fssend,
  391. .read= fssend,
  392. .write= fssend,
  393. .stat= fssend,
  394. .flush= fssend,
  395. };