depend.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  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 <thread.h>
  14. #include <bio.h>
  15. typedef struct Args Args;
  16. struct Args {
  17. int argc;
  18. char **argv;
  19. };
  20. typedef struct Dfile Dfile;
  21. typedef struct Fid Fid;
  22. typedef struct File File;
  23. typedef struct Fs Fs;
  24. typedef struct Request Request;
  25. typedef struct Symbol Symbol;
  26. typedef struct Tardir Tardir;
  27. int threadrforkflag = RFNAMEG;
  28. enum{
  29. Nstat = 1024, /* plenty for this application */
  30. MAXSIZE = 8192+IOHDRSZ,
  31. };
  32. int messagesize = MAXSIZE;
  33. void
  34. fatal(char *fmt, ...)
  35. {
  36. va_list arg;
  37. char buf[1024];
  38. write(2, "depend: ", 8);
  39. va_start(arg, fmt);
  40. vseprint(buf, buf+1024, fmt, arg);
  41. va_end(arg);
  42. write(2, buf, strlen(buf));
  43. write(2, "\n", 1);
  44. threadexitsall(fmt);
  45. }
  46. enum
  47. {
  48. Nfidhash= 64,
  49. Ndfhash= 128,
  50. };
  51. struct Symbol
  52. {
  53. Symbol *next; /* hash list chaining */
  54. char *sym;
  55. int fno; /* file symbol is defined in */
  56. };
  57. /* source file */
  58. struct File
  59. {
  60. QLock QLock;
  61. char *name;
  62. Symbol *ref;
  63. unsigned char *refvec; /* files resolving the references */
  64. uint len; /* length of file */
  65. uint tarlen; /* length of tar file */
  66. uint mode;
  67. uint mtime;
  68. int use;
  69. int fd;
  70. };
  71. /* .depend file */
  72. struct Dfile
  73. {
  74. Lock Lock;
  75. int use; /* use count */
  76. int old; /* true if this is an superceded dfile */
  77. File *file; /* files */
  78. int nfile; /* number of files */
  79. int flen; /* length of file table */
  80. Symbol **dhash; /* hash table of symbols */
  81. int hlen; /* length of hash table */
  82. Dfile *next; /* hash chain */
  83. char *path; /* path name of dependency file */
  84. Qid qid; /* qid of the dependency file */
  85. };
  86. struct Fid
  87. {
  88. Fid *next;
  89. int fid;
  90. int ref;
  91. int attached;
  92. int open;
  93. Qid qid;
  94. char *path;
  95. Dfile *df;
  96. Symbol *dp;
  97. int fd;
  98. Dir *dir;
  99. int ndir;
  100. int dirindex;
  101. };
  102. struct Request
  103. {
  104. Request *next;
  105. Fid *fid;
  106. Fcall f;
  107. uint8_t buf[1];
  108. };
  109. enum
  110. {
  111. Tblocksize= 512, /* tar block size */
  112. Tnamesize= 100, /* tar name size */
  113. };
  114. struct Tardir
  115. {
  116. char name[Tnamesize];
  117. char mode[8];
  118. char uid[8];
  119. char gid[8];
  120. char size[12];
  121. char mtime[12];
  122. char chksum[8];
  123. char linkflag;
  124. char linkname[Tnamesize];
  125. };
  126. struct Fs
  127. {
  128. Lock Lock;
  129. int fd; /* to kernel mount point */
  130. Fid *hash[Nfidhash];
  131. char *root;
  132. Qid rootqid;
  133. };
  134. struct Fsarg
  135. {
  136. Fs *fs;
  137. int fd;
  138. char *root;
  139. };
  140. extern void fsrun(void*);
  141. extern Fid* fsgetfid(Fs*, int);
  142. extern void fsputfid(Fs*, Fid*);
  143. extern void fsreply(Fs*, Request*, char*);
  144. extern void fsversion(Fs*, Request*, Fid*);
  145. extern void fsauth(Fs*, Request*, Fid*);
  146. extern void fsflush(Fs*, Request*, Fid*);
  147. extern void fsattach(Fs*, Request*, Fid*);
  148. extern void fswalk(Fs*, Request*, Fid*);
  149. extern void fsopen(Fs*, Request*, Fid*);
  150. extern void fscreate(Fs*, Request*, Fid*);
  151. extern void fsread(Fs*, Request*, Fid*);
  152. extern void fswrite(Fs*, Request*, Fid*);
  153. extern void fsclunk(Fs*, Request*, Fid*);
  154. extern void fsremove(Fs*, Request*, Fid*);
  155. extern void fsstat(Fs*, Request*, Fid*);
  156. extern void fswstat(Fs*, Request*, Fid*);
  157. void (*fcall[])(Fs*, Request*, Fid*) =
  158. {
  159. [Tflush] = fsflush,
  160. [Tversion] = fsversion,
  161. [Tauth] = fsauth,
  162. [Tattach] = fsattach,
  163. [Twalk] = fswalk,
  164. [Topen] = fsopen,
  165. [Tcreate] = fscreate,
  166. [Tread] = fsread,
  167. [Twrite] = fswrite,
  168. [Tclunk] = fsclunk,
  169. [Tremove] = fsremove,
  170. [Tstat] = fsstat,
  171. [Twstat] = fswstat
  172. };
  173. char Eperm[] = "permission denied";
  174. char Eexist[] = "file does not exist";
  175. char Enotdir[] = "not a directory";
  176. char Eisopen[] = "file already open";
  177. char Enofid[] = "no such fid";
  178. char mallocerr[] = "malloc: %r";
  179. char Etoolong[] = "name too long";
  180. char *dependlog = "depend";
  181. int debug;
  182. Dfile *dfhash[Ndfhash]; /* dependency file hash */
  183. QLock dfhlock[Ndfhash];
  184. QLock iolock;
  185. Request* allocreq(int);
  186. Dfile* getdf(char*);
  187. void releasedf(Dfile*);
  188. Symbol* dfsearch(Dfile*, char*);
  189. void dfresolve(Dfile*, int);
  190. char* mkpath(char*, char*);
  191. int mktar(Dfile*, Symbol*, uint8_t*, uint, int);
  192. void closetar(Dfile*, Symbol*);
  193. void*
  194. emalloc(uint n)
  195. {
  196. void *p;
  197. p = malloc(n);
  198. if(p == nil)
  199. fatal(mallocerr);
  200. memset(p, 0, n);
  201. return p;
  202. }
  203. void *
  204. erealloc(void *ReallocP, int ReallocN)
  205. {
  206. if(ReallocN == 0)
  207. ReallocN = 1;
  208. if(!ReallocP)
  209. ReallocP = emalloc(ReallocN);
  210. else if(!(ReallocP = realloc(ReallocP, ReallocN)))
  211. fatal("unable to allocate %d bytes",ReallocN);
  212. return(ReallocP);
  213. }
  214. char*
  215. estrdup(char *s)
  216. {
  217. char *d, *d0;
  218. if(!s)
  219. return 0;
  220. d = d0 = emalloc(strlen(s)+1);
  221. while((*d++ = *s++) != 0)
  222. ;
  223. return d0;
  224. }
  225. /*
  226. * mount the user interface and start one request processor
  227. * per CPU
  228. */
  229. void
  230. realmain(void *a)
  231. {
  232. Fs *fs;
  233. int pfd[2];
  234. int srv;
  235. char service[128];
  236. struct Fsarg fsarg;
  237. Args *args;
  238. int argc;
  239. char **argv;
  240. args = a;
  241. argc = args->argc;
  242. argv = args->argv;
  243. fmtinstall('F', fcallfmt);
  244. ARGBEGIN{
  245. case 'd':
  246. debug++;
  247. break;
  248. }ARGEND
  249. if(argc != 2){
  250. fprint(2, "usage: %s [-d] svc-name directory\n", argv0);
  251. exits("usage");
  252. }
  253. snprint(service, sizeof service, "#s/%s", argv[0]);
  254. if(argv[1][0] != '/')
  255. fatal("directory must be rooted");
  256. if(pipe(pfd) < 0)
  257. fatal("opening pipe: %r");
  258. /* Typically mounted before /srv exists */
  259. srv = create(service, OWRITE, 0666);
  260. if(srv < 0)
  261. fatal("post: %r");
  262. fprint(srv, "%d", pfd[1]);
  263. close(srv);
  264. close(pfd[1]);
  265. time(nil); /* open fd for time before losing / */
  266. if(bind(argv[1], "/", MREPL) == 0)
  267. fatal("can't bind %s to /", argv[1]);
  268. fs = emalloc(sizeof(Fs));
  269. fsarg.fs = fs;
  270. fsarg.fd = pfd[0];
  271. fsarg.root = argv[1];
  272. proccreate(fsrun, &fsarg, 16*1024);
  273. proccreate(fsrun, &fsarg, 16*1024);
  274. fsrun(&fsarg);
  275. exits(nil);
  276. }
  277. void
  278. threadmain(int argc, char *argv[])
  279. {
  280. static Args args;
  281. args.argc = argc;
  282. args.argv = argv;
  283. rfork(RFNAMEG);
  284. proccreate(realmain, &args, 16*1024);
  285. }
  286. char*
  287. mkpath(char *dir, char *file)
  288. {
  289. int len;
  290. char *path;
  291. len = strlen(dir) + 1;
  292. if(file != nil)
  293. len += strlen(file) + 1;
  294. path = emalloc(len);
  295. if(file != nil)
  296. sprint(path, "%s/%s", dir, file);
  297. else
  298. sprint(path, "%s", dir);
  299. return path;
  300. }
  301. void
  302. fsrun(void *a)
  303. {
  304. struct Fsarg *fsarg;
  305. Fs* fs;
  306. char *root;
  307. int n, t;
  308. Request *r;
  309. Fid *f;
  310. Dir *d;
  311. fsarg = a;
  312. fs = fsarg->fs;
  313. fs->fd = fsarg->fd;
  314. root = fsarg->root;
  315. d = dirstat("/");
  316. if(d == nil)
  317. fatal("root %s inaccessible: %r", root);
  318. fs->rootqid = d->qid;
  319. free(d);
  320. for(;;){
  321. r = allocreq(messagesize);
  322. qlock(&iolock);
  323. n = read9pmsg(fs->fd, r->buf, messagesize);
  324. qunlock(&iolock);
  325. if(n <= 0)
  326. fatal("read9pmsg error: %r");
  327. if(convM2S(r->buf, n, &r->f) == 0){
  328. fprint(2, "can't convert %x %x %x\n", r->buf[0],
  329. r->buf[1], r->buf[2]);
  330. free(r);
  331. continue;
  332. }
  333. f = fsgetfid(fs, r->f.fid);
  334. r->fid = f;
  335. if(debug)
  336. fprint(2, "%F path %llux\n", &r->f, f->qid.path);
  337. t = r->f.type;
  338. r->f.type++;
  339. (*fcall[t])(fs, r, f);
  340. fsputfid(fs, f);
  341. }
  342. }
  343. /*
  344. * any request that can get queued for a delayed reply
  345. */
  346. Request*
  347. allocreq(int bufsize)
  348. {
  349. Request *r;
  350. r = emalloc(sizeof(Request)+bufsize);
  351. r->next = nil;
  352. return r;
  353. }
  354. Fid*
  355. fsgetfid(Fs *fs, int fid)
  356. {
  357. Fid *f, *nf;
  358. lock(&fs->Lock);
  359. for(f = fs->hash[fid%Nfidhash]; f; f = f->next){
  360. if(f->fid == fid){
  361. f->ref++;
  362. unlock(&fs->Lock);
  363. return f;
  364. }
  365. }
  366. nf = emalloc(sizeof(Fid));
  367. nf->next = fs->hash[fid%Nfidhash];
  368. fs->hash[fid%Nfidhash] = nf;
  369. nf->fid = fid;
  370. nf->ref = 1;
  371. nf->fd = -1;
  372. unlock(&fs->Lock);
  373. return nf;
  374. }
  375. void
  376. fsputfid(Fs *fs, Fid *f)
  377. {
  378. Fid **l, *nf;
  379. lock(&fs->Lock);
  380. if(--f->ref > 0){
  381. unlock(&fs->Lock);
  382. return;
  383. }
  384. for(l = &fs->hash[f->fid%Nfidhash]; (nf = *l) != nil; l = &nf->next)
  385. if(nf == f){
  386. *l = f->next;
  387. break;
  388. }
  389. unlock(&fs->Lock);
  390. free(f);
  391. }
  392. void
  393. fsreply(Fs *fs, Request *r, char *err)
  394. {
  395. int n;
  396. uint8_t buf[MAXSIZE];
  397. if(err){
  398. r->f.type = Rerror;
  399. r->f.ename = err;
  400. }
  401. if(debug)
  402. fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path);
  403. n = convS2M(&r->f, buf, messagesize);
  404. if(n == 0)
  405. fatal("bad convS2M");
  406. if(write(fs->fd, buf, n) != n)
  407. fatal("unmounted");
  408. free(r);
  409. }
  410. void
  411. fsversion(Fs *fs, Request *r, Fid *fi)
  412. {
  413. if(r->f.msize < 256){
  414. fsreply(fs, r, "version: bad message size");
  415. return;
  416. }
  417. if(messagesize > r->f.msize)
  418. messagesize = r->f.msize;
  419. r->f.msize = messagesize;
  420. r->f.version = "9P2000";
  421. fsreply(fs, r, nil);
  422. }
  423. void
  424. fsauth(Fs *fs, Request *r, Fid *fi)
  425. {
  426. fsreply(fs, r, "depend: authentication not required");
  427. }
  428. void
  429. fsflush(Fs *fs, Request *r, Fid *fi)
  430. {
  431. }
  432. void
  433. fsattach(Fs *fs, Request *r, Fid *f)
  434. {
  435. f->qid = fs->rootqid;
  436. f->path = strdup("/");
  437. f->df = getdf(mkpath(f->path, ".depend"));
  438. /* hold down the fid till the clunk */
  439. f->attached = 1;
  440. lock(&fs->Lock);
  441. f->ref++;
  442. unlock(&fs->Lock);
  443. r->f.qid = f->qid;
  444. fsreply(fs, r, nil);
  445. }
  446. void
  447. fswalk(Fs *fs, Request *r, Fid *f)
  448. {
  449. Fid *nf;
  450. char *name, *tmp;
  451. int i, nqid, nwname;
  452. char errbuf[ERRMAX], *err;
  453. Qid qid[MAXWELEM];
  454. Dfile *lastdf;
  455. char *path, *npath;
  456. Dir *d;
  457. Symbol *dp;
  458. if(f->attached == 0){
  459. fsreply(fs, r, Eexist);
  460. return;
  461. }
  462. if(f->fd >= 0 || f->open)
  463. fatal("walk of an open file");
  464. nf = nil;
  465. if(r->f.newfid != r->f.fid){
  466. nf = fsgetfid(fs, r->f.newfid);
  467. nf->attached = 1;
  468. nf->open = f->open;
  469. nf->path = strdup(f->path);
  470. nf->qid = f->qid;
  471. nf->dp = f->dp;
  472. nf->fd = f->fd;
  473. nf->df = f->df;
  474. if(nf->df){
  475. lock(&nf->df->Lock);
  476. nf->df->use++;
  477. unlock(&nf->df->Lock);
  478. }
  479. if(r->f.nwname == 0){
  480. r->f.nwqid = 0;
  481. fsreply(fs, r, nil);
  482. return;
  483. }
  484. f = nf;
  485. }
  486. err = nil;
  487. path = strdup(f->path);
  488. if(path == nil)
  489. fatal(mallocerr);
  490. nqid = 0;
  491. nwname = r->f.nwname;
  492. lastdf = f->df;
  493. if(nwname > 0){
  494. for(; nqid<nwname; nqid++){
  495. name = r->f.wname[nqid];
  496. if(strcmp(name, ".") == 0){
  497. Noop:
  498. if(nqid == 0)
  499. qid[nqid] = f->qid;
  500. else
  501. qid[nqid] = qid[nqid-1];
  502. continue;
  503. }
  504. if(strcmp(name, "..") == 0){
  505. name = strrchr(path, '/');
  506. if(name){
  507. if(name == path) /* at root */
  508. goto Noop;
  509. *name = '\0';
  510. }
  511. d = dirstat(path);
  512. if(d == nil){
  513. *name = '/';
  514. errstr(errbuf, sizeof errbuf);
  515. err = errbuf;
  516. break;
  517. }
  518. Directory:
  519. qid[nqid] = d->qid;
  520. free(d);
  521. releasedf(lastdf);
  522. lastdf = getdf(mkpath(path, ".depend"));
  523. continue;
  524. }
  525. npath = mkpath(path, name);
  526. free(path);
  527. path = npath;
  528. d = dirstat(path);
  529. if(d !=nil && (d->qid.type & QTDIR))
  530. goto Directory;
  531. free(d);
  532. qid[nqid].type = QTFILE;
  533. qid[nqid].path = 0;
  534. qid[nqid].vers = 0;
  535. dp = dfsearch(lastdf, name);
  536. if(dp == nil){
  537. tmp = strdup(name);
  538. if(tmp == nil)
  539. fatal("mallocerr");
  540. i = strlen(tmp);
  541. if(i > 4 && strcmp(&tmp[i-4], ".tar") == 0){
  542. tmp[i-4] = 0;
  543. dp = dfsearch(lastdf, tmp);
  544. }
  545. free(tmp);
  546. }
  547. if(dp == nil){
  548. err = Eexist;
  549. break;
  550. }
  551. qid[nqid].path = (uint64_t)dp;
  552. qid[nqid].vers = 0;
  553. }
  554. if(nqid == 0 && err == nil)
  555. err = "file does not exist";
  556. }
  557. /* for error or partial success, put the cloned fid back*/
  558. if(nf!=nil && (err != nil || nqid < nwname)){
  559. releasedf(nf->df);
  560. nf->df = nil;
  561. fsputfid(fs, nf);
  562. }
  563. if(err == nil){
  564. /* return (possibly short) list of qids */
  565. for(i=0; i<nqid; i++)
  566. r->f.wqid[i] = qid[i];
  567. r->f.nwqid = nqid;
  568. /* for full success, advance f */
  569. if(nqid > 0 && nqid == nwname){
  570. free(f->path);
  571. f->path = path;
  572. path = nil;
  573. f->qid = qid[nqid-1];
  574. f->dp = (Symbol*)f->qid.path;
  575. if(f->df != lastdf){
  576. releasedf(f->df);
  577. f->df = lastdf;
  578. lastdf = nil;
  579. }
  580. }
  581. }
  582. releasedf(lastdf);
  583. free(path);
  584. fsreply(fs, r, err);
  585. }
  586. #ifdef adf
  587. void
  588. fsclone(Fs *fs, Request *r, Fid *f)
  589. {
  590. Fid *nf;
  591. if(f->attached == 0){
  592. fsreply(fs, r, Eexist);
  593. return;
  594. }
  595. nf = fsgetfid(fs, r->f.newfid);
  596. nf->attached = 1;
  597. nf->open = f->open;
  598. nf->path = strdup(f->path);
  599. nf->qid = f->qid;
  600. nf->dp = f->dp;
  601. nf->fd = f->fd;
  602. nf->df = f->df;
  603. if(nf->df){
  604. lock(&nf->df->Lock);
  605. nf->df->use++;
  606. unlock(&nf->df->Lock);
  607. }
  608. fsreply(fs, r, nil);
  609. }
  610. void
  611. fswalk(Fs *fs, Request *r, Fid *f)
  612. {
  613. char *name;
  614. int i;
  615. Dir d;
  616. char errbuf[ERRLEN];
  617. char *path;
  618. Symbol *dp;
  619. if(f->attached == 0){
  620. fsreply(fs, r, Enofid);
  621. return;
  622. }
  623. if(f->fd >= 0 || f->open)
  624. fatal("walk of an open file");
  625. name = r->f.name;
  626. if(strcmp(name, ".") == 0){
  627. fsreply(fs, r, nil);
  628. return;
  629. }
  630. if(strcmp(name, "..") == 0){
  631. name = strrchr(f->path, '/');
  632. if(name){
  633. if(name == f->path){
  634. fsreply(fs, r, nil);
  635. return;
  636. }
  637. *name = 0;
  638. }
  639. if(dirstat(f->path, &d) < 0){
  640. *name = '/';
  641. errstr(errbuf);
  642. fsreply(fs, r, errbuf);
  643. return;
  644. }
  645. r->f.qid = f->qid = d.qid;
  646. releasedf(f->df);
  647. f->df = getdf(mkpath(f->path, ".depend"));
  648. fsreply(fs, r, nil);
  649. return;
  650. }
  651. path = mkpath(f->path, name);
  652. if(dirstat(path, &d) < 0 || (d.qid.path & CHDIR) == 0){
  653. dp = dfsearch(f->df, name);
  654. if(dp == nil){
  655. i = strlen(name);
  656. if(i > 4 && strcmp(&name[i-4], ".tar") == 0){
  657. name[i-4] = 0;
  658. dp = dfsearch(f->df, name);
  659. }
  660. }
  661. if(dp == nil){
  662. fsreply(fs, r, Eexist);
  663. free(path);
  664. return;
  665. }
  666. f->dp = dp;
  667. d.qid.path = (uint)dp;
  668. d.qid.vers = 0;
  669. }
  670. free(f->path);
  671. f->path = path;
  672. if(d.qid.path & CHDIR){
  673. releasedf(f->df);
  674. f->df = getdf(mkpath(f->path, ".depend"));
  675. }
  676. r->f.qid = f->qid = d.qid;
  677. fsreply(fs, r, nil);
  678. }
  679. #endif
  680. void
  681. fsopen(Fs *fs, Request *r, Fid *f)
  682. {
  683. int mode;
  684. char errbuf[ERRMAX];
  685. if(f->attached == 0){
  686. fsreply(fs, r, Enofid);
  687. return;
  688. }
  689. if(f->open){
  690. fsreply(fs, r, Eisopen);
  691. return;
  692. }
  693. mode = r->f.mode & 3;
  694. if(mode != OREAD){
  695. fsreply(fs, r, Eperm);
  696. return;
  697. }
  698. if(f->qid.type & QTDIR){
  699. f->fd = open(f->path, OREAD);
  700. if(f->fd < 0){
  701. errstr(errbuf, sizeof errbuf);
  702. fsreply(fs, r, errbuf);
  703. return;
  704. }
  705. }
  706. f->open = 1;
  707. r->f.qid = f->qid;
  708. fsreply(fs, r, nil);
  709. }
  710. void
  711. fscreate(Fs *fs, Request *r, Fid *f)
  712. {
  713. fsreply(fs, r, Eperm);
  714. }
  715. void
  716. fsread(Fs *fs, Request *r, Fid *f)
  717. {
  718. int i, n, len,skip;
  719. Dir d;
  720. Symbol *dp;
  721. char buf[512];
  722. if(f->attached == 0){
  723. fsreply(fs, r, Enofid);
  724. return;
  725. }
  726. if((int)r->f.count < 0){
  727. fsreply(fs, r, "bad read count");
  728. return;
  729. }
  730. if(f->qid.type & QTDIR){
  731. n = 0;
  732. if(f->dir == nil){
  733. f->ndir = dirreadall(f->fd, &f->dir);
  734. f->dirindex = 0;
  735. }
  736. if(f->dir == nil)
  737. goto Return;
  738. if(r->f.offset == 0) /* seeking to zero is permitted */
  739. f->dirindex = 0;
  740. for(; f->dirindex < f->ndir; f->dirindex++){
  741. if((f->dir[f->dirindex].qid.type & QTDIR) == 0)
  742. continue;
  743. len = convD2M(&f->dir[f->dirindex], r->buf+n, r->f.count-n);
  744. if(len <= BIT16SZ)
  745. goto Return;
  746. n += len;
  747. }
  748. skip = f->dirindex - f->ndir; /* # depend records already read */
  749. if(f->df){
  750. for(i = 0; i < f->df->hlen; i++)
  751. for(dp = f->df->dhash[i]; dp; dp = dp->next){
  752. if(skip-- > 0)
  753. continue;
  754. snprint(buf, sizeof buf, "%s.tar", dp->sym);
  755. d.name = buf;
  756. d.uid = "none";
  757. d.gid = "none";
  758. d.muid = "none";
  759. d.qid.type = QTFILE;
  760. d.qid.path = (uint64_t)dp;
  761. d.qid.vers = 0;
  762. d.length = f->df->file[dp->fno].tarlen;
  763. d.mode = 0444;
  764. d.mtime = time(nil);
  765. d.atime = time(nil);
  766. len = convD2M(&d, r->buf + n, r->f.count - n);
  767. if(len <= BIT16SZ)
  768. goto Return;
  769. n += len;
  770. f->dirindex++;
  771. }
  772. }
  773. } else
  774. n = mktar(f->df, f->dp, r->buf, r->f.offset, r->f.count);
  775. Return:
  776. r->f.data = (char*)r->buf;
  777. r->f.count = n;
  778. fsreply(fs, r, nil);
  779. }
  780. void
  781. fswrite(Fs *fs, Request *r, Fid *v)
  782. {
  783. fsreply(fs, r, Eperm);
  784. }
  785. void
  786. fsclunk(Fs *fs, Request *r, Fid *f)
  787. {
  788. if(f->attached == 0){
  789. fsreply(fs, r, Enofid);
  790. return;
  791. }
  792. if(f->fd >= 0){
  793. close(f->fd);
  794. f->fd = -1;
  795. }
  796. if((f->qid.type & QTDIR) == 0)
  797. closetar(f->df, f->dp);
  798. releasedf(f->df);
  799. f->df = nil;
  800. free(f->dir);
  801. f->dir = nil;
  802. fsreply(fs, r, nil);
  803. fsputfid(fs, f);
  804. }
  805. void
  806. fsremove(Fs *fs, Request *r, Fid *v)
  807. {
  808. fsreply(fs, r, Eperm);
  809. }
  810. void
  811. fsstat(Fs *fs, Request *r, Fid *f)
  812. {
  813. char err[ERRMAX];
  814. Dir d;
  815. Symbol *dp;
  816. int n;
  817. uint8_t statbuf[Nstat];
  818. if(f->qid.type & QTDIR)
  819. n = stat(f->path, statbuf, sizeof statbuf);
  820. else {
  821. dp = f->dp;
  822. d.name = dp->sym;
  823. d.uid = "none";
  824. d.gid = "none";
  825. d.muid = "none";
  826. d.qid.type = QTFILE;
  827. d.qid.path = (uint64_t)dp;
  828. d.qid.vers = 0;
  829. d.length = f->df->file[dp->fno].tarlen;
  830. d.mode = 0444;
  831. d.mtime = time(nil);
  832. d.atime = time(nil);
  833. n = convD2M(&d, statbuf, sizeof statbuf);
  834. }
  835. if(n <= BIT16SZ){
  836. errstr(err, sizeof err);
  837. fsreply(fs, r, err);
  838. } else {
  839. r->f.stat = statbuf;
  840. r->f.nstat = n;
  841. fsreply(fs, r, nil);
  842. }
  843. }
  844. void
  845. fswstat(Fs *fs, Request *r, Fid *f)
  846. {
  847. fsreply(fs, r, Eperm);
  848. }
  849. /*
  850. * string hash
  851. */
  852. uint
  853. shash(char *str, int len)
  854. {
  855. uint hash;
  856. char *val;
  857. hash = 0;
  858. for(val = str; *val; val++)
  859. hash = (hash*13) + *val-'a';
  860. return hash % len;
  861. }
  862. /*
  863. * free info about a dependency file
  864. */
  865. void
  866. freedf(Dfile *df)
  867. {
  868. int i;
  869. Symbol *dp, *next;
  870. lock(&df->Lock);
  871. df->old = 1;
  872. if(df->use){
  873. unlock(&df->Lock);
  874. return;
  875. }
  876. unlock(&df->Lock); /* we're no longer referenced */
  877. for(i = 0; i < df->nfile; i++)
  878. free(df->file[i].name);
  879. free(df->file[i].refvec);
  880. free(df->file);
  881. df->file = nil;
  882. for(i = 0; i < df->hlen; i++)
  883. for(dp = df->dhash[i]; dp != nil; dp = next){
  884. next = dp->next;
  885. free(dp);
  886. }
  887. free(df->path);
  888. free(df);
  889. free(df->dhash);
  890. df->dhash = nil;
  891. }
  892. /*
  893. * crack a dependency file
  894. */
  895. void
  896. newsym(char *name, int fno, Symbol **l)
  897. {
  898. Symbol *dp;
  899. dp = emalloc(sizeof(Symbol));
  900. dp->sym = strdup(name);
  901. if(dp->sym == nil)
  902. fatal("mallocerr");
  903. dp->next = *l;
  904. dp->fno = fno;
  905. *l = dp;
  906. }
  907. int
  908. awk(Biobuf *b, char **field, int n)
  909. {
  910. char *line;
  911. int i;
  912. while((line = Brdline(b, '\n')) != nil){
  913. line[Blinelen(b)-1] = 0;
  914. while(*line == ' ' || *line == '\t')
  915. *line++ = 0;
  916. for(i = 0; i < n; i++){
  917. if(*line == 0 || *line == '#')
  918. break;
  919. field[i] = line;
  920. while(*line && *line != ' ' && *line != '\t')
  921. line++;
  922. while(*line == ' ' || *line == '\t')
  923. *line++ = 0;
  924. }
  925. if(i)
  926. return i;
  927. }
  928. return 0;
  929. }
  930. void
  931. crackdf(Dfile *df, Biobuf *b, uint len, char *dpath)
  932. {
  933. char *name;
  934. char *field[3];
  935. char path[512];
  936. int n, inc, ok, npath;
  937. Symbol **l, *dp, *next;
  938. File *f, *ef;
  939. Dir *d;
  940. inc = 32;
  941. df->flen = inc;
  942. df->file = emalloc(df->flen*sizeof(File));
  943. df->nfile = 0;
  944. df->hlen = 1 + len/8;
  945. df->dhash = emalloc(df->hlen*sizeof(Symbol*));
  946. l = nil;
  947. while((n = awk(b, field, 3)) > 0){
  948. if(n != 2)
  949. continue;
  950. name = field[1];
  951. switch(*field[0]){
  952. case 'F':
  953. if(df->flen == df->nfile){
  954. df->flen += inc;
  955. df->file = realloc(df->file, df->flen*sizeof(File));
  956. if(df->file == nil)
  957. fatal(mallocerr);
  958. memset(&df->file[df->nfile], 0, inc*sizeof(File));
  959. }
  960. f = &df->file[df->nfile++];
  961. f->name = strdup(name);
  962. l = &f->ref;
  963. /* fall through and define as a symbol */
  964. case 'D':
  965. if(l == nil)
  966. continue;
  967. newsym(name, df->nfile-1, &(df->dhash[shash(name, df->hlen)]));
  968. break;
  969. case 'R':
  970. if(l == nil)
  971. continue;
  972. newsym(name, 0, l);
  973. break;
  974. }
  975. }
  976. ef = &df->file[df->nfile];
  977. /* stat the files to get sizes */
  978. npath = strlen(dpath);
  979. if(npath+1+1 >= sizeof path)
  980. fatal(Etoolong);
  981. memmove(path, dpath, npath+1); /* include NUL */
  982. name = strrchr(path, '/') + 1;
  983. for(f = df->file; f < ef; f++){
  984. n = strlen(f->name);
  985. if(npath+1+n+3+1 > sizeof path)
  986. fatal(Etoolong);
  987. memmove(name, f->name, n+1); /* include NUL */
  988. ok = access(path, AEXIST);
  989. if(ok < 0){
  990. strcpy(name+n, ".Z");
  991. ok = access(path, AEXIST);
  992. if(ok < 0){
  993. strcpy(name+n, ".gz");
  994. ok = access(path, AEXIST);
  995. }
  996. }
  997. if(ok >= 0){
  998. free(f->name);
  999. f->name = strdup(name);
  1000. if(f->name == nil)
  1001. fatal(mallocerr);
  1002. }
  1003. d = dirstat(path);
  1004. if(d){
  1005. f->len = d->length;
  1006. f->mode = d->mode;
  1007. f->mtime = d->mtime;
  1008. free(d);
  1009. }else{
  1010. f->len = 0;
  1011. f->mode = 0;
  1012. f->mtime = 0;
  1013. }
  1014. f->fd = -1;
  1015. }
  1016. /* resolve all file references */
  1017. for(f = df->file; f < ef; f++)
  1018. dfresolve(df, f-df->file);
  1019. /* free the referenced symbols, don't need them anymore */
  1020. for(f = df->file; f < ef; f++){
  1021. f->tarlen += 2*Tblocksize; /* tars trailing 0 blocks */
  1022. for(dp = f->ref; dp != nil; dp = next){
  1023. next = dp->next;
  1024. free(dp);
  1025. }
  1026. f->ref = nil;
  1027. }
  1028. }
  1029. /*
  1030. * get a cracked dependency file
  1031. */
  1032. Dfile*
  1033. getdf(char *path)
  1034. {
  1035. Dfile *df, **l;
  1036. QLock *lk;
  1037. Dir *d;
  1038. int i, fd;
  1039. Biobuf *b;
  1040. i = shash(path, Ndfhash);
  1041. l = &dfhash[i];
  1042. lk = &dfhlock[i];
  1043. qlock(lk);
  1044. for(df = *l; df; df = *l){
  1045. if(strcmp(path, df->path) == 0)
  1046. break;
  1047. l = &df->next;
  1048. }
  1049. d = dirstat(path);
  1050. if(df){
  1051. if(d!=nil && d->qid.type == df->qid.type && d->qid.vers == df->qid.vers && d->qid.vers == df->qid.vers){
  1052. free(path);
  1053. lock(&df->Lock);
  1054. df->use++;
  1055. unlock(&df->Lock);
  1056. goto Return;
  1057. }
  1058. *l = df->next;
  1059. freedf(df);
  1060. }
  1061. fd = open(path, OREAD);
  1062. if(d == nil || fd < 0){
  1063. close(fd);
  1064. goto Return;
  1065. }
  1066. df = emalloc(sizeof(*df));
  1067. b = emalloc(sizeof(Biobuf));
  1068. Binit(b, fd, OREAD);
  1069. df->qid = d->qid;
  1070. df->path = path;
  1071. crackdf(df, b, d->length, path);
  1072. Bterm(b);
  1073. free(b);
  1074. df->next = *l;
  1075. *l = df;
  1076. df->use = 1;
  1077. Return:
  1078. qunlock(lk);
  1079. free(d);
  1080. return df;
  1081. }
  1082. /*
  1083. * stop using a dependency file. Free it if it is no longer linked in.
  1084. */
  1085. void
  1086. releasedf(Dfile *df)
  1087. {
  1088. Dfile **l, *d;
  1089. QLock *lk;
  1090. int i;
  1091. if(df == nil)
  1092. return;
  1093. /* remove from hash chain */
  1094. i = shash(df->path, Ndfhash);
  1095. l = &dfhash[i];
  1096. lk = &dfhlock[i];
  1097. qlock(lk);
  1098. lock(&df->Lock);
  1099. df->use--;
  1100. if(df->old == 0 || df->use > 0){
  1101. unlock(&df->Lock);
  1102. qunlock(lk);
  1103. return;
  1104. }
  1105. for(d = *l; d; d = *l){
  1106. if(d == df){
  1107. *l = d->next;
  1108. break;
  1109. }
  1110. l = &d->next;
  1111. }
  1112. unlock(&df->Lock);
  1113. qunlock(lk);
  1114. /* now we know it is unreferenced, remove it */
  1115. freedf(df);
  1116. }
  1117. /*
  1118. * search a dependency file for a symbol
  1119. */
  1120. Symbol*
  1121. dfsearch(Dfile *df, char *name)
  1122. {
  1123. Symbol *dp;
  1124. if(df == nil)
  1125. return nil;
  1126. for(dp = df->dhash[shash(name, df->hlen)]; dp; dp = dp->next)
  1127. if(strcmp(dp->sym, name) == 0)
  1128. return dp;
  1129. return nil;
  1130. }
  1131. /*
  1132. * resolve a single file into a vector of referenced files and the sum of their
  1133. * lengths
  1134. */
  1135. /* set a bit in the referenced file vector */
  1136. int
  1137. set(uint8_t *vec, int fno)
  1138. {
  1139. if(vec[fno/8] & (1<<(fno&7)))
  1140. return 1;
  1141. vec[fno/8] |= 1<<(fno&7);
  1142. return 0;
  1143. }
  1144. /* merge two referenced file vectors */
  1145. void
  1146. merge(uint8_t *vec, uint8_t *ovec, int nfile)
  1147. {
  1148. nfile = (nfile+7)/8;
  1149. while(nfile-- > 0)
  1150. *vec++ |= *ovec++;
  1151. }
  1152. uint
  1153. res(Dfile *df, uint8_t *vec, int fno)
  1154. {
  1155. File *f;
  1156. Symbol *rp, *dp;
  1157. int len;
  1158. f = &df->file[fno];
  1159. if(set(vec, fno))
  1160. return 0; /* already set */
  1161. if(f->refvec != nil){
  1162. merge(vec, f->refvec, df->nfile); /* we've descended here before */
  1163. return f->tarlen;
  1164. }
  1165. len = 0;
  1166. for(rp = f->ref; rp; rp = rp->next){
  1167. dp = dfsearch(df, rp->sym);
  1168. if(dp == nil)
  1169. continue;
  1170. len += res(df, vec, dp->fno);
  1171. }
  1172. return len + Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;
  1173. }
  1174. void
  1175. dfresolve(Dfile *df, int fno)
  1176. {
  1177. uint8_t *vec;
  1178. File *f;
  1179. f = &df->file[fno];
  1180. vec = emalloc((df->nfile+7)/8);
  1181. f->tarlen = res(df, vec, fno);
  1182. f->refvec = vec;
  1183. }
  1184. /*
  1185. * make the tar directory block for a file
  1186. */
  1187. uint8_t*
  1188. mktardir(File *f)
  1189. {
  1190. uint8_t *ep;
  1191. Tardir *tp;
  1192. uint sum;
  1193. uint8_t *p, *cp;
  1194. p = emalloc(Tblocksize);
  1195. tp = (Tardir*)p;
  1196. strcpy(tp->name, f->name);
  1197. sprint(tp->mode, "%6o ", f->mode & 0777);
  1198. sprint(tp->uid, "%6o ", 0);
  1199. sprint(tp->gid, "%6o ", 0);
  1200. sprint(tp->size, "%11o ", f->len);
  1201. sprint(tp->mtime, "%11o ", f->mtime);
  1202. /* calculate checksum */
  1203. memset(tp->chksum, ' ', sizeof(tp->chksum));
  1204. sum = 0;
  1205. ep = p + Tblocksize;
  1206. for (cp = p; cp < ep; cp++)
  1207. sum += *cp;
  1208. sprint(tp->chksum, "%6o", sum);
  1209. return p;
  1210. }
  1211. /*
  1212. * manage open files
  1213. */
  1214. int
  1215. getfile(Dfile *df, File *f)
  1216. {
  1217. int n;
  1218. char path[512], *name;
  1219. qlock(&f->QLock);
  1220. f->use++;
  1221. if(f->fd < 0){
  1222. name = strrchr(df->path, '/') + 1;
  1223. n = snprint(path, sizeof path, "%.*s/%s", (int)(name-df->path), df->path, f->name);
  1224. if(n >= sizeof path - UTFmax){
  1225. syslog(0, dependlog, "path name too long: %.20s.../%.20s...", df->path, f->name);
  1226. return -1;
  1227. }
  1228. f->fd = open(path, OREAD);
  1229. if(f->fd < 0)
  1230. syslog(0, dependlog, "can't open %s: %r", path);
  1231. }
  1232. return f->fd;
  1233. }
  1234. void
  1235. releasefile(File *f)
  1236. {
  1237. --f->use;
  1238. qunlock(&f->QLock);
  1239. }
  1240. void
  1241. closefile(File *f)
  1242. {
  1243. qlock(&f->QLock);
  1244. if(f->use == 0){
  1245. close(f->fd);
  1246. f->fd = -1;
  1247. }
  1248. qunlock(&f->QLock);
  1249. }
  1250. /*
  1251. * return a block of a tar file
  1252. */
  1253. int
  1254. mktar(Dfile *df, Symbol *dp, uint8_t *area, uint offset, int len)
  1255. {
  1256. int fd, i, j, n, off;
  1257. uint8_t *p, *buf;
  1258. uint8_t *vec;
  1259. File *f;
  1260. f = &df->file[dp->fno];
  1261. vec = f->refvec;
  1262. p = area;
  1263. /* find file */
  1264. for(i = 0; i < df->nfile && len > 0; i++){
  1265. if((vec[i/8] & (1<<(i&7))) == 0)
  1266. continue;
  1267. f = &df->file[i];
  1268. n = Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;
  1269. if(offset >= n){
  1270. offset -= n;
  1271. continue;
  1272. }
  1273. if(offset < Tblocksize){
  1274. buf = mktardir(f);
  1275. if(offset + len > Tblocksize)
  1276. j = Tblocksize - offset;
  1277. else
  1278. j = len;
  1279. //if(debug)fprint(2, "reading %d bytes dir of %s\n", j, f->name);
  1280. memmove(p, buf+offset, j);
  1281. p += j;
  1282. len -= j;
  1283. offset += j;
  1284. free(buf);
  1285. }
  1286. if(len <= 0)
  1287. break;
  1288. off = offset - Tblocksize;
  1289. if(off >= 0 && off < f->len){
  1290. if(off + len > f->len)
  1291. j = f->len - off;
  1292. else
  1293. j = len;
  1294. fd = getfile(df, f);
  1295. if(fd >= 0){
  1296. //if(debug)fprint(2, "reading %d bytes from offset %d of %s\n", j, off, f->name);
  1297. if(pread(fd, p, j, off) != j)
  1298. syslog(0, dependlog, "%r reading %d bytes from offset %d of %s", j, off, f->name);
  1299. }
  1300. releasefile(f);
  1301. p += j;
  1302. len -= j;
  1303. offset += j;
  1304. }
  1305. if(len <= 0)
  1306. break;
  1307. if(offset < n){
  1308. if(offset + len > n)
  1309. j = n - offset;
  1310. else
  1311. j = len;
  1312. //if(debug)fprint(2, "filling %d bytes after %s\n", j, f->name);
  1313. memset(p, 0, j);
  1314. p += j;
  1315. len -= j;
  1316. }
  1317. offset = 0;
  1318. }
  1319. /* null blocks at end of tar file */
  1320. if(offset < 2*Tblocksize && len > 0){
  1321. if(offset + len > 2*Tblocksize)
  1322. j = 2*Tblocksize - offset;
  1323. else
  1324. j = len;
  1325. //if(debug)fprint(2, "filling %d bytes at end\n", j);
  1326. memset(p, 0, j);
  1327. p += j;
  1328. }
  1329. return p - area;
  1330. }
  1331. /*
  1332. * close the files making up a tar file
  1333. */
  1334. void
  1335. closetar(Dfile *df, Symbol *dp)
  1336. {
  1337. int i;
  1338. uint8_t *vec;
  1339. File *f;
  1340. f = &df->file[dp->fno];
  1341. vec = f->refvec;
  1342. /* find file */
  1343. for(i = 0; i < df->nfile; i++){
  1344. if((vec[i/8] & (1<<(i&7))) == 0)
  1345. continue;
  1346. closefile(&df->file[i]);
  1347. }
  1348. }