srv.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include <thread.h>
  6. #include <9p.h>
  7. static char Ebadattach[] = "unknown specifier in attach";
  8. static char Ebadoffset[] = "bad offset";
  9. static char Ebadcount[] = "bad count";
  10. static char Ebotch[] = "9P protocol botch";
  11. static char Ecreatenondir[] = "create in non-directory";
  12. static char Edupfid[] = "duplicate fid";
  13. static char Eduptag[] = "duplicate tag";
  14. static char Eisdir[] = "is a directory";
  15. static char Enocreate[] = "create prohibited";
  16. static char Enomem[] = "out of memory";
  17. static char Enoremove[] = "remove prohibited";
  18. static char Enostat[] = "stat prohibited";
  19. static char Enotfound[] = "file not found";
  20. static char Enowrite[] = "write prohibited";
  21. static char Enowstat[] = "wstat prohibited";
  22. static char Eperm[] = "permission denied";
  23. static char Eunknownfid[] = "unknown fid";
  24. static char Ebaddir[] = "bad directory in wstat";
  25. static char Ewalknodir[] = "walk in non-directory";
  26. static void
  27. setfcallerror(Fcall *f, char *err)
  28. {
  29. f->ename = err;
  30. f->type = Rerror;
  31. }
  32. static void
  33. changemsize(Srv *srv, int msize)
  34. {
  35. if(srv->rbuf && srv->wbuf && srv->msize == msize)
  36. return;
  37. qlock(&srv->rlock);
  38. qlock(&srv->wlock);
  39. srv->msize = msize;
  40. free(srv->rbuf);
  41. free(srv->wbuf);
  42. srv->rbuf = emalloc9p(msize);
  43. srv->wbuf = emalloc9p(msize);
  44. qunlock(&srv->rlock);
  45. qunlock(&srv->wlock);
  46. }
  47. static Req*
  48. getreq(Srv *s)
  49. {
  50. long n;
  51. uchar *buf;
  52. Fcall f;
  53. Req *r;
  54. qlock(&s->rlock);
  55. if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){
  56. qunlock(&s->rlock);
  57. return nil;
  58. }
  59. buf = emalloc9p(n);
  60. memmove(buf, s->rbuf, n);
  61. qunlock(&s->rlock);
  62. if(convM2S(buf, n, &f) != n){
  63. free(buf);
  64. return nil;
  65. }
  66. if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */
  67. r = emalloc9p(sizeof *r);
  68. incref(&r->ref);
  69. r->tag = f.tag;
  70. r->ifcall = f;
  71. r->error = Eduptag;
  72. r->buf = buf;
  73. r->responded = 0;
  74. r->type = 0;
  75. r->srv = s;
  76. r->pool = nil;
  77. if(chatty9p)
  78. fprint(2, "<-%d- %F: dup tag\n", s->infd, &f);
  79. return r;
  80. }
  81. r->srv = s;
  82. r->responded = 0;
  83. r->buf = buf;
  84. r->ifcall = f;
  85. memset(&r->ofcall, 0, sizeof r->ofcall);
  86. r->type = r->ifcall.type;
  87. if(chatty9p)
  88. if(r->error)
  89. fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error);
  90. else
  91. fprint(2, "<-%d- %F\n", s->infd, &r->ifcall);
  92. return r;
  93. }
  94. static void
  95. filewalk(Req *r)
  96. {
  97. int i;
  98. File *f;
  99. f = r->fid->file;
  100. assert(f != nil);
  101. incref(f);
  102. for(i=0; i<r->ifcall.nwname; i++)
  103. if(f = walkfile(f, r->ifcall.wname[i]))
  104. r->ofcall.wqid[i] = f->qid;
  105. else
  106. break;
  107. r->ofcall.nwqid = i;
  108. if(f){
  109. r->newfid->file = f;
  110. r->newfid->qid = r->newfid->file->qid;
  111. }
  112. respond(r, nil);
  113. }
  114. void
  115. walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg)
  116. {
  117. int i;
  118. char *e;
  119. if(r->fid == r->newfid && r->ifcall.nwname > 1){
  120. respond(r, "lib9p: unused documented feature not implemented");
  121. return;
  122. }
  123. if(r->fid != r->newfid){
  124. r->newfid->qid = r->fid->qid;
  125. if(clone && (e = clone(r->fid, r->newfid, arg))){
  126. respond(r, e);
  127. return;
  128. }
  129. }
  130. e = nil;
  131. for(i=0; i<r->ifcall.nwname; i++){
  132. if(e = walk1(r->newfid, r->ifcall.wname[i], arg))
  133. break;
  134. r->ofcall.wqid[i] = r->newfid->qid;
  135. }
  136. r->ofcall.nwqid = i;
  137. if(e && i==0)
  138. respond(r, e);
  139. else
  140. respond(r, nil);
  141. }
  142. static void
  143. sversion(Srv*, Req *r)
  144. {
  145. if(strncmp(r->ifcall.version, "9P", 2) != 0){
  146. r->ofcall.version = "unknown";
  147. respond(r, nil);
  148. return;
  149. }
  150. r->ofcall.version = "9P2000";
  151. r->ofcall.msize = r->ifcall.msize;
  152. respond(r, nil);
  153. }
  154. static void
  155. rversion(Req *r, char *error)
  156. {
  157. assert(error == nil);
  158. changemsize(r->srv, r->ofcall.msize);
  159. }
  160. static void
  161. sauth(Srv *srv, Req *r)
  162. {
  163. char e[ERRMAX];
  164. if((r->afid = allocfid(srv->fpool, r->ifcall.afid)) == nil){
  165. respond(r, Edupfid);
  166. return;
  167. }
  168. if(srv->auth)
  169. srv->auth(r);
  170. else{
  171. snprint(e, sizeof e, "%s: authentication not required", argv0);
  172. respond(r, e);
  173. }
  174. }
  175. static void
  176. rauth(Req *r, char *error)
  177. {
  178. if(error && r->afid)
  179. closefid(removefid(r->srv->fpool, r->afid->fid));
  180. }
  181. static void
  182. sattach(Srv *srv, Req *r)
  183. {
  184. if((r->fid = allocfid(srv->fpool, r->ifcall.fid)) == nil){
  185. respond(r, Edupfid);
  186. return;
  187. }
  188. r->afid = nil;
  189. if(r->ifcall.afid != NOFID && (r->afid = lookupfid(srv->fpool, r->ifcall.afid)) == nil){
  190. respond(r, Eunknownfid);
  191. return;
  192. }
  193. r->fid->uid = estrdup9p(r->ifcall.uname);
  194. if(srv->tree){
  195. r->fid->file = srv->tree->root;
  196. /* BUG? incref(r->fid->file) ??? */
  197. r->ofcall.qid = r->fid->file->qid;
  198. r->fid->qid = r->ofcall.qid;
  199. }
  200. if(srv->attach)
  201. srv->attach(r);
  202. else
  203. respond(r, nil);
  204. return;
  205. }
  206. static void
  207. rattach(Req *r, char *error)
  208. {
  209. if(error && r->fid)
  210. closefid(removefid(r->srv->fpool, r->fid->fid));
  211. }
  212. static void
  213. sflush(Srv *srv, Req *r)
  214. {
  215. r->oldreq = lookupreq(srv->rpool, r->ifcall.oldtag);
  216. if(r->oldreq == nil || r->oldreq == r)
  217. respond(r, nil);
  218. else if(srv->flush)
  219. srv->flush(r);
  220. else
  221. respond(r, nil);
  222. }
  223. static int
  224. rflush(Req *r, char *error)
  225. {
  226. Req *or;
  227. assert(error == nil);
  228. or = r->oldreq;
  229. if(or){
  230. qlock(&or->lk);
  231. if(or->responded == 0){
  232. or->flush = erealloc9p(or->flush, (or->nflush+1)*sizeof(or->flush[0]));
  233. or->flush[or->nflush++] = r;
  234. qunlock(&or->lk);
  235. return -1; /* delay response until or is responded */
  236. }
  237. qunlock(&or->lk);
  238. closereq(or);
  239. }
  240. r->oldreq = nil;
  241. return 0;
  242. }
  243. static char*
  244. oldwalk1(Fid *fid, char *name, void *arg)
  245. {
  246. char *e;
  247. Qid qid;
  248. Srv *srv;
  249. srv = arg;
  250. e = srv->walk1(fid, name, &qid);
  251. if(e)
  252. return e;
  253. fid->qid = qid;
  254. return nil;
  255. }
  256. static char*
  257. oldclone(Fid *fid, Fid *newfid, void *arg)
  258. {
  259. Srv *srv;
  260. srv = arg;
  261. if(srv->clone == nil)
  262. return nil;
  263. return srv->clone(fid, newfid);
  264. }
  265. static void
  266. swalk(Srv *srv, Req *r)
  267. {
  268. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  269. respond(r, Eunknownfid);
  270. return;
  271. }
  272. if(r->fid->omode != -1){
  273. respond(r, "cannot clone open fid");
  274. return;
  275. }
  276. if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)){
  277. respond(r, Ewalknodir);
  278. return;
  279. }
  280. if(r->ifcall.fid != r->ifcall.newfid){
  281. if((r->newfid = allocfid(srv->fpool, r->ifcall.newfid)) == nil){
  282. respond(r, Edupfid);
  283. return;
  284. }
  285. r->newfid->uid = estrdup9p(r->fid->uid);
  286. }else{
  287. incref(&r->fid->ref);
  288. r->newfid = r->fid;
  289. }
  290. if(r->fid->file){
  291. filewalk(r);
  292. }else if(srv->walk1)
  293. walkandclone(r, oldwalk1, oldclone, srv);
  294. else if(srv->walk)
  295. srv->walk(r);
  296. else
  297. sysfatal("no walk function, no file trees");
  298. }
  299. static void
  300. rwalk(Req *r, char *error)
  301. {
  302. if(error || r->ofcall.nwqid < r->ifcall.nwname){
  303. if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
  304. closefid(removefid(r->srv->fpool, r->newfid->fid));
  305. if (r->ofcall.nwqid==0){
  306. if(error==nil && r->ifcall.nwname!=0)
  307. r->error = Enotfound;
  308. }else
  309. r->error = nil; // No error on partial walks
  310. }else{
  311. if(r->ofcall.nwqid == 0){
  312. /* Just a clone */
  313. r->newfid->qid = r->fid->qid;
  314. }else{
  315. /* if file trees are in use, filewalk took care of the rest */
  316. r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];
  317. }
  318. }
  319. }
  320. static void
  321. sopen(Srv *srv, Req *r)
  322. {
  323. int p;
  324. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  325. respond(r, Eunknownfid);
  326. return;
  327. }
  328. if(r->fid->omode != -1){
  329. respond(r, Ebotch);
  330. return;
  331. }
  332. if((r->fid->qid.type&QTDIR) && (r->ifcall.mode&~ORCLOSE) != OREAD){
  333. respond(r, Eisdir);
  334. return;
  335. }
  336. r->ofcall.qid = r->fid->qid;
  337. switch(r->ifcall.mode&3){
  338. default:
  339. assert(0);
  340. case OREAD:
  341. p = AREAD;
  342. break;
  343. case OWRITE:
  344. p = AWRITE;
  345. break;
  346. case ORDWR:
  347. p = AREAD|AWRITE;
  348. break;
  349. case OEXEC:
  350. p = AEXEC;
  351. break;
  352. }
  353. if(r->ifcall.mode&OTRUNC)
  354. p |= AWRITE;
  355. if((r->fid->qid.type&QTDIR) && p!=AREAD){
  356. respond(r, Eperm);
  357. return;
  358. }
  359. if(r->fid->file){
  360. if(!hasperm(r->fid->file, r->fid->uid, p)){
  361. respond(r, Eperm);
  362. return;
  363. }
  364. /* BUG RACE */
  365. if((r->ifcall.mode&ORCLOSE)
  366. && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
  367. respond(r, Eperm);
  368. return;
  369. }
  370. r->ofcall.qid = r->fid->file->qid;
  371. if((r->ofcall.qid.type&QTDIR)
  372. && (r->fid->rdir = opendirfile(r->fid->file)) == nil){
  373. respond(r, "opendirfile failed");
  374. return;
  375. }
  376. }
  377. if(srv->open)
  378. srv->open(r);
  379. else
  380. respond(r, nil);
  381. }
  382. static void
  383. ropen(Req *r, char *error)
  384. {
  385. char errbuf[ERRMAX];
  386. if(error)
  387. return;
  388. if(chatty9p){
  389. snprint(errbuf, sizeof errbuf, "fid mode is 0x%ux\n", r->ifcall.mode);
  390. write(2, errbuf, strlen(errbuf));
  391. }
  392. r->fid->omode = r->ifcall.mode;
  393. r->fid->qid = r->ofcall.qid;
  394. if(r->ofcall.qid.type&QTDIR)
  395. r->fid->diroffset = 0;
  396. }
  397. static void
  398. screate(Srv *srv, Req *r)
  399. {
  400. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil)
  401. respond(r, Eunknownfid);
  402. else if(r->fid->omode != -1)
  403. respond(r, Ebotch);
  404. else if(!(r->fid->qid.type&QTDIR))
  405. respond(r, Ecreatenondir);
  406. else if(r->fid->file && !hasperm(r->fid->file, r->fid->uid, AWRITE))
  407. respond(r, Eperm);
  408. else if(srv->create)
  409. srv->create(r);
  410. else
  411. respond(r, Enocreate);
  412. }
  413. static void
  414. rcreate(Req *r, char *error)
  415. {
  416. if(error)
  417. return;
  418. r->fid->omode = r->ifcall.mode;
  419. r->fid->qid = r->ofcall.qid;
  420. }
  421. static void
  422. sread(Srv *srv, Req *r)
  423. {
  424. int o;
  425. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  426. respond(r, Eunknownfid);
  427. return;
  428. }
  429. if(r->ifcall.count < 0){
  430. respond(r, Ebotch);
  431. return;
  432. }
  433. if(r->ifcall.offset < 0
  434. || ((r->fid->qid.type&QTDIR) && r->ifcall.offset != 0 && r->ifcall.offset != r->fid->diroffset)){
  435. respond(r, Ebadoffset);
  436. return;
  437. }
  438. if(r->ifcall.count > srv->msize - IOHDRSZ)
  439. r->ifcall.count = srv->msize - IOHDRSZ;
  440. r->rbuf = emalloc9p(r->ifcall.count);
  441. r->ofcall.data = r->rbuf;
  442. o = r->fid->omode & 3;
  443. if(o != OREAD && o != ORDWR && o != OEXEC){
  444. respond(r, Ebotch);
  445. return;
  446. }
  447. if((r->fid->qid.type&QTDIR) && r->fid->file){
  448. r->ofcall.count = readdirfile(r->fid->rdir, r->rbuf, r->ifcall.count);
  449. respond(r, nil);
  450. return;
  451. }
  452. if(srv->read)
  453. srv->read(r);
  454. else
  455. respond(r, "no srv->read");
  456. }
  457. static void
  458. rread(Req *r, char *error)
  459. {
  460. if(error==nil && (r->fid->qid.type&QTDIR))
  461. r->fid->diroffset += r->ofcall.count;
  462. }
  463. static void
  464. swrite(Srv *srv, Req *r)
  465. {
  466. int o;
  467. char e[ERRMAX];
  468. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  469. respond(r, Eunknownfid);
  470. return;
  471. }
  472. if(r->ifcall.count < 0){
  473. respond(r, Ebotch);
  474. return;
  475. }
  476. if(r->ifcall.offset < 0){
  477. respond(r, Ebotch);
  478. return;
  479. }
  480. if(r->ifcall.count > srv->msize - IOHDRSZ)
  481. r->ifcall.count = srv->msize - IOHDRSZ;
  482. o = r->fid->omode & 3;
  483. if(o != OWRITE && o != ORDWR){
  484. snprint(e, sizeof e, "write on fid with open mode 0x%ux", r->fid->omode);
  485. respond(r, e);
  486. return;
  487. }
  488. if(srv->write)
  489. srv->write(r);
  490. else
  491. respond(r, "no srv->write");
  492. }
  493. static void
  494. rwrite(Req *r, char *error)
  495. {
  496. if(error)
  497. return;
  498. if(r->fid->file)
  499. r->fid->file->qid.vers++;
  500. }
  501. static void
  502. sclunk(Srv *srv, Req *r)
  503. {
  504. if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil)
  505. respond(r, Eunknownfid);
  506. else
  507. respond(r, nil);
  508. }
  509. static void
  510. rclunk(Req*, char*)
  511. {
  512. }
  513. static void
  514. sremove(Srv *srv, Req *r)
  515. {
  516. if((r->fid = removefid(srv->fpool, r->ifcall.fid)) == nil){
  517. respond(r, Eunknownfid);
  518. return;
  519. }
  520. /* BUG RACE */
  521. if(r->fid->file && !hasperm(r->fid->file->parent, r->fid->uid, AWRITE)){
  522. respond(r, Eperm);
  523. return;
  524. }
  525. if(srv->remove)
  526. srv->remove(r);
  527. else
  528. respond(r, r->fid->file ? nil : Enoremove);
  529. }
  530. static void
  531. rremove(Req *r, char *error, char *errbuf)
  532. {
  533. if(error)
  534. return;
  535. if(r->fid->file){
  536. if(removefile(r->fid->file) < 0){
  537. snprint(errbuf, ERRMAX, "remove %s: %r",
  538. r->fid->file->name);
  539. r->error = errbuf;
  540. }
  541. r->fid->file = nil;
  542. }
  543. }
  544. static void
  545. sstat(Srv *srv, Req *r)
  546. {
  547. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  548. respond(r, Eunknownfid);
  549. return;
  550. }
  551. if(r->fid->file){
  552. r->d = r->fid->file->Dir;
  553. if(r->d.name)
  554. r->d.name = estrdup9p(r->d.name);
  555. if(r->d.uid)
  556. r->d.uid = estrdup9p(r->d.uid);
  557. if(r->d.gid)
  558. r->d.gid = estrdup9p(r->d.gid);
  559. if(r->d.muid)
  560. r->d.muid = estrdup9p(r->d.muid);
  561. }
  562. if(srv->stat)
  563. srv->stat(r);
  564. else if(r->fid->file)
  565. respond(r, nil);
  566. else
  567. respond(r, Enostat);
  568. }
  569. static void
  570. rstat(Req *r, char *error)
  571. {
  572. int n;
  573. uchar *statbuf;
  574. uchar tmp[BIT16SZ];
  575. if(error)
  576. return;
  577. if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){
  578. r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ";
  579. return;
  580. }
  581. n = GBIT16(tmp)+BIT16SZ;
  582. statbuf = emalloc9p(n);
  583. if(statbuf == nil){
  584. r->error = "out of memory";
  585. return;
  586. }
  587. r->ofcall.nstat = convD2M(&r->d, statbuf, n);
  588. r->ofcall.stat = statbuf; /* freed in closereq */
  589. if(r->ofcall.nstat < 0){
  590. r->error = "convD2M fails";
  591. free(statbuf);
  592. return;
  593. }
  594. }
  595. static void
  596. swstat(Srv *srv, Req *r)
  597. {
  598. if((r->fid = lookupfid(srv->fpool, r->ifcall.fid)) == nil){
  599. respond(r, Eunknownfid);
  600. return;
  601. }
  602. if(srv->wstat == nil){
  603. respond(r, Enowstat);
  604. return;
  605. }
  606. if(convM2D(r->ifcall.stat, r->ifcall.nstat, &r->d, (char*)r->ifcall.stat) != r->ifcall.nstat){
  607. respond(r, Ebaddir);
  608. return;
  609. }
  610. if((ushort)~r->d.type){
  611. respond(r, "wstat -- attempt to change type");
  612. return;
  613. }
  614. if((uint)~r->d.dev){
  615. respond(r, "wstat -- attempt to change dev");
  616. return;
  617. }
  618. if((uchar)~r->d.qid.type || (ulong)~r->d.qid.vers || (uvlong)~r->d.qid.path){
  619. respond(r, "wstat -- attempt to change qid");
  620. return;
  621. }
  622. if(r->d.muid && r->d.muid[0]){
  623. respond(r, "wstat -- attempt to change muid");
  624. return;
  625. }
  626. if((ulong)~r->d.mode && ((r->d.mode&DMDIR)>>24) != (r->fid->qid.type&QTDIR)){
  627. respond(r, "wstat -- attempt to change DMDIR bit");
  628. return;
  629. }
  630. srv->wstat(r);
  631. }
  632. static void
  633. rwstat(Req*, char*)
  634. {
  635. }
  636. void
  637. srv(Srv *srv)
  638. {
  639. Req *r;
  640. fmtinstall('D', dirfmt);
  641. fmtinstall('F', fcallfmt);
  642. if(srv->fpool == nil)
  643. srv->fpool = allocfidpool(srv->destroyfid);
  644. if(srv->rpool == nil)
  645. srv->rpool = allocreqpool(srv->destroyreq);
  646. if(srv->msize == 0)
  647. srv->msize = 8192+IOHDRSZ;
  648. changemsize(srv, srv->msize);
  649. srv->fpool->srv = srv;
  650. srv->rpool->srv = srv;
  651. while(r = getreq(srv)){
  652. if(r->error){
  653. respond(r, r->error);
  654. continue;
  655. }
  656. switch(r->ifcall.type){
  657. default:
  658. respond(r, "unknown message");
  659. break;
  660. case Tversion: sversion(srv, r); break;
  661. case Tauth: sauth(srv, r); break;
  662. case Tattach: sattach(srv, r); break;
  663. case Tflush: sflush(srv, r); break;
  664. case Twalk: swalk(srv, r); break;
  665. case Topen: sopen(srv, r); break;
  666. case Tcreate: screate(srv, r); break;
  667. case Tread: sread(srv, r); break;
  668. case Twrite: swrite(srv, r); break;
  669. case Tclunk: sclunk(srv, r); break;
  670. case Tremove: sremove(srv, r); break;
  671. case Tstat: sstat(srv, r); break;
  672. case Twstat: swstat(srv, r); break;
  673. }
  674. }
  675. if(srv->end)
  676. srv->end(srv);
  677. }
  678. void
  679. respond(Req *r, char *error)
  680. {
  681. int i, m, n;
  682. char errbuf[ERRMAX];
  683. Srv *srv;
  684. srv = r->srv;
  685. assert(srv != nil);
  686. assert(r->responded == 0);
  687. r->error = error;
  688. switch(r->ifcall.type){
  689. default:
  690. assert(0);
  691. /*
  692. * Flush is special. If the handler says so, we return
  693. * without further processing. Respond will be called
  694. * again once it is safe.
  695. */
  696. case Tflush:
  697. if(rflush(r, error)<0)
  698. return;
  699. break;
  700. case Tversion: rversion(r, error); break;
  701. case Tauth: rauth(r, error); break;
  702. case Tattach: rattach(r, error); break;
  703. case Twalk: rwalk(r, error); break;
  704. case Topen: ropen(r, error); break;
  705. case Tcreate: rcreate(r, error); break;
  706. case Tread: rread(r, error); break;
  707. case Twrite: rwrite(r, error); break;
  708. case Tclunk: rclunk(r, error); break;
  709. case Tremove: rremove(r, error, errbuf); break;
  710. case Tstat: rstat(r, error); break;
  711. case Twstat: rwstat(r, error); break;
  712. }
  713. r->ofcall.tag = r->ifcall.tag;
  714. r->ofcall.type = r->ifcall.type+1;
  715. if(r->error)
  716. setfcallerror(&r->ofcall, r->error);
  717. if(chatty9p)
  718. fprint(2, "-%d-> %F\n", srv->outfd, &r->ofcall);
  719. qlock(&srv->wlock);
  720. n = convS2M(&r->ofcall, srv->wbuf, srv->msize);
  721. if(n <= 0){
  722. fprint(2, "n = %d %F\n", n, &r->ofcall);
  723. abort();
  724. }
  725. assert(n > 2);
  726. if(r->pool) /* not a fake */
  727. closereq(removereq(r->pool, r->ifcall.tag));
  728. m = write(srv->outfd, srv->wbuf, n);
  729. if(m != n)
  730. sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd);
  731. qunlock(&srv->wlock);
  732. qlock(&r->lk); /* no one will add flushes now */
  733. r->responded = 1;
  734. qunlock(&r->lk);
  735. for(i=0; i<r->nflush; i++)
  736. respond(r->flush[i], nil);
  737. free(r->flush);
  738. if(r->pool)
  739. closereq(r);
  740. else
  741. free(r);
  742. }
  743. int
  744. postfd(char *name, int pfd)
  745. {
  746. int fd;
  747. char buf[80];
  748. snprint(buf, sizeof buf, "/srv/%s", name);
  749. if(chatty9p)
  750. fprint(2, "postfd %s\n", buf);
  751. fd = create(buf, OWRITE|ORCLOSE|OCEXEC, 0600);
  752. if(fd < 0){
  753. if(chatty9p)
  754. fprint(2, "create fails: %r\n");
  755. return -1;
  756. }
  757. if(fprint(fd, "%d", pfd) < 0){
  758. if(chatty9p)
  759. fprint(2, "write fails: %r\n");
  760. close(fd);
  761. return -1;
  762. }
  763. if(chatty9p)
  764. fprint(2, "postfd successful\n");
  765. return 0;
  766. }