lnfs.c 13 KB

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