paqfs.c 20 KB

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