srv.c 17 KB

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