paqfs.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  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 <bio.h>
  14. #include <mp.h>
  15. #include <libsec.h>
  16. #include <flate.h>
  17. #include "paqfs.h"
  18. enum
  19. {
  20. OPERM = 0x3, /* mask of all permission types in open mode */
  21. OffsetSize = 4, /* size in bytes of an offset */
  22. };
  23. typedef struct Fid Fid;
  24. typedef struct Paq Paq;
  25. typedef struct Block Block;
  26. struct Fid
  27. {
  28. int16_t busy;
  29. int16_t open;
  30. int fid;
  31. char *user;
  32. uint32_t offset; /* for directory reading */
  33. Paq *paq;
  34. Fid *next;
  35. };
  36. struct Paq
  37. {
  38. int ref;
  39. Paq *up;
  40. PaqDir *dir;
  41. Qid qid;
  42. };
  43. struct Block
  44. {
  45. int ref;
  46. uint32_t addr; /* block byte address */
  47. uint32_t age;
  48. uint8_t *data;
  49. };
  50. enum
  51. {
  52. Pexec = 1,
  53. Pwrite = 2,
  54. Pread = 4,
  55. Pother = 1,
  56. Pgroup = 8,
  57. Powner = 64,
  58. };
  59. int noauth;
  60. Fid *fids;
  61. Fcall rhdr, thdr;
  62. int blocksize;
  63. int cachesize = 20;
  64. int mesgsize = 8*1024 + IOHDRSZ;
  65. Paq *root, *rootfile;
  66. Block *cache;
  67. uint32_t cacheage;
  68. Biobuf *bin;
  69. int qflag;
  70. Fid * newfid(int);
  71. void paqstat(PaqDir*, char*);
  72. void io(int fd);
  73. void *erealloc(void*, uint32_t);
  74. void *emalloc(uint32_t);
  75. void *emallocz(uint32_t n);
  76. char *estrdup(char*);
  77. void usage(void);
  78. uint32_t getl(uint8_t *p);
  79. int gets(uint8_t *p);
  80. char *getstr(uint8_t *p);
  81. PaqDir *getDir(uint8_t*);
  82. void getHeader(uint8_t *p, PaqHeader *b);
  83. void getBlock(uint8_t *p, PaqBlock *b);
  84. void getTrailer(uint8_t *p, PaqTrailer *b);
  85. void init(char*, int);
  86. void paqDirFree(PaqDir*);
  87. Qid paqDirQid(PaqDir *d);
  88. Paq *paqCpy(Paq *s);
  89. Paq *paqLookup(Paq *s, char *name);
  90. void paqFree(Paq*);
  91. Paq *paqWalk(Paq *s, char *name);
  92. int perm(PaqDir *s, char *user, int p);
  93. int dirRead(Fid*, uint8_t*, int);
  94. Block *blockLoad(uint32_t addr, int type);
  95. void blockFree(Block*);
  96. int checkDirSize(uint8_t *p, uint8_t *ep);
  97. int packDir(PaqDir*, uint8_t*, int);
  98. int blockRead(uint8_t *data, uint32_t addr, int type);
  99. void readHeader(PaqHeader *hdr, char *name, DigestState *ds);
  100. void readBlocks(char *name, DigestState *ds);
  101. void readTrailer(PaqTrailer *tlr, char *name, DigestState *ds);
  102. char *rflush(Fid*), *rversion(Fid*),
  103. *rauth(Fid*), *rattach(Fid*), *rwalk(Fid*),
  104. *ropen(Fid*), *rcreate(Fid*),
  105. *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
  106. *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
  107. char *(*fcalls[])(Fid*) = {
  108. [Tflush] rflush,
  109. [Tversion] rversion,
  110. [Tattach] rattach,
  111. [Tauth] rauth,
  112. [Twalk] rwalk,
  113. [Topen] ropen,
  114. [Tcreate] rcreate,
  115. [Tread] rread,
  116. [Twrite] rwrite,
  117. [Tclunk] rclunk,
  118. [Tremove] rremove,
  119. [Tstat] rstat,
  120. [Twstat] rwstat,
  121. };
  122. char Eperm[] = "permission denied";
  123. char Enotdir[] = "not a directory";
  124. char Enoauth[] = "authentication not required";
  125. char Enotexist[] = "file does not exist";
  126. char Einuse[] = "file in use";
  127. char Eexist[] = "file exists";
  128. char Enotowner[] = "not owner";
  129. char Eisopen[] = "file already open for I/O";
  130. char Excl[] = "exclusive use file already open";
  131. char Ename[] = "illegal name";
  132. char Erdonly[] = "read only file system";
  133. char Ebadblock[] = "bad block";
  134. char Eversion[] = "bad version of P9";
  135. char Edirtoobig[] = "directory entry too big";
  136. int debug;
  137. static int
  138. sha1fmt(Fmt *f)
  139. {
  140. int i;
  141. uint8_t *v;
  142. v = va_arg(f->args, uint8_t*);
  143. if(v == nil){
  144. fmtprint(f, "*");
  145. }
  146. else{
  147. for(i = 0; i < SHA1dlen; i++)
  148. fmtprint(f, "%2.2x", v[i]);
  149. }
  150. return 0;
  151. }
  152. void
  153. main(int argc, char *argv[])
  154. {
  155. int pfd[2];
  156. int fd, mnt, srv, stdio, verify;
  157. char buf[64], *mntpoint, *srvname, *p;
  158. fmtinstall('V', sha1fmt);
  159. mntpoint = "/n/paq";
  160. srvname = "paqfs";
  161. mnt = 1;
  162. srv = stdio = verify = 0;
  163. ARGBEGIN{
  164. default:
  165. usage();
  166. case 'a':
  167. noauth = 1;
  168. break;
  169. case 'c':
  170. p = EARGF(usage());
  171. cachesize = atoi(p);
  172. break;
  173. case 'd':
  174. debug = 1;
  175. break;
  176. case 'i':
  177. mnt = 0;
  178. stdio = 1;
  179. pfd[0] = 0;
  180. pfd[1] = 1;
  181. break;
  182. case 'm':
  183. mntpoint = EARGF(usage());
  184. break;
  185. case 'M':
  186. p = EARGF(usage());
  187. mesgsize = atoi(p);
  188. if(mesgsize < 512)
  189. mesgsize = 512;
  190. if(mesgsize > 128*1024)
  191. mesgsize = 128*1024;
  192. break;
  193. case 'p':
  194. srv = 1;
  195. mnt = 1;
  196. break;
  197. case 'q':
  198. qflag = 1;
  199. break;
  200. case 's':
  201. srv = 1;
  202. mnt = 0;
  203. break;
  204. case 'S':
  205. srvname = EARGF(usage());
  206. break;
  207. case 'v':
  208. verify = 1;
  209. break;
  210. }ARGEND
  211. if(argc != 1)
  212. usage();
  213. init(argv[0], verify);
  214. if(!stdio){
  215. if(pipe(pfd) < 0)
  216. sysfatal("pipe: %r");
  217. if(srv){
  218. snprint(buf, sizeof buf, "#s/%s", srvname);
  219. fd = create(buf, OWRITE, 0666);
  220. if(fd < 0)
  221. sysfatal("create %s: %r", buf);
  222. if(fprint(fd, "%d", pfd[0]) < 0)
  223. sysfatal("write %s: %r", buf);
  224. }
  225. }
  226. if(debug)
  227. fmtinstall('F', fcallfmt);
  228. switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
  229. case -1:
  230. sysfatal("fork");
  231. case 0:
  232. close(pfd[0]);
  233. io(pfd[1]);
  234. break;
  235. default:
  236. close(pfd[1]); /* don't deadlock if child fails */
  237. if(mnt && mount(pfd[0], -1, mntpoint, MREPL|MCREATE, "") < 0)
  238. sysfatal("mount %s: %r", mntpoint);
  239. }
  240. exits(0);
  241. }
  242. char*
  243. rversion(Fid*)
  244. {
  245. Fid *f;
  246. for(f = fids; f; f = f->next)
  247. if(f->busy)
  248. rclunk(f);
  249. if(rhdr.msize > mesgsize)
  250. thdr.msize = mesgsize;
  251. else
  252. thdr.msize = rhdr.msize;
  253. if(strcmp(rhdr.version, "9P2000") != 0)
  254. return Eversion;
  255. thdr.version = "9P2000";
  256. return 0;
  257. }
  258. char*
  259. rauth(Fid*)
  260. {
  261. return Enoauth;
  262. }
  263. char*
  264. rflush(Fid *f)
  265. {
  266. USED(f);
  267. return 0;
  268. }
  269. char*
  270. rattach(Fid *f)
  271. {
  272. /* no authentication! */
  273. f->busy = 1;
  274. f->paq = paqCpy(root);
  275. thdr.qid = f->paq->qid;
  276. if(rhdr.uname[0])
  277. f->user = estrdup(rhdr.uname);
  278. else
  279. f->user = "none";
  280. return 0;
  281. }
  282. char*
  283. clone(Fid *f, Fid **res)
  284. {
  285. Fid *nf;
  286. if(f->open)
  287. return Eisopen;
  288. if(f->busy == 0)
  289. return Enotexist;
  290. nf = newfid(rhdr.newfid);
  291. nf->busy = 1;
  292. nf->open = 0;
  293. nf->paq = paqCpy(f->paq);
  294. nf->user = strdup(f->user);
  295. *res = nf;
  296. return 0;
  297. }
  298. char*
  299. rwalk(Fid *f)
  300. {
  301. Paq *paq, *npaq;
  302. Fid *nf;
  303. int nqid, nwname;
  304. Qid qid;
  305. char *err;
  306. if(f->busy == 0)
  307. return Enotexist;
  308. nf = nil;
  309. if(rhdr.fid != rhdr.newfid){
  310. err = clone(f, &nf);
  311. if(err)
  312. return err;
  313. f = nf; /* walk the new fid */
  314. }
  315. nwname = rhdr.nwname;
  316. /* easy case */
  317. if(nwname == 0) {
  318. thdr.nwqid = 0;
  319. return 0;
  320. }
  321. paq = paqCpy(f->paq);
  322. qid = paq->qid;
  323. err = nil;
  324. for(nqid = 0; nqid < nwname; nqid++){
  325. if((qid.type & QTDIR) == 0){
  326. err = Enotdir;
  327. break;
  328. }
  329. if(!perm(paq->dir, f->user, Pexec)) {
  330. err = Eperm;
  331. break;
  332. }
  333. npaq = paqWalk(paq, rhdr.wname[nqid]);
  334. if(npaq == nil) {
  335. err = Enotexist;
  336. break;
  337. }
  338. paqFree(paq);
  339. paq = npaq;
  340. qid = paq->qid;
  341. thdr.wqid[nqid] = qid;
  342. }
  343. thdr.nwqid = nqid;
  344. if(nqid == nwname){
  345. /* success */
  346. paqFree(f->paq);
  347. f->paq = paq;
  348. return 0;
  349. }
  350. paqFree(paq);
  351. if(nf != nil)
  352. rclunk(nf);
  353. /* only error on the first element */
  354. if(nqid == 0)
  355. return err;
  356. return 0;
  357. }
  358. char *
  359. ropen(Fid *f)
  360. {
  361. int mode, trunc;
  362. if(f->open)
  363. return Eisopen;
  364. if(f->busy == 0)
  365. return Enotexist;
  366. mode = rhdr.mode;
  367. if(f->paq->qid.type & QTDIR){
  368. if(mode != OREAD)
  369. return Eperm;
  370. thdr.qid = f->paq->qid;
  371. return 0;
  372. }
  373. if(mode & ORCLOSE)
  374. return Erdonly;
  375. trunc = mode & OTRUNC;
  376. mode &= OPERM;
  377. if(mode==OWRITE || mode==ORDWR || trunc)
  378. return Erdonly;
  379. if(mode==OREAD)
  380. if(!perm(f->paq->dir, f->user, Pread))
  381. return Eperm;
  382. if(mode==OEXEC)
  383. if(!perm(f->paq->dir, f->user, Pexec))
  384. return Eperm;
  385. thdr.qid = f->paq->qid;
  386. f->open = 1;
  387. return 0;
  388. }
  389. char *
  390. rcreate(Fid *f)
  391. {
  392. if(f->open)
  393. return Eisopen;
  394. if(f->busy == 0)
  395. return Enotexist;
  396. return Erdonly;
  397. }
  398. char *
  399. readdir(Fid *f)
  400. {
  401. PaqDir *pd;
  402. uint8_t *p, *ep;
  403. uint32_t off;
  404. int n, cnt, i;
  405. uint8_t *buf;
  406. Block *ptr, *b;
  407. buf = (uint8_t*)thdr.data;
  408. cnt = rhdr.count;
  409. if(rhdr.offset == 0)
  410. f->offset = 0;
  411. off = f->offset;
  412. if(rootfile && f->paq == root){
  413. if(off != 0){
  414. rhdr.count = 0;
  415. return nil;
  416. }
  417. n = packDir(rootfile->dir, buf, cnt);
  418. rhdr.count = n;
  419. return nil;
  420. }
  421. ptr = blockLoad(f->paq->dir->offset, PointerBlock);
  422. if(ptr == nil)
  423. return Ebadblock;
  424. i = off/blocksize;
  425. off -= i*blocksize;
  426. thdr.count = 0;
  427. b = blockLoad(getl(ptr->data + i*4), DirBlock);
  428. while(b != nil) {
  429. p = b->data + off;
  430. ep = b->data + blocksize;
  431. if(checkDirSize(p, ep)) {
  432. pd = getDir(p);
  433. n = packDir(pd, buf, cnt);
  434. paqDirFree(pd);
  435. if(n == 0) {
  436. blockFree(b);
  437. if(thdr.count == 0) {
  438. blockFree(ptr);
  439. return Edirtoobig;
  440. }
  441. break;
  442. }
  443. off += gets(p);
  444. cnt -= n;
  445. buf += n;
  446. thdr.count += n;
  447. } else {
  448. off = 0;
  449. i++;
  450. blockFree(b);
  451. b = blockLoad(getl(ptr->data + i*4), DirBlock);
  452. }
  453. }
  454. f->offset = i*blocksize + off;
  455. blockFree(ptr);
  456. return 0;
  457. }
  458. char*
  459. rread(Fid *f)
  460. {
  461. PaqDir *pd;
  462. uint8_t *buf;
  463. int64_t off;
  464. uint32_t uoff;
  465. int n, cnt, i;
  466. Block *ptr, *b;
  467. if(f->busy == 0)
  468. return Enotexist;
  469. if(f->paq->qid.type & QTDIR)
  470. return readdir(f);
  471. pd = f->paq->dir;
  472. off = rhdr.offset;
  473. buf = (uint8_t*)thdr.data;
  474. cnt = rhdr.count;
  475. thdr.count = 0;
  476. if(off >= pd->length || cnt == 0)
  477. return 0;
  478. if(cnt > pd->length - off)
  479. cnt = pd->length - off;
  480. ptr = blockLoad(pd->offset, PointerBlock);
  481. if(ptr == nil)
  482. return Ebadblock;
  483. i = off/blocksize;
  484. uoff = off-i*blocksize;
  485. while(cnt > 0) {
  486. b = blockLoad(getl(ptr->data + i*4), DataBlock);
  487. if(b == nil) {
  488. blockFree(ptr);
  489. return Ebadblock;
  490. }
  491. n = blocksize - uoff;
  492. if(n > cnt)
  493. n = cnt;
  494. memmove(buf, b->data + uoff, n);
  495. cnt -= n;
  496. thdr.count += n;
  497. buf += n;
  498. uoff = 0;
  499. i++;
  500. blockFree(b);
  501. }
  502. blockFree(ptr);
  503. return 0;
  504. }
  505. char*
  506. rwrite(Fid *f)
  507. {
  508. if(f->busy == 0)
  509. return Enotexist;
  510. return Erdonly;
  511. }
  512. char *
  513. rclunk(Fid *f)
  514. {
  515. f->busy = 0;
  516. f->open = 0;
  517. free(f->user);
  518. paqFree(f->paq);
  519. return 0;
  520. }
  521. char *
  522. rremove(Fid *f)
  523. {
  524. rclunk(f);
  525. return Erdonly;
  526. }
  527. char *
  528. rstat(Fid *f)
  529. {
  530. if(f->busy == 0)
  531. return Enotexist;
  532. thdr.stat = (uint8_t*)thdr.data;
  533. thdr.nstat = packDir(f->paq->dir, thdr.stat, mesgsize);
  534. if(thdr.nstat == 0)
  535. return Edirtoobig;
  536. return 0;
  537. }
  538. char *
  539. rwstat(Fid *f)
  540. {
  541. if(f->busy == 0)
  542. return Enotexist;
  543. return Erdonly;
  544. }
  545. Paq*
  546. paqCpy(Paq *s)
  547. {
  548. s->ref++;
  549. return s;
  550. }
  551. void
  552. paqFree(Paq *p)
  553. {
  554. if(p == nil)
  555. return;
  556. p->ref--;
  557. if(p->ref > 0)
  558. return;
  559. assert(p != root);
  560. paqFree(p->up);
  561. paqDirFree(p->dir);
  562. free(p);
  563. }
  564. void
  565. paqDirFree(PaqDir *pd)
  566. {
  567. if(pd == nil)
  568. return;
  569. free(pd->name);
  570. free(pd->uid);
  571. free(pd->gid);
  572. free(pd);
  573. }
  574. Qid
  575. paqDirQid(PaqDir *d)
  576. {
  577. Qid q;
  578. q.path = d->qid;
  579. q.vers = 0;
  580. q.type = d->mode >> 24;
  581. return q;
  582. }
  583. int
  584. packDir(PaqDir *s, uint8_t *buf, int n)
  585. {
  586. Dir dir;
  587. memset(&dir, 0, sizeof(dir));
  588. dir.qid = paqDirQid(s);
  589. dir.mode = s->mode;
  590. dir.atime = s->mtime;
  591. dir.mtime = s->mtime;
  592. dir.length = s->length;
  593. dir.name = s->name;
  594. dir.uid = s->uid;
  595. dir.gid = s->gid;
  596. dir.muid = s->uid;
  597. n = convD2M(&dir, buf, n);
  598. if(n < STATFIXLEN)
  599. return 0;
  600. return n;
  601. }
  602. Block *
  603. blockLoad(uint32_t addr, int type)
  604. {
  605. uint32_t age;
  606. int i, j;
  607. Block *b;
  608. if(addr == 0)
  609. return nil;
  610. cacheage++;
  611. /* age has wraped */
  612. if(cacheage == 0) {
  613. for(i=0; i<cachesize; i++)
  614. cache[i].age = 0;
  615. }
  616. j = -1;
  617. age = ~0;
  618. for(i=0; i<cachesize; i++) {
  619. b = &cache[i];
  620. if(b->age < age && b->ref == 0) {
  621. age = b->age;
  622. j = i;
  623. }
  624. if(b->addr != addr)
  625. continue;
  626. b->age = cacheage;
  627. b->ref++;
  628. return b;
  629. }
  630. if(j < 0)
  631. sysfatal("no empty spots in cache!");
  632. b = &cache[j];
  633. assert(b->ref == 0);
  634. if(!blockRead(b->data, addr, type)) {
  635. b->addr = 0;
  636. b->age = 0;
  637. return nil;
  638. }
  639. b->age = cacheage;
  640. b->addr = addr;
  641. b->ref = 1;
  642. return b;
  643. }
  644. void
  645. blockFree(Block *b)
  646. {
  647. if(b == nil)
  648. return;
  649. if(--b->ref > 0)
  650. return;
  651. assert(b->ref == 0);
  652. }
  653. Paq*
  654. paqWalk(Paq *s, char *name)
  655. {
  656. Block *ptr, *b;
  657. uint8_t *p, *ep;
  658. PaqDir *pd;
  659. int i, n;
  660. Paq *ss;
  661. if(strcmp(name, "..") == 0)
  662. return paqCpy(s->up);
  663. if(rootfile && s == root){
  664. if(strcmp(name, rootfile->dir->name) == 0)
  665. return paqCpy(rootfile);
  666. return nil;
  667. }
  668. ptr = blockLoad(s->dir->offset, PointerBlock);
  669. if(ptr == nil)
  670. return nil;
  671. for(i=0; i<blocksize/4; i++) {
  672. b = blockLoad(getl(ptr->data+i*4), DirBlock);
  673. if(b == nil)
  674. break;
  675. p = b->data;
  676. ep = p + blocksize;
  677. while(checkDirSize(p, ep)) {
  678. n = gets(p);
  679. pd = getDir(p);
  680. if(strcmp(pd->name, name) == 0) {
  681. ss = emallocz(sizeof(Paq));
  682. ss->ref = 1;
  683. ss->up = paqCpy(s);
  684. ss->dir = pd;
  685. ss->qid = paqDirQid(pd);
  686. blockFree(b);
  687. blockFree(ptr);
  688. return ss;
  689. }
  690. paqDirFree(pd);
  691. p += n;
  692. }
  693. blockFree(b);
  694. }
  695. blockFree(ptr);
  696. return nil;
  697. }
  698. Fid *
  699. newfid(int fid)
  700. {
  701. Fid *f, *ff;
  702. ff = 0;
  703. for(f = fids; f; f = f->next)
  704. if(f->fid == fid)
  705. return f;
  706. else if(!ff && !f->busy)
  707. ff = f;
  708. if(ff){
  709. ff->fid = fid;
  710. return ff;
  711. }
  712. f = emallocz(sizeof *f);
  713. f->fid = fid;
  714. f->next = fids;
  715. fids = f;
  716. return f;
  717. }
  718. void
  719. io(int fd)
  720. {
  721. char *err;
  722. int n, pid;
  723. uint8_t *mdata;
  724. mdata = emalloc(mesgsize);
  725. pid = getpid();
  726. for(;;){
  727. n = read9pmsg(fd, mdata, mesgsize);
  728. if(n < 0)
  729. sysfatal("mount read");
  730. if(n == 0)
  731. break;
  732. if(convM2S(mdata, n, &rhdr) == 0)
  733. continue;
  734. if(debug)
  735. fprint(2, "paqfs %d:<-%F\n", pid, &rhdr);
  736. thdr.data = (char*)mdata + IOHDRSZ;
  737. if(!fcalls[rhdr.type])
  738. err = "bad fcall type";
  739. else
  740. err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
  741. if(err){
  742. thdr.type = Rerror;
  743. thdr.ename = err;
  744. }else{
  745. thdr.type = rhdr.type + 1;
  746. thdr.fid = rhdr.fid;
  747. }
  748. thdr.tag = rhdr.tag;
  749. if(debug)
  750. fprint(2, "paqfs %d:->%F\n", pid, &thdr);/**/
  751. n = convS2M(&thdr, mdata, mesgsize);
  752. if(n == 0)
  753. sysfatal("convS2M sysfatal on write");
  754. if(write(fd, mdata, n) != n)
  755. sysfatal("mount write");
  756. }
  757. }
  758. int
  759. perm(PaqDir *s, char *user, int p)
  760. {
  761. uint32_t perm = s->mode;
  762. if((p*Pother) & perm)
  763. return 1;
  764. if((noauth || strcmp(user, s->gid)==0) && ((p*Pgroup) & perm))
  765. return 1;
  766. if((noauth || strcmp(user, s->uid)==0) && ((p*Powner) & perm))
  767. return 1;
  768. return 0;
  769. }
  770. void
  771. init(char *file, int verify)
  772. {
  773. PaqHeader hdr;
  774. PaqTrailer tlr;
  775. Dir *dir;
  776. int i;
  777. uint8_t *p;
  778. DigestState *ds = nil;
  779. PaqDir *r;
  780. Block *b;
  781. uint32_t offset;
  782. inflateinit();
  783. bin = Bopen(file, OREAD);
  784. if(bin == nil)
  785. sysfatal("could not open file: %s: %r", file);
  786. if(verify)
  787. ds = sha1(0, 0, 0, 0);
  788. readHeader(&hdr, file, ds);
  789. blocksize = hdr.blocksize;
  790. if(verify) {
  791. readBlocks(file, ds);
  792. } else {
  793. dir = dirstat(file);
  794. if(dir == nil)
  795. sysfatal("could not stat file: %s: %r", file);
  796. offset = dir->length - TrailerSize;
  797. free(dir);
  798. if(Bseek(bin, offset, 0) != offset)
  799. sysfatal("could not seek to trailer: %s", file);
  800. }
  801. readTrailer(&tlr, file, ds);
  802. /* asctime includes a newline - yuk */
  803. if(!qflag){
  804. fprint(2, "%s: %s", hdr.label, asctime(gmtime(hdr.time)));
  805. fprint(2, "fingerprint: %V\n", tlr.sha1);
  806. }
  807. cache = emallocz(cachesize*sizeof(Block));
  808. p = emalloc(cachesize*blocksize);
  809. for(i=0; i<cachesize; i++) {
  810. cache[i].data = p;
  811. p += blocksize;
  812. }
  813. /* hand craft root */
  814. b = blockLoad(tlr.root, DirBlock);
  815. if(b == nil || !checkDirSize(b->data, b->data+blocksize))
  816. sysfatal("could not read root block: %s", file);
  817. r = getDir(b->data);
  818. blockFree(b);
  819. root = emallocz(sizeof(Paq));
  820. root->qid = paqDirQid(r);
  821. root->ref = 1;
  822. root->dir = r;
  823. root->up = root; /* parent of root is root */
  824. /* craft root directory if root is a normal file */
  825. if(!(root->qid.type&QTDIR)){
  826. rootfile = root;
  827. root = emallocz(sizeof(Paq));
  828. root->qid = rootfile->qid;
  829. root->qid.type |= QTDIR;
  830. root->qid.path++;
  831. root->ref = 1;
  832. root->dir = emallocz(sizeof(PaqDir));
  833. *root->dir = *r;
  834. root->dir->mode |= DMDIR|0111;
  835. root->up = root;
  836. }
  837. }
  838. int
  839. blockRead(uint8_t *data, uint32_t addr, int type)
  840. {
  841. uint8_t buf[BlockSize];
  842. PaqBlock b;
  843. uint8_t *cdat;
  844. if(Bseek(bin, addr, 0) != addr){
  845. fprint(2, "paqfs: seek %lu: %r\n", addr);
  846. return 0;
  847. }
  848. if(Bread(bin, buf, BlockSize) != BlockSize){
  849. fprint(2, "paqfs: read %d at %lu: %r\n", BlockSize, addr);
  850. return 0;
  851. }
  852. getBlock(buf, &b);
  853. if(b.magic != BlockMagic || b.size > blocksize || b.type != type){
  854. fprint(2, "paqfs: bad block: magic %.8lux (want %.8x) size %lu (max %d) type %u (want %u)\n",
  855. b.magic, BlockMagic, b.size, blocksize, b.type, type);
  856. return 0;
  857. }
  858. switch(b.encoding) {
  859. default:
  860. return 0;
  861. case NoEnc:
  862. if(Bread(bin, data, blocksize) < blocksize)
  863. return 0;
  864. break;
  865. case DeflateEnc:
  866. cdat = emalloc(b.size);
  867. if(Bread(bin, cdat, b.size) < b.size) {
  868. free(cdat);
  869. return 0;
  870. }
  871. if(inflateblock(data, blocksize, cdat, b.size) < 0) {
  872. fprint(2, "inflate error: %r\n");
  873. free(cdat);
  874. return 0;
  875. }
  876. free(cdat);
  877. break;
  878. }
  879. if(adler32(0, data, blocksize) != b.adler32)
  880. return 0;
  881. return 1;
  882. }
  883. void
  884. readHeader(PaqHeader *hdr, char *name, DigestState *ds)
  885. {
  886. uint8_t buf[HeaderSize];
  887. if(Bread(bin, buf, HeaderSize) < HeaderSize)
  888. sysfatal("could not read header: %s: %r", name);
  889. if(ds)
  890. sha1(buf, HeaderSize, 0, ds);
  891. getHeader(buf, hdr);
  892. if(hdr->magic != HeaderMagic)
  893. sysfatal("bad header magic 0x%lx: %s", hdr->magic, name);
  894. if(hdr->version != Version)
  895. sysfatal("unknown file version: %s", name);
  896. }
  897. void
  898. readBlocks(char *name, DigestState *ds)
  899. {
  900. uint8_t *buf;
  901. PaqBlock b;
  902. buf = emalloc(BlockSize+blocksize);
  903. for(;;) {
  904. if(Bread(bin, buf, 4) < 4)
  905. sysfatal("could not read block: %s: %r", name);
  906. Bseek(bin, -4, 1);
  907. /* check if it is a data block */
  908. if(getl(buf) != BlockMagic)
  909. break;
  910. if(Bread(bin, buf, BlockSize) < BlockSize)
  911. sysfatal("could not read block: %s: %r", name);
  912. if(ds)
  913. sha1(buf, BlockSize, 0, ds);
  914. getBlock(buf, &b);
  915. if(b.size > blocksize)
  916. sysfatal("bad block size: %lu: %s", b.size, name);
  917. if(ds) {
  918. if(Bread(bin, buf, b.size) < b.size)
  919. sysfatal("sysfatal reading block: %s: %r", name);
  920. sha1(buf, b.size, 0, ds);
  921. } else
  922. Bseek(bin, b.size, 1);
  923. }
  924. free(buf);
  925. }
  926. void
  927. readTrailer(PaqTrailer *tlr, char *name, DigestState *ds)
  928. {
  929. uint8_t buf[TrailerSize];
  930. uint8_t digest[SHA1dlen];
  931. if(Bread(bin, buf, TrailerSize) < TrailerSize)
  932. sysfatal("could not read trailer: %s: %r", name);
  933. getTrailer(buf, tlr);
  934. if(tlr->magic != TrailerMagic)
  935. sysfatal("bad trailer magic: %s", name);
  936. if(ds) {
  937. sha1(buf, TrailerSize-SHA1dlen, digest, ds);
  938. if(memcmp(digest, tlr->sha1, SHA1dlen) != 0)
  939. sysfatal("bad sha1 digest: %s", name);
  940. }
  941. }
  942. void *
  943. emalloc(uint32_t n)
  944. {
  945. void *p;
  946. p = malloc(n);
  947. if(!p)
  948. sysfatal("out of memory");
  949. return p;
  950. }
  951. void *
  952. emallocz(uint32_t n)
  953. {
  954. void *p;
  955. p = emalloc(n);
  956. memset(p, 0, n);
  957. return p;
  958. }
  959. void *
  960. erealloc(void *p, uint32_t n)
  961. {
  962. p = realloc(p, n);
  963. if(!p)
  964. sysfatal("out of memory");
  965. return p;
  966. }
  967. char *
  968. estrdup(char *s)
  969. {
  970. s = strdup(s);
  971. if(s == nil)
  972. sysfatal("out of memory");
  973. return s;
  974. }
  975. uint32_t
  976. getl(uint8_t *p)
  977. {
  978. return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
  979. }
  980. int
  981. gets(uint8_t *p)
  982. {
  983. return (p[0]<<8) | p[1];
  984. }
  985. int
  986. checkDirSize(uint8_t *p, uint8_t *ep)
  987. {
  988. int n;
  989. int i;
  990. if(ep-p < 2)
  991. return 0;
  992. n = gets(p);
  993. if(p+n > ep)
  994. return 0;
  995. ep = p+n;
  996. p += 22;
  997. for(i=0; i<3; i++) {
  998. if(p+2 > ep)
  999. return 0;
  1000. n = gets(p);
  1001. if(p+n > ep)
  1002. return 0;
  1003. p += n;
  1004. }
  1005. return 1;
  1006. }
  1007. void
  1008. getHeader(uint8_t *p, PaqHeader *h)
  1009. {
  1010. h->magic = getl(p);
  1011. h->version = gets(p+4);
  1012. h->blocksize = gets(p+6);
  1013. if((h->magic>>16) == BigHeaderMagic){
  1014. h->magic = HeaderMagic;
  1015. h->version = gets(p+2);
  1016. h->blocksize = getl(p+4);
  1017. }
  1018. h->time = getl(p+8);
  1019. memmove(h->label, p+12, sizeof(h->label));
  1020. h->label[sizeof(h->label)-1] = 0;
  1021. }
  1022. void
  1023. getTrailer(uint8_t *p, PaqTrailer *t)
  1024. {
  1025. t->magic = getl(p);
  1026. t->root = getl(p+4);
  1027. memmove(t->sha1, p+8, SHA1dlen);
  1028. }
  1029. void
  1030. getBlock(uint8_t *p, PaqBlock *b)
  1031. {
  1032. b->magic = getl(p);
  1033. b->size = gets(p+4);
  1034. if((b->magic>>16) == BigBlockMagic){
  1035. b->magic = BlockMagic;
  1036. b->size = getl(p+2);
  1037. }
  1038. b->type = p[6];
  1039. b->encoding = p[7];
  1040. b->adler32 = getl(p+8);
  1041. }
  1042. PaqDir *
  1043. getDir(uint8_t *p)
  1044. {
  1045. PaqDir *pd;
  1046. pd = emallocz(sizeof(PaqDir));
  1047. pd->qid = getl(p+2);
  1048. pd->mode = getl(p+6);
  1049. pd->mtime = getl(p+10);
  1050. pd->length = getl(p+14);
  1051. pd->offset = getl(p+18);
  1052. p += 22;
  1053. pd->name = getstr(p);
  1054. p += gets(p);
  1055. pd->uid = getstr(p);
  1056. p += gets(p);
  1057. pd->gid = getstr(p);
  1058. return pd;
  1059. }
  1060. char *
  1061. getstr(uint8_t *p)
  1062. {
  1063. char *s;
  1064. int n;
  1065. n = gets(p);
  1066. s = emalloc(n+1);
  1067. memmove(s, p+2, n);
  1068. s[n] = 0;
  1069. return s;
  1070. }
  1071. void
  1072. usage(void)
  1073. {
  1074. fprint(2, "usage: %s [-disv] [-c cachesize] [-m mountpoint] [-M mesgsize] paqfile\n", argv0);
  1075. exits("usage");
  1076. }