srv.c 17 KB

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