depend.c 25 KB

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