fsys.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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 <draw.h>
  12. #include <thread.h>
  13. #include <cursor.h>
  14. #include <mouse.h>
  15. #include <keyboard.h>
  16. #include <frame.h>
  17. #include <fcall.h>
  18. #include <plumb.h>
  19. #include "dat.h"
  20. #include "fns.h"
  21. static int cfd;
  22. static int sfd;
  23. enum
  24. {
  25. Nhash = 16,
  26. DEBUG = 0
  27. };
  28. static Fid *fids[Nhash];
  29. Fid *newfid(int);
  30. static Xfid* fsysflush(Xfid*, Fid*);
  31. static Xfid* fsysauth(Xfid*, Fid*);
  32. static Xfid* fsysversion(Xfid*, Fid*);
  33. static Xfid* fsysattach(Xfid*, Fid*);
  34. static Xfid* fsyswalk(Xfid*, Fid*);
  35. static Xfid* fsysopen(Xfid*, Fid*);
  36. static Xfid* fsyscreate(Xfid*, Fid*);
  37. static Xfid* fsysread(Xfid*, Fid*);
  38. static Xfid* fsyswrite(Xfid*, Fid*);
  39. static Xfid* fsysclunk(Xfid*, Fid*);
  40. static Xfid* fsysremove(Xfid*, Fid*);
  41. static Xfid* fsysstat(Xfid*, Fid*);
  42. static Xfid* fsyswstat(Xfid*, Fid*);
  43. Xfid* (*fcall[Tmax])(Xfid*, Fid*) =
  44. {
  45. [Tflush] = fsysflush,
  46. [Tversion] = fsysversion,
  47. [Tauth] = fsysauth,
  48. [Tattach] = fsysattach,
  49. [Twalk] = fsyswalk,
  50. [Topen] = fsysopen,
  51. [Tcreate] = fsyscreate,
  52. [Tread] = fsysread,
  53. [Twrite] = fsyswrite,
  54. [Tclunk] = fsysclunk,
  55. [Tremove]= fsysremove,
  56. [Tstat] = fsysstat,
  57. [Twstat] = fsyswstat,
  58. };
  59. char Eperm[] = "permission denied";
  60. char Eexist[] = "file does not exist";
  61. char Enotdir[] = "not a directory";
  62. Dirtab dirtab[]=
  63. {
  64. { ".", QTDIR, Qdir, 0500|DMDIR },
  65. { "acme", QTDIR, Qacme, 0500|DMDIR },
  66. { "cons", QTFILE, Qcons, 0600 },
  67. { "consctl", QTFILE, Qconsctl, 0000 },
  68. { "draw", QTDIR, Qdraw, 0000|DMDIR }, /* to suppress graphics progs started in acme */
  69. { "editout", QTFILE, Qeditout, 0200 },
  70. { "index", QTFILE, Qindex, 0400 },
  71. { "label", QTFILE, Qlabel, 0600 },
  72. { "new", QTDIR, Qnew, 0500|DMDIR },
  73. { nil, }
  74. };
  75. Dirtab dirtabw[]=
  76. {
  77. { ".", QTDIR, Qdir, 0500|DMDIR },
  78. { "addr", QTFILE, QWaddr, 0600 },
  79. { "body", QTAPPEND, QWbody, 0600|DMAPPEND },
  80. { "ctl", QTFILE, QWctl, 0600 },
  81. { "data", QTFILE, QWdata, 0600 },
  82. { "editout", QTFILE, QWeditout, 0200 },
  83. { "errors", QTFILE, QWerrors, 0200 },
  84. { "event", QTFILE, QWevent, 0600 },
  85. { "rdsel", QTFILE, QWrdsel, 0400 },
  86. { "wrsel", QTFILE, QWwrsel, 0200 },
  87. { "tag", QTAPPEND, QWtag, 0600|DMAPPEND },
  88. { "xdata", QTFILE, QWxdata, 0600 },
  89. { nil, }
  90. };
  91. typedef struct Mnt Mnt;
  92. struct Mnt
  93. {
  94. QLock;
  95. int id;
  96. Mntdir *md;
  97. };
  98. Mnt mnt;
  99. Xfid* respond(Xfid*, Fcall*, char*);
  100. int dostat(int, Dirtab*, uint8_t*, int, uint);
  101. uint getclock(void);
  102. char *user = "Wile E. Coyote";
  103. int clockfd;
  104. static int closing = 0;
  105. int messagesize = Maxblock+IOHDRSZ; /* good start */
  106. void fsysproc(void *);
  107. void
  108. fsysinit(void)
  109. {
  110. int p[2];
  111. int n, fd;
  112. char buf[256];
  113. if(pipe(p) < 0)
  114. error("can't create pipe");
  115. cfd = p[0];
  116. sfd = p[1];
  117. fmtinstall('F', fcallfmt);
  118. clockfd = open("/dev/time", OREAD|OCEXEC);
  119. fd = open("/dev/user", OREAD);
  120. if(fd >= 0){
  121. n = read(fd, buf, sizeof buf-1);
  122. if(n > 0){
  123. buf[n] = 0;
  124. user = estrdup(buf);
  125. }
  126. close(fd);
  127. }
  128. proccreate(fsysproc, nil, STACK);
  129. }
  130. void
  131. fsysproc(void *v)
  132. {
  133. int n;
  134. Xfid *x;
  135. Fid *f;
  136. Fcall t;
  137. uint8_t *buf;
  138. threadsetname("fsysproc");
  139. x = nil;
  140. for(;;){
  141. buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */
  142. n = read9pmsg(sfd, buf, messagesize);
  143. if(n <= 0){
  144. if(closing)
  145. break;
  146. error("i/o error on server channel");
  147. }
  148. if(x == nil){
  149. sendp(cxfidalloc, nil);
  150. x = recvp(cxfidalloc);
  151. }
  152. x->buf = buf;
  153. if(convM2S(buf, n, x) != n)
  154. error("convert error in convM2S");
  155. if(DEBUG)
  156. fprint(2, "%F\n", &x->Fcall);
  157. if(fcall[x->type] == nil)
  158. x = respond(x, &t, "bad fcall type");
  159. else{
  160. switch(x->type){
  161. case Tversion:
  162. case Tauth:
  163. case Tflush:
  164. f = nil;
  165. break;
  166. case Tattach:
  167. f = newfid(x->fid);
  168. break;
  169. default:
  170. f = newfid(x->fid);
  171. if(!f->busy){
  172. x->f = f;
  173. x = respond(x, &t, "fid not in use");
  174. continue;
  175. }
  176. break;
  177. }
  178. x->f = f;
  179. x = (*fcall[x->type])(x, f);
  180. }
  181. }
  182. }
  183. Mntdir*
  184. fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
  185. {
  186. Mntdir *m;
  187. int id;
  188. qlock(&mnt);
  189. id = ++mnt.id;
  190. m = emalloc(sizeof *m);
  191. m->id = id;
  192. m->dir = dir;
  193. m->ref = 1; /* one for Command, one will be incremented in attach */
  194. m->ndir = ndir;
  195. m->next = mnt.md;
  196. m->incl = incl;
  197. m->nincl = nincl;
  198. mnt.md = m;
  199. qunlock(&mnt);
  200. return m;
  201. }
  202. void
  203. fsysincid(Mntdir *m)
  204. {
  205. qlock(&mnt);
  206. m->ref++;
  207. qunlock(&mnt);
  208. }
  209. void
  210. fsysdelid(Mntdir *idm)
  211. {
  212. Mntdir *m, *prev;
  213. int i;
  214. char buf[64];
  215. if(idm == nil)
  216. return;
  217. qlock(&mnt);
  218. if(--idm->ref > 0){
  219. qunlock(&mnt);
  220. return;
  221. }
  222. prev = nil;
  223. for(m=mnt.md; m; m=m->next){
  224. if(m == idm){
  225. if(prev)
  226. prev->next = m->next;
  227. else
  228. mnt.md = m->next;
  229. for(i=0; i<m->nincl; i++)
  230. free(m->incl[i]);
  231. free(m->incl);
  232. free(m->dir);
  233. free(m);
  234. qunlock(&mnt);
  235. return;
  236. }
  237. prev = m;
  238. }
  239. qunlock(&mnt);
  240. sprint(buf, "fsysdelid: can't find id %d\n", idm->id);
  241. sendp(cerr, estrdup(buf));
  242. }
  243. /*
  244. * Called only in exec.c:/^run(), from a different FD group
  245. */
  246. Mntdir*
  247. fsysmount(Rune *dir, int ndir, Rune **incl, int nincl)
  248. {
  249. char buf[256];
  250. Mntdir *m;
  251. /* close server side so don't hang if acme is half-exited */
  252. close(sfd);
  253. m = fsysaddid(dir, ndir, incl, nincl);
  254. sprint(buf, "%d", m->id);
  255. if(mount(cfd, -1, "/mnt/acme", MREPL, buf, 'M') < 0){
  256. fsysdelid(m);
  257. return nil;
  258. }
  259. close(cfd);
  260. bind("/mnt/acme", "/mnt/wsys", MREPL);
  261. if(bind("/mnt/acme", "/dev", MBEFORE) < 0){
  262. fsysdelid(m);
  263. return nil;
  264. }
  265. return m;
  266. }
  267. void
  268. fsysclose(void)
  269. {
  270. closing = 1;
  271. close(cfd);
  272. close(sfd);
  273. }
  274. Xfid*
  275. respond(Xfid *x, Fcall *t, char *err)
  276. {
  277. int n;
  278. if(err){
  279. t->type = Rerror;
  280. t->ename = err;
  281. }else
  282. t->type = x->type+1;
  283. t->fid = x->fid;
  284. t->tag = x->tag;
  285. if(x->buf == nil)
  286. x->buf = emalloc(messagesize);
  287. n = convS2M(t, x->buf, messagesize);
  288. if(n <= 0)
  289. error("convert error in convS2M");
  290. if(write(sfd, x->buf, n) != n)
  291. error("write error in respond");
  292. free(x->buf);
  293. x->buf = nil;
  294. if(DEBUG)
  295. fprint(2, "r: %F\n", t);
  296. return x;
  297. }
  298. static
  299. Xfid*
  300. fsysversion(Xfid *x, Fid*f)
  301. {
  302. Fcall t;
  303. if(x->msize < 256)
  304. return respond(x, &t, "version: message size too small");
  305. if(x->msize < messagesize)
  306. messagesize = x->msize;
  307. t.msize = messagesize;
  308. if(strncmp(x->version, "9P2000", 6) != 0)
  309. return respond(x, &t, "unrecognized 9P version");
  310. t.version = "9P2000";
  311. return respond(x, &t, nil);
  312. }
  313. static
  314. Xfid*
  315. fsysauth(Xfid *x, Fid*f)
  316. {
  317. Fcall t;
  318. return respond(x, &t, "acme: authentication not required");
  319. }
  320. static
  321. Xfid*
  322. fsysflush(Xfid *x, Fid*f)
  323. {
  324. sendp(x->c, xfidflush);
  325. return nil;
  326. }
  327. static
  328. Xfid*
  329. fsysattach(Xfid *x, Fid *f)
  330. {
  331. Fcall t;
  332. int id;
  333. Mntdir *m;
  334. if(strcmp(x->uname, user) != 0)
  335. return respond(x, &t, Eperm);
  336. f->busy = TRUE;
  337. f->open = FALSE;
  338. f->qid.path = Qdir;
  339. f->qid.type = QTDIR;
  340. f->qid.vers = 0;
  341. f->dir = dirtab;
  342. f->nrpart = 0;
  343. f->w = nil;
  344. t.qid = f->qid;
  345. f->mntdir = nil;
  346. id = atoi(x->aname);
  347. qlock(&mnt);
  348. for(m=mnt.md; m; m=m->next)
  349. if(m->id == id){
  350. f->mntdir = m;
  351. m->ref++;
  352. break;
  353. }
  354. if(m == nil)
  355. sendp(cerr, estrdup("unknown id in attach"));
  356. qunlock(&mnt);
  357. return respond(x, &t, nil);
  358. }
  359. static
  360. Xfid*
  361. fsyswalk(Xfid *x, Fid *f)
  362. {
  363. Fcall t;
  364. int c, i, j, id;
  365. Qid q;
  366. uint8_t type;
  367. uint32_t path;
  368. Fid *nf;
  369. Dirtab *d, *dir;
  370. Window *w;
  371. char *err;
  372. nf = nil;
  373. w = nil;
  374. if(f->open)
  375. return respond(x, &t, "walk of open file");
  376. if(x->fid != x->newfid){
  377. nf = newfid(x->newfid);
  378. if(nf->busy)
  379. return respond(x, &t, "newfid already in use");
  380. nf->busy = TRUE;
  381. nf->open = FALSE;
  382. nf->mntdir = f->mntdir;
  383. if(f->mntdir)
  384. f->mntdir->ref++;
  385. nf->dir = f->dir;
  386. nf->qid = f->qid;
  387. nf->w = f->w;
  388. nf->nrpart = 0; /* not open, so must be zero */
  389. if(nf->w)
  390. incref(nf->w);
  391. f = nf; /* walk f */
  392. }
  393. t.nwqid = 0;
  394. err = nil;
  395. dir = nil;
  396. id = WIN(f->qid);
  397. q = f->qid;
  398. if(x->nwname > 0){
  399. for(i=0; i<x->nwname; i++){
  400. if((q.type & QTDIR) == 0){
  401. err = Enotdir;
  402. break;
  403. }
  404. if(strcmp(x->wname[i], "..") == 0){
  405. type = QTDIR;
  406. path = Qdir;
  407. id = 0;
  408. if(w){
  409. winclose(w);
  410. w = nil;
  411. }
  412. Accept:
  413. if(i == MAXWELEM){
  414. err = "name too long";
  415. break;
  416. }
  417. q.type = type;
  418. q.vers = 0;
  419. q.path = QID(id, path);
  420. t.wqid[t.nwqid++] = q;
  421. continue;
  422. }
  423. /* is it a numeric name? */
  424. for(j=0; (c=x->wname[i][j]); j++)
  425. if(c<'0' || '9'<c)
  426. goto Regular;
  427. /* yes: it's a directory */
  428. if(w) /* name has form 27/23; get out before losing w */
  429. break;
  430. id = atoi(x->wname[i]);
  431. qlock(&row);
  432. w = lookid(id, FALSE);
  433. if(w == nil){
  434. qunlock(&row);
  435. break;
  436. }
  437. incref(w); /* we'll drop reference at end if there's an error */
  438. path = Qdir;
  439. type = QTDIR;
  440. qunlock(&row);
  441. dir = dirtabw;
  442. goto Accept;
  443. Regular:
  444. // if(FILE(f->qid) == Qacme) /* empty directory */
  445. // break;
  446. if(strcmp(x->wname[i], "new") == 0){
  447. if(w)
  448. error("w set in walk to new");
  449. sendp(cnewwindow, nil); /* signal newwindowthread */
  450. w = recvp(cnewwindow); /* receive new window */
  451. incref(w);
  452. type = QTDIR;
  453. path = QID(w->id, Qdir);
  454. id = w->id;
  455. dir = dirtabw;
  456. goto Accept;
  457. }
  458. if(id == 0)
  459. d = dirtab;
  460. else
  461. d = dirtabw;
  462. d++; /* skip '.' */
  463. for(; d->name; d++)
  464. if(strcmp(x->wname[i], d->name) == 0){
  465. path = d->qid;
  466. type = d->type;
  467. dir = d;
  468. goto Accept;
  469. }
  470. break; /* file not found */
  471. }
  472. if(i==0 && err == nil)
  473. err = Eexist;
  474. }
  475. if(err!=nil || t.nwqid<x->nwname){
  476. if(nf){
  477. nf->busy = FALSE;
  478. fsysdelid(nf->mntdir);
  479. }
  480. }else if(t.nwqid == x->nwname){
  481. if(w){
  482. f->w = w;
  483. w = nil; /* don't drop the reference */
  484. }
  485. if(dir)
  486. f->dir = dir;
  487. f->qid = q;
  488. }
  489. if(w != nil)
  490. winclose(w);
  491. return respond(x, &t, err);
  492. }
  493. static
  494. Xfid*
  495. fsysopen(Xfid *x, Fid *f)
  496. {
  497. Fcall t;
  498. int m;
  499. /* can't truncate anything, so just disregard */
  500. x->mode &= ~(OTRUNC|OCEXEC);
  501. /* can't execute or remove anything */
  502. if(x->mode==OEXEC || (x->mode&ORCLOSE))
  503. goto Deny;
  504. switch(x->mode){
  505. default:
  506. goto Deny;
  507. case OREAD:
  508. m = 0400;
  509. break;
  510. case OWRITE:
  511. m = 0200;
  512. break;
  513. case ORDWR:
  514. m = 0600;
  515. break;
  516. }
  517. if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
  518. goto Deny;
  519. sendp(x->c, xfidopen);
  520. return nil;
  521. Deny:
  522. return respond(x, &t, Eperm);
  523. }
  524. static
  525. Xfid*
  526. fsyscreate(Xfid *x, Fid*f)
  527. {
  528. Fcall t;
  529. return respond(x, &t, Eperm);
  530. }
  531. static
  532. int
  533. idcmp(const void *a, const void *b)
  534. {
  535. return *(int*)a - *(int*)b;
  536. }
  537. static
  538. Xfid*
  539. fsysread(Xfid *x, Fid *f)
  540. {
  541. Fcall t;
  542. uint8_t *b;
  543. int i, id, n, o, e, j, k, *ids, nids;
  544. Dirtab *d, dt;
  545. Column *c;
  546. uint clock, len;
  547. char buf[16];
  548. if(f->qid.type & QTDIR){
  549. if(FILE(f->qid) == Qacme){ /* empty dir */
  550. t.data = nil;
  551. t.count = 0;
  552. respond(x, &t, nil);
  553. return x;
  554. }
  555. o = x->offset;
  556. e = x->offset+x->count;
  557. clock = getclock();
  558. b = emalloc(messagesize);
  559. id = WIN(f->qid);
  560. n = 0;
  561. if(id > 0)
  562. d = dirtabw;
  563. else
  564. d = dirtab;
  565. d++; /* first entry is '.' */
  566. for(i=0; d->name!=nil && i<e; i+=len){
  567. len = dostat(WIN(x->f->qid), d, b+n, x->count-n, clock);
  568. if(len <= BIT16SZ)
  569. break;
  570. if(i >= o)
  571. n += len;
  572. d++;
  573. }
  574. if(id == 0){
  575. qlock(&row);
  576. nids = 0;
  577. ids = nil;
  578. for(j=0; j<row.ncol; j++){
  579. c = row.col[j];
  580. for(k=0; k<c->nw; k++){
  581. ids = erealloc(ids, (nids+1)*sizeof(int));
  582. ids[nids++] = c->w[k]->id;
  583. }
  584. }
  585. qunlock(&row);
  586. qsort(ids, nids, sizeof ids[0], idcmp);
  587. j = 0;
  588. dt.name = buf;
  589. for(; j<nids && i<e; i+=len){
  590. k = ids[j];
  591. sprint(dt.name, "%d", k);
  592. dt.qid = QID(k, Qdir);
  593. dt.type = QTDIR;
  594. dt.perm = DMDIR|0700;
  595. len = dostat(k, &dt, b+n, x->count-n, clock);
  596. if(len == 0)
  597. break;
  598. if(i >= o)
  599. n += len;
  600. j++;
  601. }
  602. free(ids);
  603. }
  604. t.data = (char*)b;
  605. t.count = n;
  606. respond(x, &t, nil);
  607. free(b);
  608. return x;
  609. }
  610. sendp(x->c, xfidread);
  611. return nil;
  612. }
  613. static
  614. Xfid*
  615. fsyswrite(Xfid *x, Fid*f)
  616. {
  617. sendp(x->c, xfidwrite);
  618. return nil;
  619. }
  620. static
  621. Xfid*
  622. fsysclunk(Xfid *x, Fid *f)
  623. {
  624. fsysdelid(f->mntdir);
  625. sendp(x->c, xfidclose);
  626. return nil;
  627. }
  628. static
  629. Xfid*
  630. fsysremove(Xfid *x, Fid*f)
  631. {
  632. Fcall t;
  633. return respond(x, &t, Eperm);
  634. }
  635. static
  636. Xfid*
  637. fsysstat(Xfid *x, Fid *f)
  638. {
  639. Fcall t;
  640. t.stat = emalloc(messagesize-IOHDRSZ);
  641. t.nstat = dostat(WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock());
  642. x = respond(x, &t, nil);
  643. free(t.stat);
  644. return x;
  645. }
  646. static
  647. Xfid*
  648. fsyswstat(Xfid *x, Fid*f)
  649. {
  650. Fcall t;
  651. return respond(x, &t, Eperm);
  652. }
  653. Fid*
  654. newfid(int fid)
  655. {
  656. Fid *f, *ff, **fh;
  657. ff = nil;
  658. fh = &fids[fid&(Nhash-1)];
  659. for(f=*fh; f; f=f->next)
  660. if(f->fid == fid)
  661. return f;
  662. else if(ff==nil && f->busy==FALSE)
  663. ff = f;
  664. if(ff){
  665. ff->fid = fid;
  666. return ff;
  667. }
  668. f = emalloc(sizeof *f);
  669. f->fid = fid;
  670. f->next = *fh;
  671. *fh = f;
  672. return f;
  673. }
  674. uint
  675. getclock()
  676. {
  677. char buf[32];
  678. buf[0] = '\0';
  679. pread(clockfd, buf, sizeof buf, 0);
  680. return atoi(buf);
  681. }
  682. int
  683. dostat(int id, Dirtab *dir, uint8_t *buf, int nbuf, uint clock)
  684. {
  685. Dir d;
  686. d.qid.path = QID(id, dir->qid);
  687. d.qid.vers = 0;
  688. d.qid.type = dir->type;
  689. d.mode = dir->perm;
  690. d.length = 0; /* would be nice to do better */
  691. d.name = dir->name;
  692. d.uid = user;
  693. d.gid = user;
  694. d.muid = user;
  695. d.atime = clock;
  696. d.mtime = clock;
  697. return convD2M(&d, buf, nbuf);
  698. }