devsrv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. #include "dat.h"
  2. #include "fns.h"
  3. #include "error.h"
  4. #include "interp.h"
  5. #include <isa.h>
  6. #include "runt.h"
  7. typedef struct SrvFile SrvFile;
  8. typedef struct Pending Pending;
  9. /* request pending to a server, in case a server vanishes */
  10. struct Pending
  11. {
  12. Pending* next;
  13. Pending* prev;
  14. int fid;
  15. Channel* rc;
  16. Channel* wc;
  17. };
  18. struct SrvFile
  19. {
  20. char* name;
  21. char* user;
  22. ulong perm;
  23. Qid qid;
  24. int ref;
  25. /* root directory */
  26. char* spec;
  27. SrvFile* devlist;
  28. SrvFile* entry;
  29. /* file */
  30. int opens;
  31. int flags;
  32. vlong length;
  33. Channel* read;
  34. Channel* write;
  35. SrvFile* dir; /* parent directory */
  36. Pending waitlist; /* pending requests from client opens */
  37. };
  38. enum
  39. {
  40. SORCLOSE = (1<<0),
  41. SRDCLOSE = (1<<1),
  42. SWRCLOSE = (1<<2),
  43. SREMOVED = (1<<3),
  44. };
  45. typedef struct SrvDev SrvDev;
  46. struct SrvDev
  47. {
  48. Type* Rread;
  49. Type* Rwrite;
  50. QLock l;
  51. ulong pathgen;
  52. SrvFile* devices;
  53. };
  54. static SrvDev dev;
  55. void freechan(Heap*, int);
  56. static void freerdchan(Heap*, int);
  57. static void freewrchan(Heap*, int);
  58. static void delwaiting(Pending*);
  59. Type *Trdchan;
  60. Type *Twrchan;
  61. static int
  62. srvgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
  63. {
  64. SrvFile *f;
  65. USED(name);
  66. USED(tab);
  67. USED(ntab);
  68. if(s == DEVDOTDOT){
  69. devdir(c, c->qid, "#s", 0, eve, 0555, dp);
  70. return 1;
  71. }
  72. f = c->aux;
  73. if((c->qid.type & QTDIR) == 0){
  74. if(s > 0)
  75. return -1;
  76. devdir(c, f->qid, f->name, f->length, f->user, f->perm, dp);
  77. return 1;
  78. }
  79. for(f = f->entry; f != nil; f = f->entry){
  80. if(s-- == 0)
  81. break;
  82. }
  83. if(f == nil)
  84. return -1;
  85. devdir(c, f->qid, f->name, f->length, f->user, f->perm, dp);
  86. return 1;
  87. }
  88. static void
  89. srvinit(void)
  90. {
  91. static uchar rmap[] = Sys_Rread_map;
  92. static uchar wmap[] = Sys_Rwrite_map;
  93. Trdchan = dtype(freerdchan, sizeof(Channel), Tchannel.map, Tchannel.np);
  94. Twrchan = dtype(freewrchan, sizeof(Channel), Tchannel.map, Tchannel.np);
  95. dev.pathgen = 1;
  96. dev.Rread = dtype(freeheap, Sys_Rread_size, rmap, sizeof(rmap));
  97. dev.Rwrite = dtype(freeheap, Sys_Rwrite_size, wmap, sizeof(wmap));
  98. }
  99. static int
  100. srvcanattach(SrvFile *d)
  101. {
  102. if(strcmp(d->user, up->env->user) == 0)
  103. return 1;
  104. /*
  105. * Need write permission in other to allow attaches if
  106. * we are not the owner
  107. */
  108. if(d->perm & 2)
  109. return 1;
  110. return 0;
  111. }
  112. static Chan*
  113. srvattach(char *spec)
  114. {
  115. Chan *c;
  116. SrvFile *d;
  117. char srvname[16];
  118. qlock(&dev.l);
  119. if(waserror()){
  120. qunlock(&dev.l);
  121. nexterror();
  122. }
  123. if(spec[0] != '\0'){
  124. for(d = dev.devices; d != nil; d = d->devlist){
  125. if(strcmp(spec, d->spec) == 0){
  126. if(!srvcanattach(d))
  127. error(Eperm);
  128. c = devattach('s', spec);
  129. c->aux = d;
  130. c->qid = d->qid;
  131. d->ref++;
  132. poperror();
  133. qunlock(&dev.l);
  134. return c;
  135. }
  136. }
  137. }
  138. d = malloc(sizeof(SrvFile));
  139. if(d == nil)
  140. error(Enomem);
  141. d->ref = 1;
  142. kstrdup(&d->spec, spec);
  143. kstrdup(&d->user, up->env->user);
  144. snprint(srvname, sizeof(srvname), "srv%ld", up->env->pgrp->pgrpid);
  145. kstrdup(&d->name, srvname);
  146. d->perm = DMDIR|0770;
  147. mkqid(&d->qid, dev.pathgen++, 0, QTDIR);
  148. d->devlist = dev.devices;
  149. dev.devices = d;
  150. poperror();
  151. qunlock(&dev.l);
  152. c = devattach('s', spec);
  153. c->aux = d;
  154. c->qid = d->qid;
  155. return c;
  156. }
  157. static Walkqid*
  158. srvwalk(Chan *c, Chan *nc, char **name, int nname)
  159. {
  160. SrvFile *d, *pd;
  161. Walkqid *w;
  162. pd = c->aux;
  163. qlock(&dev.l);
  164. if(waserror()){
  165. qunlock(&dev.l);
  166. nexterror();
  167. }
  168. w = devwalk(c, nc, name, nname, nil, 0, srvgen);
  169. if(w != nil && w->clone != nil){
  170. if(nname != 0){
  171. for(d = pd->entry; d != nil; d = d->entry)
  172. if(d->qid.path == w->clone->qid.path)
  173. break;
  174. if(d == nil)
  175. panic("srvwalk");
  176. if(w->clone == c)
  177. pd->ref--;
  178. }else
  179. d = pd;
  180. w->clone->aux = d;
  181. d->ref++;
  182. }
  183. poperror();
  184. qunlock(&dev.l);
  185. return w;
  186. }
  187. static int
  188. srvstat(Chan *c, uchar *db, int n)
  189. {
  190. qlock(&dev.l);
  191. if(waserror()){
  192. qunlock(&dev.l);
  193. nexterror();
  194. }
  195. n = devstat(c, db, n, 0, 0, srvgen);
  196. poperror();
  197. qunlock(&dev.l);
  198. return n;
  199. }
  200. static Chan*
  201. srvopen(Chan *c, int omode)
  202. {
  203. SrvFile *sf;
  204. openmode(omode); /* check it */
  205. if(c->qid.type & QTDIR){
  206. if(omode != OREAD)
  207. error(Eisdir);
  208. c->mode = omode;
  209. c->flag |= COPEN;
  210. c->offset = 0;
  211. return c;
  212. }
  213. sf = c->aux;
  214. qlock(&dev.l);
  215. if(waserror()){
  216. qunlock(&dev.l);
  217. nexterror();
  218. }
  219. devpermcheck(sf->user, sf->perm, omode);
  220. if(omode&ORCLOSE && strcmp(sf->user, up->env->user) != 0)
  221. error(Eperm);
  222. if(sf->perm & DMEXCL && sf->opens != 0)
  223. error(Einuse);
  224. sf->opens++;
  225. if(omode&ORCLOSE)
  226. sf->flags |= SORCLOSE;
  227. poperror();
  228. qunlock(&dev.l);
  229. c->offset = 0;
  230. c->flag |= COPEN;
  231. c->mode = openmode(omode);
  232. return c;
  233. }
  234. static int
  235. srvwstat(Chan *c, uchar *dp, int n)
  236. {
  237. Dir *d;
  238. SrvFile *sf, *f;
  239. sf = c->aux;
  240. if(strcmp(up->env->user, sf->user) != 0)
  241. error(Eperm);
  242. d = smalloc(sizeof(*d)+n);
  243. if(waserror()){
  244. free(d);
  245. nexterror();
  246. }
  247. n = convM2D(dp, n, d, (char*)&d[1]);
  248. if(n == 0)
  249. error(Eshortstat);
  250. if(!emptystr(d->name)){
  251. if(sf->dir == nil)
  252. error(Eperm);
  253. validwstatname(d->name);
  254. qlock(&dev.l);
  255. for(f = sf->dir; f != nil; f = f->entry)
  256. if(strcmp(f->name, d->name) == 0){
  257. qunlock(&dev.l);
  258. error(Eexist);
  259. }
  260. kstrdup(&sf->name, d->name);
  261. qunlock(&dev.l);
  262. }
  263. if(d->mode != ~0UL)
  264. sf->perm = d->mode & (DMEXCL|DMAPPEND|0777);
  265. if(d->length != (vlong)-1)
  266. sf->length = d->length;
  267. poperror();
  268. free(d);
  269. return n;
  270. }
  271. static void
  272. srvputdir(SrvFile *dir)
  273. {
  274. SrvFile **l, *d;
  275. dir->ref--;
  276. if(dir->ref != 0)
  277. return;
  278. for(l = &dev.devices; (d = *l) != nil; l = &d->devlist)
  279. if(d == dir){
  280. *l = d->devlist;
  281. break;
  282. }
  283. free(dir->spec);
  284. free(dir->user);
  285. free(dir->name);
  286. free(dir);
  287. }
  288. static void
  289. srvunblock(SrvFile *sf, int fid)
  290. {
  291. Channel *d;
  292. Sys_FileIO_read rreq;
  293. Sys_FileIO_write wreq;
  294. acquire();
  295. if(waserror()){
  296. release();
  297. nexterror();
  298. }
  299. d = sf->read;
  300. if(d != H){
  301. rreq.t0 = 0;
  302. rreq.t1 = 0;
  303. rreq.t2 = fid;
  304. rreq.t3 = H;
  305. csendalt(d, &rreq, d->mid.t, -1);
  306. }
  307. d = sf->write;
  308. if(d != H){
  309. wreq.t0 = 0;
  310. wreq.t1 = H;
  311. wreq.t2 = fid;
  312. wreq.t3 = H;
  313. csendalt(d, &wreq, d->mid.t, -1);
  314. }
  315. poperror();
  316. release();
  317. }
  318. static void
  319. srvcancelreqs(SrvFile *sf)
  320. {
  321. Pending *w, *ws;
  322. Sys_Rread rreply;
  323. Sys_Rwrite wreply;
  324. acquire();
  325. ws = &sf->waitlist;
  326. while((w = ws->next) != ws){
  327. delwaiting(w);
  328. if(waserror() == 0){
  329. if(w->rc != nil){
  330. rreply.t0 = H;
  331. rreply.t1 = c2string(Ehungup, strlen(Ehungup));
  332. csend(w->rc, &rreply);
  333. }
  334. if(w->wc != nil){
  335. wreply.t0 = 0;
  336. wreply.t1 = c2string(Ehungup, strlen(Ehungup));
  337. csend(w->wc, &wreply);
  338. }
  339. poperror();
  340. }
  341. }
  342. release();
  343. }
  344. static void
  345. srvdelete(SrvFile *sf)
  346. {
  347. SrvFile *f, **l;
  348. if((sf->flags & SREMOVED) == 0){
  349. for(l = &sf->dir->entry; (f = *l) != nil; l = &f->entry){
  350. if(sf == f){
  351. *l = f->entry;
  352. break;
  353. }
  354. }
  355. sf->ref--;
  356. sf->flags |= SREMOVED;
  357. }
  358. }
  359. static void
  360. srvchkref(SrvFile *sf)
  361. {
  362. if(sf->ref != 0)
  363. return;
  364. if(sf->dir != nil)
  365. srvputdir(sf->dir);
  366. free(sf->user);
  367. free(sf->name);
  368. free(sf);
  369. }
  370. static void
  371. srvfree(SrvFile *sf, int flag)
  372. {
  373. sf->flags |= flag;
  374. if((sf->flags & (SRDCLOSE | SWRCLOSE)) == (SRDCLOSE | SWRCLOSE)){
  375. sf->ref--;
  376. srvdelete(sf);
  377. /* no further requests can arrive; return error to pending requests */
  378. srvcancelreqs(sf);
  379. srvchkref(sf);
  380. }
  381. }
  382. static void
  383. freerdchan(Heap *h, int swept)
  384. {
  385. SrvFile *sf;
  386. release();
  387. qlock(&dev.l);
  388. sf = H2D(Channel*, h)->aux;
  389. sf->read = H;
  390. srvfree(sf, SRDCLOSE);
  391. qunlock(&dev.l);
  392. acquire();
  393. freechan(h, swept);
  394. }
  395. static void
  396. freewrchan(Heap *h, int swept)
  397. {
  398. SrvFile *sf;
  399. release();
  400. qlock(&dev.l);
  401. sf = H2D(Channel*, h)->aux;
  402. sf->write = H;
  403. srvfree(sf, SWRCLOSE);
  404. qunlock(&dev.l);
  405. acquire();
  406. freechan(h, swept);
  407. }
  408. static void
  409. srvclunk(Chan *c, int remove)
  410. {
  411. int opens, noperm;
  412. SrvFile *sf;
  413. sf = c->aux;
  414. qlock(&dev.l);
  415. if(c->qid.type & QTDIR){
  416. srvputdir(sf);
  417. qunlock(&dev.l);
  418. if(remove)
  419. error(Eperm);
  420. return;
  421. }
  422. opens = 0;
  423. if(c->flag & COPEN){
  424. opens = sf->opens--;
  425. if(sf->read != H || sf->write != H)
  426. srvunblock(sf, c->fid);
  427. }
  428. sf->ref--;
  429. if(opens == 1){
  430. if(sf->flags & SORCLOSE)
  431. remove = 1;
  432. }
  433. noperm = 0;
  434. if(remove && strcmp(sf->dir->user, up->env->user) != 0){
  435. noperm = 1;
  436. remove = 0;
  437. }
  438. if(remove)
  439. srvdelete(sf);
  440. srvchkref(sf);
  441. qunlock(&dev.l);
  442. if(noperm)
  443. error(Eperm);
  444. }
  445. static void
  446. srvclose(Chan *c)
  447. {
  448. srvclunk(c, 0);
  449. }
  450. static void
  451. srvremove(Chan *c)
  452. {
  453. srvclunk(c, 1);
  454. }
  455. static void
  456. addwaiting(SrvFile *sp, Pending *w)
  457. {
  458. Pending *sw;
  459. sw = &sp->waitlist;
  460. w->next = sw;
  461. w->prev = sw->prev;
  462. sw->prev->next = w;
  463. sw->prev = w;
  464. }
  465. static void
  466. delwaiting(Pending *w)
  467. {
  468. w->next->prev = w->prev;
  469. w->prev->next = w->next;
  470. }
  471. static long
  472. srvread(Chan *c, void *va, long count, vlong offset)
  473. {
  474. int l;
  475. Heap * volatile h;
  476. Array *a;
  477. SrvFile *sp;
  478. Channel *rc;
  479. Channel *rd;
  480. Pending wait;
  481. Sys_Rread * volatile r;
  482. Sys_FileIO_read req;
  483. if(c->qid.type & QTDIR){
  484. qlock(&dev.l);
  485. if(waserror()){
  486. qunlock(&dev.l);
  487. nexterror();
  488. }
  489. l = devdirread(c, va, count, 0, 0, srvgen);
  490. poperror();
  491. qunlock(&dev.l);
  492. return l;
  493. }
  494. sp = c->aux;
  495. acquire();
  496. if(waserror()){
  497. release();
  498. nexterror();
  499. }
  500. rd = sp->read;
  501. if(rd == H)
  502. error(Ehungup);
  503. rc = cnewc(dev.Rread, movtmp, 1);
  504. ptradd(D2H(rc));
  505. if(waserror()){
  506. ptrdel(D2H(rc));
  507. destroy(rc);
  508. nexterror();
  509. }
  510. req.t0 = offset;
  511. req.t1 = count;
  512. req.t2 = c->fid;
  513. req.t3 = rc;
  514. csend(rd, &req);
  515. h = heap(dev.Rread);
  516. r = H2D(Sys_Rread *, h);
  517. ptradd(h);
  518. if(waserror()){
  519. ptrdel(h);
  520. destroy(r);
  521. nexterror();
  522. }
  523. wait.fid = c->fid;
  524. wait.rc = rc;
  525. wait.wc = nil;
  526. addwaiting(sp, &wait);
  527. if(waserror()){
  528. delwaiting(&wait);
  529. nexterror();
  530. }
  531. crecv(rc, r);
  532. poperror();
  533. delwaiting(&wait);
  534. if(r->t1 != H)
  535. error(string2c(r->t1));
  536. a = r->t0;
  537. l = 0;
  538. if(a != H){
  539. l = a->len;
  540. if(l > count)
  541. l = count;
  542. memmove(va, a->data, l);
  543. }
  544. poperror();
  545. ptrdel(h);
  546. destroy(r);
  547. poperror();
  548. ptrdel(D2H(rc));
  549. destroy(rc);
  550. poperror();
  551. release();
  552. return l;
  553. }
  554. static long
  555. srvwrite(Chan *c, void *va, long count, vlong offset)
  556. {
  557. long l;
  558. Heap * volatile h;
  559. SrvFile *sp;
  560. Channel *wc;
  561. Channel *wr;
  562. Pending wait;
  563. Sys_Rwrite * volatile w;
  564. Sys_FileIO_write req;
  565. if(c->qid.type & QTDIR)
  566. error(Eperm);
  567. acquire();
  568. if(waserror()){
  569. release();
  570. nexterror();
  571. }
  572. sp = c->aux;
  573. wr = sp->write;
  574. if(wr == H)
  575. error(Ehungup);
  576. wc = cnewc(dev.Rwrite, movtmp, 1);
  577. ptradd(D2H(wc));
  578. if(waserror()){
  579. ptrdel(D2H(wc));
  580. destroy(wc);
  581. nexterror();
  582. }
  583. req.t0 = offset;
  584. req.t1 = mem2array(va, count);
  585. req.t2 = c->fid;
  586. req.t3 = wc;
  587. ptradd(D2H(req.t1));
  588. if(waserror()){
  589. ptrdel(D2H(req.t1));
  590. destroy(req.t1);
  591. nexterror();
  592. }
  593. csend(wr, &req);
  594. poperror();
  595. ptrdel(D2H(req.t1));
  596. destroy(req.t1);
  597. h = heap(dev.Rwrite);
  598. w = H2D(Sys_Rwrite *, h);
  599. ptradd(h);
  600. if(waserror()){
  601. ptrdel(h);
  602. destroy(w);
  603. nexterror();
  604. }
  605. wait.fid = c->fid;
  606. wait.rc = nil;
  607. wait.wc = wc;
  608. addwaiting(sp, &wait);
  609. if(waserror()){
  610. delwaiting(&wait);
  611. nexterror();
  612. }
  613. crecv(wc, w);
  614. poperror();
  615. delwaiting(&wait);
  616. if(w->t1 != H)
  617. error(string2c(w->t1));
  618. poperror();
  619. ptrdel(h);
  620. l = w->t0;
  621. destroy(w);
  622. poperror();
  623. ptrdel(D2H(wc));
  624. destroy(wc);
  625. poperror();
  626. release();
  627. if(l < 0)
  628. l = 0;
  629. return l;
  630. }
  631. static void
  632. srvretype(Channel *c, SrvFile *f, Type *t)
  633. {
  634. Heap *h;
  635. h = D2H(c);
  636. freetype(h->t);
  637. h->t = t;
  638. t->ref++;
  639. c->aux = f;
  640. }
  641. int
  642. srvf2c(char *dir, char *file, Sys_FileIO *io)
  643. {
  644. SrvFile *s, *f;
  645. volatile struct { Chan *c; } c;
  646. c.c = nil;
  647. if(waserror()){
  648. cclose(c.c);
  649. return -1;
  650. }
  651. if(strchr(file, '/') != nil || strlen(file) >= 64 || strcmp(file, ".") == 0 || strcmp(file, "..") == 0)
  652. error(Efilename);
  653. c.c = namec(dir, Aaccess, 0, 0);
  654. if((c.c->qid.type&QTDIR) == 0 || devtab[c.c->type]->dc != 's')
  655. error("directory not a srv device");
  656. s = c.c->aux;
  657. qlock(&dev.l);
  658. if(waserror()){
  659. qunlock(&dev.l);
  660. nexterror();
  661. }
  662. for(f = s->entry; f != nil; f = f->entry){
  663. if(strcmp(f->name, file) == 0)
  664. error(Eexist);
  665. }
  666. f = malloc(sizeof(SrvFile));
  667. if(f == nil)
  668. error(Enomem);
  669. srvretype(io->read, f, Trdchan);
  670. srvretype(io->write, f, Twrchan);
  671. f->read = io->read;
  672. f->write = io->write;
  673. f->waitlist.next = &f->waitlist;
  674. f->waitlist.prev = &f->waitlist;
  675. kstrdup(&f->name, file);
  676. kstrdup(&f->user, up->env->user);
  677. f->perm = 0666 & (~0666 | (s->perm & 0666));
  678. f->length = 0;
  679. f->ref = 2;
  680. mkqid(&f->qid, dev.pathgen++, 0, QTFILE);
  681. f->entry = s->entry;
  682. s->entry = f;
  683. s->ref++;
  684. f->dir = s;
  685. poperror();
  686. qunlock(&dev.l);
  687. cclose(c.c);
  688. poperror();
  689. return 0;
  690. }
  691. Dev srvdevtab = {
  692. 's',
  693. "srv",
  694. srvinit,
  695. srvattach,
  696. srvwalk,
  697. srvstat,
  698. srvopen,
  699. devcreate,
  700. srvclose,
  701. srvread,
  702. devbread,
  703. srvwrite,
  704. devbwrite,
  705. srvremove,
  706. srvwstat
  707. };