lnfs.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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 <bio.h>
  12. #include <auth.h>
  13. #include <fcall.h>
  14. #include <String.h>
  15. #include <libsec.h>
  16. enum
  17. {
  18. OPERM = 0x3, /* mask of all permission types in open mode */
  19. Maxsize = 512*1024*1024,
  20. Maxfdata = 8192,
  21. NAMELEN = 28,
  22. };
  23. typedef struct Fid Fid;
  24. struct Fid
  25. {
  26. int16_t busy;
  27. int fid;
  28. Fid *next;
  29. char *user;
  30. String *path; /* complete path */
  31. int fd; /* set on open or create */
  32. Qid qid; /* set on open or create */
  33. int attach; /* this is an attach fd */
  34. uint32_t diroff; /* directory offset */
  35. Dir *dir; /* directory entries */
  36. int ndir; /* number of directory entries */
  37. };
  38. Fid *fids;
  39. int mfd[2];
  40. char *user;
  41. uint8_t mdata[IOHDRSZ+Maxfdata];
  42. uint8_t rdata[Maxfdata]; /* buffer for data in reply */
  43. uint8_t statbuf[STATMAX];
  44. Fcall thdr;
  45. Fcall rhdr;
  46. int messagesize = sizeof mdata;
  47. int readonly;
  48. char *srvname;
  49. int debug;
  50. Fid * newfid(int);
  51. void io(void);
  52. void *erealloc(void *c, uint32_t);
  53. void *emalloc(uint32_t);
  54. char *estrdup(char*);
  55. void usage(void);
  56. void fidqid(Fid*, Qid*);
  57. char* short2int32_t(char*);
  58. char* int32_t2short(char*, int);
  59. void readnames(void);
  60. void post(char*, int);
  61. char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
  62. *rattach(Fid*), *rwalk(Fid*),
  63. *ropen(Fid*), *rcreate(Fid*),
  64. *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
  65. *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
  66. char *(*fcalls[])(Fid*) = {
  67. [Tversion] rversion,
  68. [Tflush] rflush,
  69. [Tauth] rauth,
  70. [Tattach] rattach,
  71. [Twalk] rwalk,
  72. [Topen] ropen,
  73. [Tcreate] rcreate,
  74. [Tread] rread,
  75. [Twrite] rwrite,
  76. [Tclunk] rclunk,
  77. [Tremove] rremove,
  78. [Tstat] rstat,
  79. [Twstat] rwstat,
  80. };
  81. char Eperm[] = "permission denied";
  82. char Enotdir[] = "not a directory";
  83. char Enoauth[] = "lnfs: authentication not required";
  84. char Enotexist[] = "file does not exist";
  85. char Einuse[] = "file in use";
  86. char Eexist[] = "file exists";
  87. char Eisdir[] = "file is a directory";
  88. char Enotowner[] = "not owner";
  89. char Eisopen[] = "file already open for I/O";
  90. char Excl[] = "exclusive use file already open";
  91. char Ename[] = "illegal name";
  92. char Eversion[] = "unknown 9P version";
  93. void
  94. usage(void)
  95. {
  96. fprint(2, "usage: %s [-r] [-s srvname] mountpoint\n", argv0);
  97. exits("usage");
  98. }
  99. void
  100. notifyf(void *a, char *s)
  101. {
  102. USED(a);
  103. if(strncmp(s, "interrupt", 9) == 0)
  104. noted(NCONT);
  105. noted(NDFLT);
  106. }
  107. void
  108. main(int argc, char *argv[])
  109. {
  110. char *defmnt;
  111. int p[2];
  112. Dir *d;
  113. ARGBEGIN{
  114. case 'r':
  115. readonly = 1;
  116. break;
  117. case 'd':
  118. debug = 1;
  119. break;
  120. case 's':
  121. srvname = ARGF();
  122. if(srvname == nil)
  123. usage();
  124. break;
  125. default:
  126. usage();
  127. }ARGEND
  128. if(argc < 1)
  129. usage();
  130. defmnt = argv[0];
  131. d = dirstat(defmnt);
  132. if(d == nil || !(d->qid.type & QTDIR))
  133. sysfatal("mountpoint must be an accessible directory");
  134. free(d);
  135. if(pipe(p) < 0)
  136. sysfatal("pipe failed");
  137. mfd[0] = p[0];
  138. mfd[1] = p[0];
  139. user = getuser();
  140. notify(notifyf);
  141. if(srvname != nil)
  142. post(srvname, p[1]);
  143. if(debug)
  144. fmtinstall('F', fcallfmt);
  145. switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
  146. case -1:
  147. sysfatal("fork: %r");
  148. case 0:
  149. close(p[1]);
  150. chdir(defmnt);
  151. io();
  152. break;
  153. default:
  154. close(p[0]); /* don't deadlock if child fails */
  155. if(mount(p[1], -1, defmnt, MREPL|MCREATE, "", 'M') < 0)
  156. sysfatal("mount failed: %r");
  157. }
  158. exits(0);
  159. }
  160. void
  161. post(char *srvname, int pfd)
  162. {
  163. char name[128];
  164. int fd;
  165. snprint(name, sizeof name, "#s/%s", srvname);
  166. fd = create(name, OWRITE, 0666);
  167. if(fd < 0)
  168. sysfatal("create of %s failed: %r", srvname);
  169. sprint(name, "%d", pfd);
  170. if(write(fd, name, strlen(name)) < 0)
  171. sysfatal("writing %s: %r", srvname);
  172. }
  173. char*
  174. rversion(Fid *fi)
  175. {
  176. Fid *f;
  177. for(f = fids; f; f = f->next)
  178. if(f->busy)
  179. rclunk(f);
  180. if(thdr.msize > sizeof mdata)
  181. rhdr.msize = sizeof mdata;
  182. else
  183. rhdr.msize = thdr.msize;
  184. messagesize = rhdr.msize;
  185. if(strncmp(thdr.version, "9P2000", 6) != 0)
  186. return Eversion;
  187. rhdr.version = "9P2000";
  188. return nil;
  189. }
  190. char*
  191. rauth(Fid *f)
  192. {
  193. return Enoauth;
  194. }
  195. char*
  196. rflush(Fid *f)
  197. {
  198. USED(f);
  199. return nil;
  200. }
  201. char*
  202. rattach(Fid *f)
  203. {
  204. /* no authentication! */
  205. f->busy = 1;
  206. if(thdr.uname[0])
  207. f->user = estrdup(thdr.uname);
  208. else
  209. f->user = "none";
  210. if(strcmp(user, "none") == 0)
  211. user = f->user;
  212. if(f->path)
  213. s_free(f->path);
  214. f->path = s_copy(".");
  215. fidqid(f, &rhdr.qid);
  216. f->attach = 1;
  217. return nil;
  218. }
  219. char*
  220. clone(Fid *f, Fid **nf)
  221. {
  222. if(f->fd >= 0)
  223. return Eisopen;
  224. *nf = newfid(thdr.newfid);
  225. (*nf)->busy = 1;
  226. if((*nf)->path)
  227. s_free((*nf)->path);
  228. (*nf)->path = s_clone(f->path);
  229. (*nf)->fd = -1;
  230. (*nf)->user = f->user;
  231. (*nf)->attach = 0;
  232. return nil;
  233. }
  234. char*
  235. rwalk(Fid *f)
  236. {
  237. char *name;
  238. Fid *nf;
  239. char *err;
  240. int i;
  241. String *npath;
  242. Dir *d;
  243. char *cp;
  244. Qid qid;
  245. err = nil;
  246. nf = nil;
  247. rhdr.nwqid = 0;
  248. if(rhdr.newfid != rhdr.fid){
  249. err = clone(f, &nf);
  250. if(err)
  251. return err;
  252. f = nf; /* walk the new fid */
  253. }
  254. readnames();
  255. npath = s_clone(f->path);
  256. if(thdr.nwname > 0){
  257. for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
  258. name = int32_t2short(thdr.wname[i], 0);
  259. if(strcmp(name, ".") == 0){
  260. ;
  261. } else if(strcmp(name, "..") == 0){
  262. cp = strrchr(s_to_c(npath), '/');
  263. if(cp != nil){
  264. *cp = 0;
  265. npath->ptr = cp;
  266. }
  267. } else {
  268. s_append(npath, "/");
  269. s_append(npath, name);
  270. }
  271. d = dirstat(s_to_c(npath));
  272. if(d == nil)
  273. break;
  274. rhdr.nwqid++;
  275. qid = d->qid;
  276. rhdr.wqid[i] = qid;
  277. free(d);
  278. }
  279. if(i==0 && err == nil)
  280. err = Enotexist;
  281. }
  282. /* if there was an error and we cloned, get rid of the new fid */
  283. if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
  284. f->busy = 0;
  285. s_free(npath);
  286. }
  287. /* update the fid after a successful walk */
  288. if(rhdr.nwqid == thdr.nwname){
  289. s_free(f->path);
  290. f->path = npath;
  291. }
  292. return err;
  293. }
  294. static char*
  295. passerror(void)
  296. {
  297. static char err[256];
  298. rerrstr(err, sizeof err);
  299. return err;
  300. }
  301. char*
  302. ropen(Fid *f)
  303. {
  304. if(readonly && (thdr.mode & 3))
  305. return Eperm;
  306. if(f->fd >= 0)
  307. return Eisopen;
  308. f->fd = open(s_to_c(f->path), thdr.mode);
  309. if(f->fd < 0)
  310. return passerror();
  311. fidqid(f, &rhdr.qid);
  312. f->qid = rhdr.qid;
  313. rhdr.iounit = messagesize-IOHDRSZ;
  314. return nil;
  315. }
  316. char*
  317. rcreate(Fid *f)
  318. {
  319. char *name;
  320. if(readonly)
  321. return Eperm;
  322. readnames();
  323. name = int32_t2short(thdr.name, 1);
  324. if(f->fd >= 0)
  325. return Eisopen;
  326. s_append(f->path, "/");
  327. s_append(f->path, name);
  328. f->fd = create(s_to_c(f->path), thdr.mode, thdr.perm);
  329. if(f->fd < 0)
  330. return passerror();
  331. fidqid(f, &rhdr.qid);
  332. f->qid = rhdr.qid;
  333. rhdr.iounit = messagesize-IOHDRSZ;
  334. return nil;
  335. }
  336. char*
  337. rreaddir(Fid *f)
  338. {
  339. int i;
  340. int n;
  341. /* reread the directory */
  342. if(thdr.offset == 0){
  343. if(f->dir)
  344. free(f->dir);
  345. f->dir = nil;
  346. if(f->diroff != 0)
  347. seek(f->fd, 0, 0);
  348. f->ndir = dirreadall(f->fd, &f->dir);
  349. f->diroff = 0;
  350. if(f->ndir < 0)
  351. return passerror();
  352. readnames();
  353. for(i = 0; i < f->ndir; i++)
  354. f->dir[i].name = short2int32_t(f->dir[i].name);
  355. }
  356. /* copy in as many directory entries as possible */
  357. for(n = 0; f->diroff < f->ndir; n += i){
  358. i = convD2M(&f->dir[f->diroff], rdata+n, thdr.count - n);
  359. if(i <= BIT16SZ)
  360. break;
  361. f->diroff++;
  362. }
  363. rhdr.data = (char*)rdata;
  364. rhdr.count = n;
  365. return nil;
  366. }
  367. char*
  368. rread(Fid *f)
  369. {
  370. int32_t n;
  371. if(f->fd < 0)
  372. return Enotexist;
  373. if(thdr.count > messagesize-IOHDRSZ)
  374. thdr.count = messagesize-IOHDRSZ;
  375. if(f->qid.type & QTDIR)
  376. return rreaddir(f);
  377. n = pread(f->fd, rdata, thdr.count, thdr.offset);
  378. if(n < 0)
  379. return passerror();
  380. rhdr.data = (char*)rdata;
  381. rhdr.count = n;
  382. return nil;
  383. }
  384. char*
  385. rwrite(Fid *f)
  386. {
  387. int32_t n;
  388. if(readonly || (f->qid.type & QTDIR))
  389. return Eperm;
  390. if(f->fd < 0)
  391. return Enotexist;
  392. if(thdr.count > messagesize-IOHDRSZ) /* shouldn't happen, anyway */
  393. thdr.count = messagesize-IOHDRSZ;
  394. n = pwrite(f->fd, thdr.data, thdr.count, thdr.offset);
  395. if(n < 0)
  396. return passerror();
  397. rhdr.count = n;
  398. return nil;
  399. }
  400. char*
  401. rclunk(Fid *f)
  402. {
  403. f->busy = 0;
  404. close(f->fd);
  405. f->fd = -1;
  406. f->path = s_reset(f->path);
  407. if(f->attach){
  408. free(f->user);
  409. f->user = nil;
  410. }
  411. f->attach = 0;
  412. if(f->dir != nil){
  413. free(f->dir);
  414. f->dir = nil;
  415. }
  416. f->diroff = f->ndir = 0;
  417. return nil;
  418. }
  419. char*
  420. rremove(Fid *f)
  421. {
  422. if(remove(s_to_c(f->path)) < 0)
  423. return passerror();
  424. return nil;
  425. }
  426. char*
  427. rstat(Fid *f)
  428. {
  429. int n;
  430. Dir *d;
  431. d = dirstat(s_to_c(f->path));
  432. if(d == nil)
  433. return passerror();
  434. d->name = short2int32_t(d->name);
  435. n = convD2M(d, statbuf, sizeof statbuf);
  436. free(d);
  437. if(n <= BIT16SZ)
  438. return passerror();
  439. rhdr.nstat = n;
  440. rhdr.stat = statbuf;
  441. return nil;
  442. }
  443. char*
  444. rwstat(Fid *f)
  445. {
  446. int n;
  447. Dir d;
  448. if(readonly)
  449. return Eperm;
  450. convM2D(thdr.stat, thdr.nstat, &d, (char*)rdata);
  451. d.name = int32_t2short(d.name, 1);
  452. n = dirwstat(s_to_c(f->path), &d);
  453. if(n < 0)
  454. return passerror();
  455. return nil;
  456. }
  457. Fid *
  458. newfid(int fid)
  459. {
  460. Fid *f, *ff;
  461. ff = 0;
  462. for(f = fids; f; f = f->next)
  463. if(f->fid == fid)
  464. return f;
  465. else if(!ff && !f->busy)
  466. ff = f;
  467. if(ff){
  468. ff->fid = fid;
  469. return ff;
  470. }
  471. f = emalloc(sizeof *f);
  472. f->path = s_reset(f->path);
  473. f->fd = -1;
  474. f->fid = fid;
  475. f->next = fids;
  476. fids = f;
  477. return f;
  478. }
  479. void
  480. io(void)
  481. {
  482. char *err;
  483. int n, pid;
  484. pid = getpid();
  485. for(;;){
  486. /*
  487. * reading from a pipe or a network device
  488. * will give an error after a few eof reads.
  489. * however, we cannot tell the difference
  490. * between a zero-length read and an interrupt
  491. * on the processes writing to us,
  492. * so we wait for the error.
  493. */
  494. n = read9pmsg(mfd[0], mdata, messagesize);
  495. if(n < 0)
  496. sysfatal("mount read");
  497. if(n == 0)
  498. continue;
  499. if(convM2S(mdata, n, &thdr) == 0)
  500. continue;
  501. if(debug)
  502. fprint(2, "%s %d:<-%F\n", argv0, pid, &thdr);
  503. if(!fcalls[thdr.type])
  504. err = "bad fcall type";
  505. else
  506. err = (*fcalls[thdr.type])(newfid(thdr.fid));
  507. if(err){
  508. rhdr.type = Rerror;
  509. rhdr.ename = err;
  510. }else{
  511. rhdr.type = thdr.type + 1;
  512. rhdr.fid = thdr.fid;
  513. }
  514. rhdr.tag = thdr.tag;
  515. if(debug)
  516. fprint(2, "%s %d:->%F\n", argv0, pid, &rhdr);/**/
  517. n = convS2M(&rhdr, mdata, messagesize);
  518. if(n == 0)
  519. sysfatal("convS2M error on write");
  520. if(write(mfd[1], mdata, n) != n)
  521. sysfatal("mount write");
  522. }
  523. }
  524. void *
  525. emalloc(uint32_t n)
  526. {
  527. void *p;
  528. p = malloc(n);
  529. if(!p)
  530. sysfatal("out of memory");
  531. memset(p, 0, n);
  532. return p;
  533. }
  534. void *
  535. erealloc(void *p, uint32_t n)
  536. {
  537. p = realloc(p, n);
  538. if(!p)
  539. sysfatal("out of memory");
  540. return p;
  541. }
  542. char *
  543. estrdup(char *q)
  544. {
  545. char *p;
  546. int n;
  547. n = strlen(q)+1;
  548. p = malloc(n);
  549. if(!p)
  550. sysfatal("out of memory");
  551. memmove(p, q, n);
  552. return p;
  553. }
  554. void
  555. fidqid(Fid *f, Qid *q)
  556. {
  557. Dir *d;
  558. d = dirstat(s_to_c(f->path));
  559. if(d == nil)
  560. *q = (Qid){0, 0, QTFILE};
  561. else {
  562. *q = d->qid;
  563. free(d);
  564. }
  565. }
  566. /*
  567. * table of name translations
  568. *
  569. * the file ./.longnames contains all the known long names.
  570. * the short name is the first NAMELEN-1 bytes of the base64
  571. * encoding of the MD5 hash of the longname.
  572. */
  573. typedef struct Name Name;
  574. struct Name
  575. {
  576. Name *next;
  577. char shortname[NAMELEN];
  578. char *longname;
  579. };
  580. Dir *dbstat; /* last stat of the name file */
  581. char *namefile = "./.longnames";
  582. char *namebuf;
  583. Name *names;
  584. Name*
  585. newname(char *longname, int writeflag)
  586. {
  587. Name *np;
  588. int n;
  589. uint8_t digest[MD5dlen];
  590. int fd;
  591. /* chain in new name */
  592. n = strlen(longname);
  593. np = emalloc(sizeof(*np)+n+1);
  594. np->longname = (char*)&np[1];
  595. strcpy(np->longname, longname);
  596. md5((uint8_t*)longname, n, digest, nil);
  597. enc32(np->shortname, sizeof(np->shortname), digest, MD5dlen);
  598. np->next = names;
  599. names = np;
  600. /* don't change namefile if we're read only */
  601. if(!writeflag)
  602. return np;
  603. /* add to namefile */
  604. fd = open(namefile, OWRITE);
  605. if(fd >= 0){
  606. seek(fd, 0, 2);
  607. fprint(fd, "%s\n", longname);
  608. close(fd);
  609. }
  610. return np;
  611. }
  612. void
  613. freenames(void)
  614. {
  615. Name *np, *next;
  616. for(np = names; np != nil; np = next){
  617. next = np->next;
  618. free(np);
  619. }
  620. names = nil;
  621. }
  622. /*
  623. * reread the file if the qid.path has changed.
  624. *
  625. * read any new entries if length has changed.
  626. */
  627. void
  628. readnames(void)
  629. {
  630. Dir *d;
  631. int fd;
  632. int64_t offset;
  633. Biobuf *b;
  634. char *p;
  635. d = dirstat(namefile);
  636. if(d == nil){
  637. if(readonly)
  638. return;
  639. /* create file if it doesn't exist */
  640. fd = create(namefile, OREAD, DMAPPEND|0666);
  641. if(fd < 0)
  642. return;
  643. if(dbstat != nil)
  644. free(dbstat);
  645. dbstat = nil;
  646. close(fd);
  647. return;
  648. }
  649. /* up to date? */
  650. offset = 0;
  651. if(dbstat != nil){
  652. if(d->qid.path == dbstat->qid.path){
  653. if(d->length <= dbstat->length){
  654. free(d);
  655. return;
  656. }
  657. offset = dbstat->length;
  658. } else {
  659. freenames();
  660. }
  661. free(dbstat);
  662. dbstat = nil;
  663. }
  664. /* read file */
  665. b = Bopen(namefile, OREAD);
  666. if(b == nil){
  667. free(d);
  668. return;
  669. }
  670. Bseek(b, offset, 0);
  671. while((p = Brdline(b, '\n')) != nil){
  672. p[Blinelen(b)-1] = 0;
  673. newname(p, 0);
  674. }
  675. Bterm(b);
  676. dbstat = d;
  677. }
  678. /*
  679. * look up a int32_t name, if it doesn't exist in the
  680. * file, add an entry to the file if the writeflag is
  681. * non-zero. Return a pointer to the short name.
  682. */
  683. char*
  684. int32_t2short(char *longname, int writeflag)
  685. {
  686. Name *np;
  687. if(strlen(longname) < NAMELEN-1 && strpbrk(longname, " ")==nil)
  688. return longname;
  689. for(np = names; np != nil; np = np->next)
  690. if(strcmp(longname, np->longname) == 0)
  691. return np->shortname;
  692. if(!writeflag)
  693. return longname;
  694. np = newname(longname, !readonly);
  695. return np->shortname;
  696. }
  697. /*
  698. * look up a short name, if it doesn't exist, return the
  699. * longname.
  700. */
  701. char*
  702. short2int32_t(char *shortname)
  703. {
  704. Name *np;
  705. for(np = names; np != nil; np = np->next)
  706. if(strcmp(shortname, np->shortname) == 0)
  707. return np->longname;
  708. return shortname;
  709. }