srvold9p.c 19 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include <libsec.h>
  6. #include "9p1.h"
  7. char *user;
  8. int newfd;
  9. int roldfd;
  10. int woldfd;
  11. int debug;
  12. int dofcall;
  13. QLock servelock;
  14. QLock fidlock;
  15. QLock taglock;
  16. int mainpid;
  17. int ntag;
  18. int nfork;
  19. char FLUSHED[] = "FLUSHED";
  20. enum{
  21. Maxfdata = 8192
  22. };
  23. enum{
  24. Command,
  25. Network,
  26. File,
  27. Stdio,
  28. };
  29. typedef struct Tag Tag;
  30. struct Tag
  31. {
  32. int tag;
  33. int flushed;
  34. int received;
  35. int ref;
  36. Tag *next;
  37. };
  38. typedef struct Message Message;
  39. struct Message
  40. {
  41. char *data;
  42. int n;
  43. };
  44. typedef struct Fid Fid;
  45. struct Fid
  46. {
  47. short busy;
  48. short allocated;
  49. int fid;
  50. Qid qid;
  51. ulong newoffset;
  52. ulong oldoffset;
  53. Fid *next;
  54. };
  55. Fid *fids;
  56. Tag *tags;
  57. char *rflush(Fcall*, Fcall*, char*),
  58. *rversion(Fcall*, Fcall*, char*),
  59. *rauth(Fcall*, Fcall*, char*),
  60. *rattach(Fcall*, Fcall*, char*),
  61. *rwalk(Fcall*, Fcall*, char*),
  62. *ropen(Fcall*, Fcall*, char*),
  63. *rcreate(Fcall*, Fcall*, char*),
  64. *rread(Fcall*, Fcall*, char*),
  65. *rwrite(Fcall*, Fcall*, char*),
  66. *rclunk(Fcall*, Fcall*, char*),
  67. *rremove(Fcall*, Fcall*, char*),
  68. *rstat(Fcall*, Fcall*, char*),
  69. *rwstat(Fcall*, Fcall*, char*);
  70. char *(*fcalls[])(Fcall*, Fcall*, char*) = {
  71. [Tversion] rversion,
  72. [Tflush] rflush,
  73. [Tauth] rauth,
  74. [Tattach] rattach,
  75. [Twalk] rwalk,
  76. [Topen] ropen,
  77. [Tcreate] rcreate,
  78. [Tread] rread,
  79. [Twrite] rwrite,
  80. [Tclunk] rclunk,
  81. [Tremove] rremove,
  82. [Tstat] rstat,
  83. [Twstat] rwstat,
  84. };
  85. char Etoolong[] = "name too long";
  86. void connect(int, char*);
  87. void post(int, char*);
  88. void serve(void);
  89. void demux(void);
  90. void* emalloc(ulong);
  91. char* transact9p1(Fcall9p1*, Fcall9p1*, char*);
  92. Fid* newfid(int);
  93. struct
  94. {
  95. char chal[CHALLEN]; /* my challenge */
  96. char rchal[CHALLEN]; /* his challenge */
  97. char authid[NAMEREC];
  98. char authdom[DOMLEN];
  99. int id;
  100. } ai;
  101. void
  102. usage(void)
  103. {
  104. fprint(2, "usage: srvold9p [-abcCd] [-u user] [-s | [-m mountpoint]] [-x 'command' | -n network-addr | -f file] [-F] [-p servicename]\n");
  105. exits("usage");
  106. }
  107. void
  108. main(int argc, char *argv[])
  109. {
  110. int method;
  111. char *oldstring;
  112. char *mountpoint, *postname;
  113. int mountflag, mountfd;
  114. int p[2];
  115. int i;
  116. fmtinstall('F', fcallfmt);
  117. fmtinstall('G', fcallfmt9p1);
  118. fmtinstall('D', dirfmt);
  119. user = getuser();
  120. mountpoint = nil;
  121. mountflag = 0;
  122. postname = nil;
  123. oldstring = nil;
  124. method = -1;
  125. mountfd = -1;
  126. ARGBEGIN{
  127. case 'a':
  128. mountflag |= MAFTER;
  129. break;
  130. case 'b':
  131. mountflag |= MBEFORE;
  132. break;
  133. case 'c':
  134. mountflag |= MCREATE;
  135. break;
  136. case 'C':
  137. mountflag |= MCACHE;
  138. break;
  139. case 'd':
  140. debug++;
  141. break;
  142. case 'f':
  143. method = File;
  144. oldstring = ARGF();
  145. break;
  146. case 'F':
  147. dofcall++;
  148. break;
  149. case 'm':
  150. mountpoint = EARGF(usage());
  151. break;
  152. case 'n':
  153. method = Network;
  154. oldstring = ARGF();
  155. break;
  156. case 'p':
  157. postname = ARGF();
  158. if(postname == nil)
  159. usage();
  160. break;
  161. case 's':
  162. method = Stdio;
  163. break;
  164. case 'u':
  165. user = EARGF(usage());
  166. break;
  167. case 'x':
  168. method = Command;
  169. oldstring = ARGF();
  170. break;
  171. default:
  172. usage();
  173. }ARGEND;
  174. if(method == Stdio){
  175. if(mountpoint!=nil || argc!=0)
  176. usage();
  177. }else{
  178. if(oldstring == nil || argc != 0 || (mountflag!=0 && mountpoint==nil))
  179. usage();
  180. }
  181. rfork(RFNOTEG|RFREND);
  182. connect(method, oldstring);
  183. if(method == Stdio)
  184. newfd = 0;
  185. else{
  186. if(pipe(p) < 0)
  187. fatal("pipe: %r");
  188. if(postname != nil)
  189. post(p[0], postname);
  190. mountfd = p[0];
  191. newfd = p[1];
  192. }
  193. if(debug)
  194. fprint(2, "connected and posted\n");
  195. switch(rfork(RFPROC|RFMEM|RFNAMEG|RFFDG)){
  196. case 0:
  197. mainpid = getpid();
  198. /* child does all the work */
  199. if(mountfd >= 0)
  200. close(mountfd);
  201. switch(rfork(RFPROC|RFMEM|RFFDG)){
  202. case 0:
  203. for(i = 0; i < 20; i++)
  204. if (i != roldfd) close(i);
  205. demux();
  206. return;
  207. case -1:
  208. fatal("fork error: %r");
  209. break;
  210. }
  211. for(i = 0; i < 20; i++)
  212. if (i != newfd && i != woldfd && (debug == 0 || i != 2)) close(i);
  213. serve();
  214. break;
  215. case -1:
  216. fatal("fork error: %r");
  217. break;
  218. default:
  219. /* parent mounts if required, then exits */
  220. if(mountpoint){
  221. if(mount(mountfd, -1, mountpoint, mountflag, "") < 0)
  222. fatal("can't mount: %r");
  223. }
  224. break;
  225. }
  226. exits(nil);
  227. }
  228. void
  229. connect(int method, char *oldstring)
  230. {
  231. char *s;
  232. char dir[256];
  233. switch(method){
  234. default:
  235. roldfd = -1;
  236. woldfd = -1;
  237. fatal("can't handle method type %d", method);
  238. break;
  239. case Network:
  240. s = netmkaddr(oldstring, 0, "9fs");
  241. roldfd = dial(s, 0, dir, 0);
  242. if(roldfd < 0)
  243. fatal("dial %s: %r", s);
  244. woldfd = roldfd;
  245. if(dofcall)
  246. roldfd = fcall(woldfd);
  247. break;
  248. case File:
  249. roldfd = open(oldstring, ORDWR);
  250. if(roldfd < 0)
  251. fatal("can't open %s: %r", oldstring);
  252. woldfd = roldfd;
  253. if(dofcall)
  254. roldfd = fcall(woldfd);
  255. break;
  256. case Stdio:
  257. roldfd = fcall(1);
  258. woldfd = 1;
  259. break;
  260. }
  261. }
  262. void
  263. post(int fd, char *srv)
  264. {
  265. int f;
  266. char buf[128];
  267. snprint(buf, sizeof buf, "/srv/%s", srv);
  268. f = create(buf, OWRITE, 0666);
  269. if(f < 0)
  270. fatal("can't create %s: %r", buf);
  271. sprint(buf, "%d", fd);
  272. if(write(f, buf, strlen(buf)) != strlen(buf))
  273. fatal("post write: %r");
  274. close(f);
  275. }
  276. Fid *
  277. newfid(int fid)
  278. {
  279. Fid *f, *ff;
  280. ff = 0;
  281. qlock(&fidlock);
  282. for(f = fids; f; f = f->next)
  283. if(f->fid == fid){
  284. f->allocated = 1;
  285. qunlock(&fidlock);
  286. return f;
  287. }
  288. else if(!ff && !f->allocated)
  289. ff = f;
  290. if(ff){
  291. ff->fid = fid;
  292. ff->allocated = 1;
  293. qunlock(&fidlock);
  294. return ff;
  295. }
  296. f = emalloc(sizeof *f);
  297. f->fid = fid;
  298. f->next = fids;
  299. f->allocated = 1;
  300. fids = f;
  301. qunlock(&fidlock);
  302. return f;
  303. }
  304. /*
  305. * Reads returning 9P1 messages and demultiplexes them.
  306. * BUG: assumes one read per message.
  307. */
  308. void
  309. demux(void)
  310. {
  311. int m, n;
  312. char *data;
  313. Fcall9p1 r;
  314. Message *msg;
  315. Tag *t;
  316. for(;;){
  317. data = malloc(IOHDRSZ+Maxfdata); /* no need to clear memory */
  318. if(data == nil)
  319. fatal("demux malloc: %r");
  320. m = read(roldfd, data, IOHDRSZ+Maxfdata);
  321. if(m <= 0)
  322. fatal("read error talking to old system: %r");
  323. n = convM2S9p1(data, &r, m);
  324. if(n == 0)
  325. fatal("bad conversion receiving from old system");
  326. if(debug)
  327. fprint(2, "srvold9p:<=%G\n", &r);
  328. qlock(&taglock);
  329. for(t=tags; t!=nil; t=t->next)
  330. if(t->tag == r.tag){
  331. t->received = 1;
  332. break;
  333. }
  334. qunlock(&taglock);
  335. /*
  336. * Fcall9p1 tag is used to rendezvous.
  337. * Recipient converts message a second time, but that's OK.
  338. */
  339. msg = emalloc(sizeof(Message));
  340. msg->data = data;
  341. msg->n = n;
  342. rendezvous((void*)r.tag, msg);
  343. }
  344. }
  345. Tag*
  346. newtag(int tag)
  347. {
  348. Tag *t;
  349. t = emalloc(sizeof(Tag));
  350. t->tag = tag;
  351. t->flushed = 0;
  352. t->received = 0;
  353. t->ref = 1;
  354. qlock(&taglock);
  355. t->next = tags;
  356. tags = t;
  357. qunlock(&taglock);
  358. return t;
  359. }
  360. void
  361. freetag(Tag *tag) /* called with taglock set */
  362. {
  363. Tag *t, *prev;
  364. if(tag->ref-- == 1){
  365. prev = nil;
  366. for(t=tags; t!=nil; t=t->next){
  367. if(t == tag){
  368. if(prev == nil)
  369. tags = t->next;
  370. else
  371. prev->next = t->next;
  372. break;
  373. }
  374. prev = t;
  375. }
  376. if(t == nil)
  377. sysfatal("freetag");
  378. free(tag);
  379. }
  380. }
  381. void
  382. serve(void)
  383. {
  384. char *err;
  385. int n;
  386. Fcall thdr;
  387. Fcall rhdr;
  388. uchar mdata[IOHDRSZ+Maxfdata];
  389. char mdata9p1[IOHDRSZ+Maxfdata];
  390. Tag *tag;
  391. for(;;){
  392. qlock(&servelock);
  393. for(;;){
  394. n = read9pmsg(newfd, mdata, sizeof mdata);
  395. if(n == 0)
  396. continue;
  397. if(n < 0)
  398. break;
  399. if(n > 0 && convM2S(mdata, n, &thdr) > 0)
  400. break;
  401. }
  402. if(n>0 && servelock.head==nil) /* no other processes waiting to read */
  403. switch(rfork(RFPROC|RFMEM)){
  404. case 0:
  405. /* child starts serving */
  406. continue;
  407. break;
  408. case -1:
  409. fatal("fork error: %r");
  410. break;
  411. default:
  412. break;
  413. }
  414. qunlock(&servelock);
  415. if(n < 0)
  416. fatal(nil); /* exit quietly; remote end has just hung up */
  417. if(debug)
  418. fprint(2, "srvold9p:<-%F\n", &thdr);
  419. tag = newtag(thdr.tag);
  420. if(!fcalls[thdr.type])
  421. err = "bad fcall type";
  422. else
  423. err = (*fcalls[thdr.type])(&thdr, &rhdr, mdata9p1);
  424. qlock(&taglock);
  425. if(tag->flushed){
  426. freetag(tag);
  427. qunlock(&taglock);
  428. continue;
  429. }
  430. qunlock(&taglock);
  431. if(err){
  432. rhdr.type = Rerror;
  433. rhdr.ename = err;
  434. }else{
  435. rhdr.type = thdr.type + 1;
  436. rhdr.fid = thdr.fid;
  437. }
  438. rhdr.tag = thdr.tag;
  439. if(debug)
  440. fprint(2, "srvold9p:->%F\n", &rhdr);/**/
  441. n = convS2M(&rhdr, mdata, sizeof mdata);
  442. if(n == 0)
  443. fatal("convS2M error on write");
  444. if(write(newfd, mdata, n) != n)
  445. fatal("mount write");
  446. qlock(&taglock);
  447. freetag(tag);
  448. qunlock(&taglock);
  449. }
  450. }
  451. void
  452. send9p1(Fcall9p1 *t, char *data)
  453. {
  454. int m, n;
  455. if(debug)
  456. fprint(2, "srvold9p:=>%G\n", t);
  457. n = convS2M9p1(t, data);
  458. if(n == 0)
  459. fatal("bad conversion sending to old system");
  460. m = write(woldfd, data, n);
  461. if(m != n)
  462. fatal("wrote %d to old system; should be %d", m, n);
  463. }
  464. int
  465. recv9p1(Fcall9p1 *r, int tag, char *data)
  466. {
  467. int n;
  468. Message *msg;
  469. msg = rendezvous((void*)tag, 0);
  470. if(msg == (void*)~0)
  471. fatal("rendezvous: %r");
  472. if(msg == nil){
  473. if(debug)
  474. fprint(2, "recv flushed\n");
  475. return -1;
  476. }
  477. /* copy data to local buffer */
  478. memmove(data, msg->data, msg->n);
  479. n = convM2S9p1(data, r, msg->n);
  480. if(n == 0)
  481. fatal("bad conversion receiving from old system");
  482. free(msg->data);
  483. free(msg);
  484. return 1;
  485. }
  486. char*
  487. transact9p1(Fcall9p1 *t, Fcall9p1 *r, char *mdata9p1)
  488. {
  489. send9p1(t, mdata9p1);
  490. if(recv9p1(r, t->tag, mdata9p1) < 0)
  491. return FLUSHED;
  492. if(r->type == Rerror9p1)
  493. return r->ename;
  494. if(r->type != t->type+1)
  495. fatal("bad message type; expected %d got %d", t->type+1, r->type);
  496. return nil;
  497. }
  498. char*
  499. rflush(Fcall *t, Fcall *, char *mdata9p1)
  500. {
  501. Fcall9p1 t9, r9;
  502. Tag *oldt;
  503. t9.type = Tflush9p1;
  504. t9.tag = t->tag;
  505. t9.oldtag = t->oldtag;
  506. qlock(&taglock);
  507. for(oldt=tags; oldt!=nil; oldt=oldt->next)
  508. if(oldt->tag == t->oldtag){
  509. oldt->flushed = 1;
  510. oldt->ref++;
  511. break;
  512. }
  513. qunlock(&taglock);
  514. if(oldt == nil){ /* nothing to flush */
  515. if(debug)
  516. fprint(2, "no such tag to flush\n");
  517. return 0;
  518. }
  519. transact9p1(&t9, &r9, mdata9p1); /* can't error */
  520. qlock(&taglock);
  521. if(oldt->received == 0){ /* wake up receiver */
  522. if(debug)
  523. fprint(2, "wake up receiver\n");
  524. oldt->received = 1;
  525. rendezvous((void*)t->oldtag, 0);
  526. }
  527. freetag(oldt);
  528. qunlock(&taglock);
  529. return 0;
  530. }
  531. char*
  532. rversion(Fcall *t, Fcall *r, char*)
  533. {
  534. Fid *f;
  535. /* just ack; this one doesn't go to old service */
  536. if(t->msize > IOHDRSZ+Maxfdata)
  537. r->msize = IOHDRSZ+Maxfdata;
  538. else
  539. r->msize = t->msize;
  540. if(strncmp(t->version, "9P2000", 6) != 0)
  541. return "unknown 9P version";
  542. r->version = "9P2000";
  543. qlock(&fidlock);
  544. for(f = fids; f; f = f->next){
  545. f->busy = 0;
  546. f->allocated = 0;
  547. }
  548. qunlock(&fidlock);
  549. return 0;
  550. }
  551. char*
  552. rauth(Fcall *, Fcall *, char *)
  553. {
  554. return "srvold9p: authentication not supported";
  555. }
  556. #ifdef asdf
  557. void
  558. memrandom(void *p, int n)
  559. {
  560. ulong *lp;
  561. uchar *cp;
  562. for(lp = p; n >= sizeof(ulong); n -= sizeof(ulong))
  563. *lp++ = fastrand();
  564. for(cp = (uchar*)lp; n > 0; n--)
  565. *cp++ = fastrand();
  566. }
  567. char*
  568. rsession(Fcall *t, Fcall *r, char *mdata9p1)
  569. {
  570. char *err;
  571. Fcall9p1 t9, r9;
  572. Fid *f;
  573. t9.type = Tsession9p1;
  574. t9.tag = t->tag;
  575. if(doauth)
  576. memrandom(t9.chal, sizeof t9.chal);
  577. else
  578. memset(t9.chal, 0, sizeof t9.chal);
  579. err = transact9p1(&t9, &r9, mdata9p1);
  580. if(err)
  581. return err;
  582. qlock(&fidlock);
  583. for(f = fids; f; f = f->next){
  584. f->busy = 0;
  585. f->allocated = 0;
  586. }
  587. qunlock(&fidlock);
  588. if(doauth){
  589. memmove(ai.authid, r9.authid, sizeof ai.authid);
  590. memmove(ai.authdom, r9.authdom, sizeof ai.authid);
  591. memmove(ai.rchal, r9.chal, sizeof ai.rchal);
  592. memmove(ai.chal, t9.chal, sizeof ai.chal);
  593. r->authid = ai.authid;
  594. r->authdom = ai.authdom;
  595. r->chal = (uchar*)ai.rchal;
  596. r->nchal = CHALLEN;
  597. } else {
  598. r->authid = "";
  599. r->authdom = "";
  600. r->nchal = 0;
  601. r->chal = nil;
  602. }
  603. return 0;
  604. }
  605. #endif
  606. char*
  607. rattach(Fcall *t, Fcall *r, char *mdata9p1)
  608. {
  609. char *err;
  610. Fcall9p1 t9, r9;
  611. Fid *f;
  612. f = newfid(t->fid);
  613. if(f->busy)
  614. return "attach: fid in use";
  615. /* no authentication! */
  616. t9.type = Tattach9p1;
  617. t9.tag = t->tag;
  618. t9.fid = t->fid;
  619. strncpy(t9.uname, t->uname, NAMEREC);
  620. if(strcmp(user, "none") == 0)
  621. strncpy(t9.uname, user, NAMEREC);
  622. strncpy(t9.aname, t->aname, NAMEREC);
  623. memset(t9.ticket, 0, sizeof t9.ticket);
  624. memset(t9.auth, 0, sizeof t9.auth);
  625. err = transact9p1(&t9, &r9, mdata9p1);
  626. if(err)
  627. return err;
  628. r->qid.path = r9.qid.path & ~0x80000000;
  629. r->qid.vers = r9.qid.version;
  630. r->qid.type = QTDIR;
  631. f->busy = 1;
  632. f->qid = r->qid;
  633. return 0;
  634. }
  635. char*
  636. rwalk(Fcall *t, Fcall *r, char *mdata9p1)
  637. {
  638. char *err;
  639. Fcall9p1 t9, r9;
  640. int i, fid;
  641. Qid *q;
  642. Fid *f, *nf;
  643. f = newfid(t->fid);
  644. if(!f->busy)
  645. return "walk: bad fid";
  646. fid = t->fid;
  647. nf = nil;
  648. if(t->fid != t->newfid){
  649. nf = newfid(t->newfid);
  650. if(nf->busy)
  651. return "walk: newfid in use";
  652. t9.type = Tclone9p1;
  653. t9.tag = t->tag;
  654. t9.fid = t->fid;
  655. t9.newfid = t->newfid;
  656. err = transact9p1(&t9, &r9, mdata9p1);
  657. if(err){
  658. nf->busy = 0;
  659. nf->allocated = 0;
  660. return err;
  661. }
  662. fid = t->newfid;
  663. nf->busy = 1;
  664. }
  665. err = nil;
  666. r->nwqid = 0;
  667. for(i=0; i<t->nwname && err==nil; i++){
  668. if(i > MAXWELEM)
  669. break;
  670. t9.type = Twalk9p1;
  671. t9.tag = t->tag;
  672. t9.fid = fid;
  673. strncpy(t9.name, t->wname[i], NAMEREC);
  674. err = transact9p1(&t9, &r9, mdata9p1);
  675. if(err == FLUSHED){
  676. i = -1; /* guarantee cleanup */
  677. break;
  678. }
  679. if(err == nil){
  680. q = &r->wqid[r->nwqid++];
  681. q->type = QTFILE;
  682. if(r9.qid.path & 0x80000000)
  683. q->type = QTDIR;
  684. q->vers = r9.qid.version;
  685. q->path = r9.qid.path & ~0x80000000;
  686. }
  687. }
  688. if(nf!=nil && (err!=nil || i<t->nwname)){
  689. /* clunk the new fid */
  690. t9.type = Tclunk9p1;
  691. t9.tag = t->tag;
  692. t9.fid = t->newfid;
  693. transact9p1(&t9, &r9, mdata9p1);
  694. /* ignore more errors */
  695. nf->busy = 0;
  696. nf->allocated = 0;
  697. }
  698. if(i>0 && i==t->nwname && err==nil)
  699. f->qid = r->wqid[r->nwqid-1];
  700. if(i > 0)
  701. return 0;
  702. return err;
  703. }
  704. char*
  705. ropen(Fcall *t, Fcall *r, char *mdata9p1)
  706. {
  707. char *err;
  708. Fcall9p1 t9, r9;
  709. Fid *f;
  710. f = newfid(t->fid);
  711. if(!f->busy)
  712. return "open: bad fid";
  713. t9.type = Topen9p1;
  714. t9.tag = t->tag;
  715. t9.fid = t->fid;
  716. t9.mode = t->mode;
  717. err = transact9p1(&t9, &r9, mdata9p1);
  718. if(err)
  719. return err;
  720. r->qid.path = r9.qid.path & ~0x80000000;
  721. r->qid.vers = r9.qid.version;
  722. r->qid.type = QTFILE;
  723. if(r9.qid.path & 0x80000000)
  724. r->qid.type = QTDIR;
  725. f->qid = r->qid;
  726. f->newoffset = 0;
  727. f->oldoffset = 0;
  728. r->iounit = 0;
  729. return 0;
  730. }
  731. char*
  732. rcreate(Fcall *t, Fcall *r, char *mdata9p1)
  733. {
  734. char *err;
  735. Fcall9p1 t9, r9;
  736. Fid *f;
  737. f = newfid(t->fid);
  738. if(!f->busy)
  739. return "create: bad fid";
  740. t9.type = Tcreate9p1;
  741. t9.tag = t->tag;
  742. t9.fid = t->fid;
  743. if(strlen(t->name)+1 >= NAMEREC)
  744. return "file name element too long";
  745. strncpy(t9.name, t->name, NAMEREC);
  746. t9.perm = t->perm;
  747. t9.mode = t->mode;
  748. err = transact9p1(&t9, &r9, mdata9p1);
  749. if(err)
  750. return err;
  751. r->qid.path = r9.qid.path & ~0x80000000;
  752. r->qid.vers = r9.qid.version;
  753. r->qid.type = QTFILE;
  754. if(r9.qid.path & 0x80000000)
  755. r->qid.type = QTDIR;
  756. if(r9.qid.path & 0x40000000)
  757. r->qid.type |= QTAPPEND;
  758. if(r9.qid.path & 0x20000000)
  759. r->qid.type |= QTEXCL;
  760. f->qid = r->qid;
  761. r->iounit = 0;
  762. return 0;
  763. }
  764. char*
  765. dirrread(Fcall *t, Fcall *r, char *mdata9p1)
  766. {
  767. char *err;
  768. Fcall9p1 t9, r9;
  769. Fid *f;
  770. int i, ndir, n, count;
  771. Dir d;
  772. uchar buf[Maxfdata];
  773. char *old;
  774. f = newfid(t->fid);
  775. if(!f->busy)
  776. return "dirread: bad fid";
  777. if(f->newoffset != t->offset)
  778. return "seek in directory disallowed";
  779. t9.type = Tread9p1;
  780. t9.tag = t->tag;
  781. t9.fid = t->fid;
  782. t9.offset = f->oldoffset;
  783. t9.count = t->count; /* new directories tend to be smaller, so this may overshoot */
  784. err = transact9p1(&t9, &r9, mdata9p1);
  785. if(err)
  786. return err;
  787. ndir = r9.count/DIRREC;
  788. old = r9.data;
  789. count = 0;
  790. for(i=0; i<ndir; i++){
  791. if(convM2D9p1(old, &d) != DIRREC)
  792. return "bad dir conversion in read";
  793. n = convD2M(&d, buf+count, sizeof buf-count);
  794. if(n<=BIT16SZ || count+n>t->count)
  795. break;
  796. old += DIRREC;
  797. f->oldoffset += DIRREC;
  798. f->newoffset += n;
  799. count += n;
  800. }
  801. memmove(r9.data, buf, count); /* put it back in stable storage */
  802. r->data = r9.data;
  803. r->count = count;
  804. return 0;
  805. }
  806. char*
  807. rread(Fcall *t, Fcall *r, char *mdata9p1)
  808. {
  809. char *err;
  810. Fcall9p1 t9, r9;
  811. Fid *f;
  812. f = newfid(t->fid);
  813. if(!f->busy)
  814. return "read: bad fid";
  815. if(f->qid.type & QTDIR)
  816. return dirrread(t, r, mdata9p1);
  817. t9.type = Tread9p1;
  818. t9.tag = t->tag;
  819. t9.fid = t->fid;
  820. t9.offset = t->offset;
  821. t9.count = t->count;
  822. err = transact9p1(&t9, &r9, mdata9p1);
  823. if(err)
  824. return err;
  825. r->count = r9.count;
  826. r->data = r9.data; /* points to stable storage */
  827. return 0;
  828. }
  829. char*
  830. rwrite(Fcall *t, Fcall *r, char *mdata9p1)
  831. {
  832. char *err;
  833. Fcall9p1 t9, r9;
  834. Fid *f;
  835. f = newfid(t->fid);
  836. if(!f->busy)
  837. return "write: bad fid";
  838. t9.type = Twrite9p1;
  839. t9.tag = t->tag;
  840. t9.fid = t->fid;
  841. t9.offset = t->offset;
  842. t9.count = t->count;
  843. t9.data = t->data;
  844. err = transact9p1(&t9, &r9, mdata9p1);
  845. if(err)
  846. return err;
  847. r->count = r9.count;
  848. return 0;
  849. }
  850. char*
  851. rclunk(Fcall *t, Fcall *, char *mdata9p1)
  852. {
  853. Fcall9p1 t9, r9;
  854. Fid *f;
  855. f = newfid(t->fid);
  856. if(!f->busy)
  857. return "clunk: bad fid";
  858. t9.type = Tclunk9p1;
  859. t9.tag = t->tag;
  860. t9.fid = t->fid;
  861. transact9p1(&t9, &r9, mdata9p1);
  862. f->busy = 0;
  863. f->allocated = 0;
  864. /* disregard error */
  865. return 0;
  866. }
  867. char*
  868. rremove(Fcall *t, Fcall*, char *mdata9p1)
  869. {
  870. char *err;
  871. Fcall9p1 t9, r9;
  872. Fid *f;
  873. f = newfid(t->fid);
  874. if(!f->busy)
  875. return "remove: bad fid";
  876. t9.type = Tremove9p1;
  877. t9.tag = t->tag;
  878. t9.fid = t->fid;
  879. err = transact9p1(&t9, &r9, mdata9p1);
  880. f->busy = 0;
  881. f->allocated = 0;
  882. return err;
  883. }
  884. char*
  885. rstat(Fcall *t, Fcall *r, char *mdata9p1)
  886. {
  887. Fcall9p1 t9, r9;
  888. char *err;
  889. Fid *f;
  890. Dir d;
  891. uchar buf[256]; /* big enough; there's no long names */
  892. f = newfid(t->fid);
  893. if(!f->busy)
  894. return "stat: bad fid";
  895. t9.type = Tstat9p1;
  896. t9.tag = t->tag;
  897. t9.fid = t->fid;
  898. err = transact9p1(&t9, &r9, mdata9p1);
  899. if(err)
  900. return err;
  901. if(convM2D9p1(r9.stat, &d) != DIRREC)
  902. return "bad conversion in stat";
  903. r->stat = buf;
  904. r->nstat = convD2M(&d, buf, sizeof buf);
  905. return 0;
  906. }
  907. int
  908. anydefault(Dir *d)
  909. {
  910. if(d->name[0] == '\0')
  911. return 1;
  912. if(d->uid[0] == '\0')
  913. return 1;
  914. if(d->gid[0] == '\0')
  915. return 1;
  916. if(d->mode == ~0)
  917. return 1;
  918. if(d->mtime == ~0)
  919. return 1;
  920. return 0;
  921. }
  922. char*
  923. rwstat(Fcall *t, Fcall *, char *mdata9p1)
  924. {
  925. Fcall9p1 t9, r9;
  926. char strs[DIRREC];
  927. char *err;
  928. Fid *f;
  929. Dir d, cd;
  930. f = newfid(t->fid);
  931. if(!f->busy)
  932. return "wstat: bad fid";
  933. convM2D(t->stat, t->nstat, &d, strs);
  934. cd = d;
  935. if(anydefault(&d)){
  936. /* must first stat file so we can copy current values */
  937. t9.type = Tstat9p1;
  938. t9.tag = t->tag;
  939. t9.fid = t->fid;
  940. err = transact9p1(&t9, &r9, mdata9p1);
  941. if(err)
  942. return err;
  943. if(convM2D9p1(r9.stat, &cd) != DIRREC)
  944. return "bad in conversion in wstat";
  945. /* fill in default values */
  946. if(d.name[0] != '\0'){
  947. if(strlen(d.name) >= NAMEREC)
  948. return Etoolong;
  949. cd.name = d.name;
  950. }
  951. if(d.uid[0] != '\0'){
  952. if(strlen(d.uid) >= NAMEREC)
  953. return Etoolong;
  954. cd.uid = d.uid;
  955. }
  956. if(d.gid[0] != '\0'){
  957. if(strlen(d.gid) >= NAMEREC)
  958. return Etoolong;
  959. cd.gid = d.gid;
  960. }
  961. if(d.mode != ~0)
  962. cd.mode = d.mode;
  963. if(d.mtime != ~0)
  964. cd.mtime = d.mtime;
  965. if(d.length != ~0LL)
  966. cd.length = d.length;
  967. }
  968. if(convD2M9p1(&cd, t9.stat) != DIRREC)
  969. return "bad out conversion in wstat";
  970. t9.type = Twstat9p1;
  971. t9.tag = t->tag;
  972. t9.fid = t->fid;
  973. err = transact9p1(&t9, &r9, mdata9p1);
  974. if(err)
  975. return err;
  976. return 0;
  977. }
  978. void *
  979. emalloc(ulong n)
  980. {
  981. void *p;
  982. p = malloc(n);
  983. if(!p)
  984. fatal("out of memory: %r");
  985. memset(p, 0, n);
  986. return p;
  987. }
  988. void
  989. fatal(char *fmt, ...)
  990. {
  991. char buf[1024];
  992. va_list arg;
  993. if(fmt){
  994. va_start(arg, fmt);
  995. vseprint(buf, buf+sizeof(buf), fmt, arg);
  996. va_end(arg);
  997. fprint(2, "%s: (pid %d) %s\n", argv0, getpid(), buf);
  998. }else
  999. buf[0] = '\0';
  1000. if(mainpid){
  1001. /* two hits are sometimes needed */
  1002. postnote(PNGROUP, mainpid, "die1 - from srvold9p");
  1003. postnote(PNGROUP, mainpid, "die2 - from srvold9p");
  1004. }
  1005. exits(buf);
  1006. }