lnfs.c 14 KB

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