file.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114
  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 "stdinc.h"
  10. #include "vac.h"
  11. #include "dat.h"
  12. #include "fns.h"
  13. #include "error.h"
  14. #define debug 0
  15. /*
  16. * Vac file system. This is a simplified version of the same code in Fossil.
  17. *
  18. * The locking order in the tree is upward: a thread can hold the lock
  19. * for a VacFile and then acquire the lock of f->up (the parent),
  20. * but not vice-versa.
  21. *
  22. * A vac file is one or two venti files. Plain data files are one venti file,
  23. * while directores are two: a venti data file containing traditional
  24. * directory entries, and a venti directory file containing venti
  25. * directory entries. The traditional directory entries in the data file
  26. * contain integers indexing into the venti directory entry file.
  27. * It's a little complicated, but it makes the data usable by standard
  28. * tools like venti/copy.
  29. *
  30. */
  31. static int filemetaflush(VacFile*, char*);
  32. struct VacFile
  33. {
  34. VacFs *fs; /* immutable */
  35. /* meta data for file: protected by the lk in the parent */
  36. int ref; /* holds this data structure up */
  37. int partial; /* file was never really open */
  38. int removed; /* file has been removed */
  39. int dirty; /* dir is dirty with respect to meta data in block */
  40. uint32_t boff; /* block offset within msource for this file's metadata */
  41. VacDir dir; /* metadata for this file */
  42. VacFile *up; /* parent file */
  43. VacFile *next; /* sibling */
  44. RWLock lk; /* lock for the following */
  45. VtFile *source; /* actual data */
  46. VtFile *msource; /* metadata for children in a directory */
  47. VacFile *down; /* children */
  48. int mode;
  49. uint64_t qidoffset; /* qid offset */
  50. };
  51. static VacFile*
  52. filealloc(VacFs *fs)
  53. {
  54. VacFile *f;
  55. f = vtmallocz(sizeof(VacFile));
  56. f->ref = 1;
  57. f->fs = fs;
  58. f->boff = NilBlock;
  59. f->mode = fs->mode;
  60. return f;
  61. }
  62. static void
  63. filefree(VacFile *f)
  64. {
  65. vtfileclose(f->source);
  66. vtfileclose(f->msource);
  67. vdcleanup(&f->dir);
  68. memset(f, ~0, sizeof *f); /* paranoia */
  69. vtfree(f);
  70. }
  71. static int
  72. chksource(VacFile *f)
  73. {
  74. if(f->partial)
  75. return 0;
  76. if(f->source == nil
  77. || ((f->dir.mode & ModeDir) && f->msource == nil)){
  78. werrstr(ERemoved);
  79. return -1;
  80. }
  81. return 0;
  82. }
  83. static int
  84. filelock(VacFile *f)
  85. {
  86. wlock(&f->lk);
  87. if(chksource(f) < 0){
  88. wunlock(&f->lk);
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. static void
  94. fileunlock(VacFile *f)
  95. {
  96. wunlock(&f->lk);
  97. }
  98. static int
  99. filerlock(VacFile *f)
  100. {
  101. rlock(&f->lk);
  102. if(chksource(f) < 0){
  103. runlock(&f->lk);
  104. return -1;
  105. }
  106. return 0;
  107. }
  108. static void
  109. filerunlock(VacFile *f)
  110. {
  111. runlock(&f->lk);
  112. }
  113. /*
  114. * The file metadata, like f->dir and f->ref,
  115. * are synchronized via the parent's lock.
  116. * This is why locking order goes up.
  117. */
  118. static void
  119. filemetalock(VacFile *f)
  120. {
  121. assert(f->up != nil);
  122. wlock(&f->up->lk);
  123. }
  124. static void
  125. filemetaunlock(VacFile *f)
  126. {
  127. wunlock(&f->up->lk);
  128. }
  129. uint64_t
  130. vacfilegetid(VacFile *f)
  131. {
  132. /* immutable */
  133. return f->qidoffset + f->dir.qid;
  134. }
  135. uint64_t
  136. vacfilegetqidoffset(VacFile *f)
  137. {
  138. return f->qidoffset;
  139. }
  140. uint32_t
  141. vacfilegetmcount(VacFile *f)
  142. {
  143. uint32_t mcount;
  144. filemetalock(f);
  145. mcount = f->dir.mcount;
  146. filemetaunlock(f);
  147. return mcount;
  148. }
  149. uint32_t
  150. vacfilegetmode(VacFile *f)
  151. {
  152. uint32_t mode;
  153. filemetalock(f);
  154. mode = f->dir.mode;
  155. filemetaunlock(f);
  156. return mode;
  157. }
  158. int
  159. vacfileisdir(VacFile *f)
  160. {
  161. /* immutable */
  162. return (f->dir.mode & ModeDir) != 0;
  163. }
  164. int
  165. vacfileisroot(VacFile *f)
  166. {
  167. return f == f->fs->root;
  168. }
  169. /*
  170. * The files are reference counted, and while the reference
  171. * is bigger than zero, each file can be found in its parent's
  172. * f->down list (chains via f->next), so that multiple threads
  173. * end up sharing a VacFile* when referring to the same file.
  174. *
  175. * Each VacFile holds a reference to its parent.
  176. */
  177. VacFile*
  178. vacfileincref(VacFile *vf)
  179. {
  180. filemetalock(vf);
  181. assert(vf->ref > 0);
  182. vf->ref++;
  183. filemetaunlock(vf);
  184. return vf;
  185. }
  186. int
  187. vacfiledecref(VacFile *f)
  188. {
  189. VacFile *p, *q, **qq;
  190. if(f->up == nil){
  191. /* never linked in */
  192. assert(f->ref == 1);
  193. filefree(f);
  194. return 0;
  195. }
  196. filemetalock(f);
  197. f->ref--;
  198. if(f->ref > 0){
  199. filemetaunlock(f);
  200. return -1;
  201. }
  202. assert(f->ref == 0);
  203. assert(f->down == nil);
  204. if(f->source && vtfilelock(f->source, -1) >= 0){
  205. vtfileflush(f->source);
  206. vtfileunlock(f->source);
  207. }
  208. if(f->msource && vtfilelock(f->msource, -1) >= 0){
  209. vtfileflush(f->msource);
  210. vtfileunlock(f->msource);
  211. }
  212. /*
  213. * Flush f's directory information to the cache.
  214. */
  215. filemetaflush(f, nil);
  216. p = f->up;
  217. qq = &p->down;
  218. for(q = *qq; q; q = *qq){
  219. if(q == f)
  220. break;
  221. qq = &q->next;
  222. }
  223. assert(q != nil);
  224. *qq = f->next;
  225. filemetaunlock(f);
  226. filefree(f);
  227. vacfiledecref(p);
  228. return 0;
  229. }
  230. /*
  231. * Construct a vacfile for the root of a vac tree, given the
  232. * venti file for the root information. That venti file is a
  233. * directory file containing VtEntries for three more venti files:
  234. * the two venti files making up the root directory, and a
  235. * third venti file that would be the metadata half of the
  236. * "root's parent".
  237. *
  238. * Fossil generates slightly different vac files, due to a now
  239. * impossible-to-change bug, which contain a VtEntry
  240. * for just one venti file, that itself contains the expected
  241. * three directory entries. Sigh.
  242. */
  243. VacFile*
  244. _vacfileroot(VacFs *fs, VtFile *r)
  245. {
  246. int redirected;
  247. char err[ERRMAX];
  248. VtBlock *b;
  249. VtFile *r0, *r1, *r2;
  250. MetaBlock mb;
  251. MetaEntry me;
  252. VacFile *root, *mr;
  253. redirected = 0;
  254. Top:
  255. b = nil;
  256. root = nil;
  257. mr = nil;
  258. r1 = nil;
  259. r2 = nil;
  260. if(vtfilelock(r, -1) < 0)
  261. return nil;
  262. r0 = vtfileopen(r, 0, fs->mode);
  263. if(debug)
  264. fprint(2, "r0 %p\n", r0);
  265. if(r0 == nil)
  266. goto Err;
  267. r2 = vtfileopen(r, 2, fs->mode);
  268. if(debug)
  269. fprint(2, "r2 %p\n", r2);
  270. if(r2 == nil){
  271. /*
  272. * some vac files (e.g., from fossil)
  273. * have an extra layer of indirection.
  274. */
  275. rerrstr(err, sizeof err);
  276. if(!redirected && strstr(err, "not active")){
  277. redirected = 1;
  278. vtfileunlock(r);
  279. r = r0;
  280. goto Top;
  281. }
  282. goto Err;
  283. }
  284. r1 = vtfileopen(r, 1, fs->mode);
  285. if(debug)
  286. fprint(2, "r1 %p\n", r1);
  287. if(r1 == nil)
  288. goto Err;
  289. mr = filealloc(fs);
  290. mr->msource = r2;
  291. r2 = nil;
  292. root = filealloc(fs);
  293. root->boff = 0;
  294. root->up = mr;
  295. root->source = r0;
  296. r0 = nil;
  297. root->msource = r1;
  298. r1 = nil;
  299. mr->down = root;
  300. vtfileunlock(r);
  301. if(vtfilelock(mr->msource, VtOREAD) < 0)
  302. goto Err1;
  303. b = vtfileblock(mr->msource, 0, VtOREAD);
  304. vtfileunlock(mr->msource);
  305. if(b == nil)
  306. goto Err1;
  307. if(mbunpack(&mb, b->data, mr->msource->dsize) < 0)
  308. goto Err1;
  309. meunpack(&me, &mb, 0);
  310. if(vdunpack(&root->dir, &me) < 0)
  311. goto Err1;
  312. vtblockput(b);
  313. return root;
  314. Err:
  315. vtfileunlock(r);
  316. Err1:
  317. vtblockput(b);
  318. if(r0)
  319. vtfileclose(r0);
  320. if(r1)
  321. vtfileclose(r1);
  322. if(r2)
  323. vtfileclose(r2);
  324. if(mr)
  325. filefree(mr);
  326. if(root)
  327. filefree(root);
  328. return nil;
  329. }
  330. /*
  331. * Vac directories are a sequence of metablocks, each of which
  332. * contains a bunch of metaentries sorted by file name.
  333. * The whole sequence isn't sorted, though, so you still have
  334. * to look at every block to find a given name.
  335. * Dirlookup looks in f for an element name elem.
  336. * It returns a new VacFile with the dir, boff, and mode
  337. * filled in, but the sources (venti files) are not, and f is
  338. * not yet linked into the tree. These details must be taken
  339. * care of by the caller.
  340. *
  341. * f must be locked, f->msource must not.
  342. */
  343. static VacFile*
  344. dirlookup(VacFile *f, char *elem)
  345. {
  346. int i;
  347. MetaBlock mb;
  348. MetaEntry me;
  349. VtBlock *b;
  350. VtFile *meta;
  351. VacFile *ff;
  352. uint32_t bo, nb;
  353. meta = f->msource;
  354. b = nil;
  355. if(vtfilelock(meta, -1) < 0)
  356. return nil;
  357. nb = (vtfilegetsize(meta)+meta->dsize-1)/meta->dsize;
  358. for(bo=0; bo<nb; bo++){
  359. b = vtfileblock(meta, bo, VtOREAD);
  360. if(b == nil)
  361. goto Err;
  362. if(mbunpack(&mb, b->data, meta->dsize) < 0)
  363. goto Err;
  364. if(mbsearch(&mb, elem, &i, &me) >= 0){
  365. ff = filealloc(f->fs);
  366. if(vdunpack(&ff->dir, &me) < 0){
  367. filefree(ff);
  368. goto Err;
  369. }
  370. ff->qidoffset = f->qidoffset + ff->dir.qidoffset;
  371. vtfileunlock(meta);
  372. vtblockput(b);
  373. ff->boff = bo;
  374. ff->mode = f->mode;
  375. return ff;
  376. }
  377. vtblockput(b);
  378. b = nil;
  379. }
  380. werrstr(ENoFile);
  381. /* fall through */
  382. Err:
  383. vtfileunlock(meta);
  384. vtblockput(b);
  385. return nil;
  386. }
  387. /*
  388. * Open the venti file at offset in the directory f->source.
  389. * f is locked.
  390. */
  391. static VtFile *
  392. fileopensource(VacFile *f, uint32_t offset, uint32_t gen, int dir,
  393. uint mode)
  394. {
  395. VtFile *r;
  396. if((r = vtfileopen(f->source, offset, mode)) == nil)
  397. return nil;
  398. if(r == nil)
  399. return nil;
  400. if(r->gen != gen){
  401. werrstr(ERemoved);
  402. vtfileclose(r);
  403. return nil;
  404. }
  405. if(r->dir != dir && r->mode != -1){
  406. werrstr(EBadMeta);
  407. vtfileclose(r);
  408. return nil;
  409. }
  410. return r;
  411. }
  412. VacFile*
  413. vacfilegetparent(VacFile *f)
  414. {
  415. if(vacfileisroot(f))
  416. return vacfileincref(f);
  417. return vacfileincref(f->up);
  418. }
  419. /*
  420. * Given an unlocked vacfile (directory) f,
  421. * return the vacfile named elem in f.
  422. * Interprets . and .. as a convenience to callers.
  423. */
  424. VacFile*
  425. vacfilewalk(VacFile *f, char *elem)
  426. {
  427. VacFile *ff;
  428. if(elem[0] == 0){
  429. werrstr(EBadPath);
  430. return nil;
  431. }
  432. if(!vacfileisdir(f)){
  433. werrstr(ENotDir);
  434. return nil;
  435. }
  436. if(strcmp(elem, ".") == 0)
  437. return vacfileincref(f);
  438. if(strcmp(elem, "..") == 0)
  439. return vacfilegetparent(f);
  440. if(filelock(f) < 0)
  441. return nil;
  442. for(ff = f->down; ff; ff=ff->next){
  443. if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
  444. ff->ref++;
  445. goto Exit;
  446. }
  447. }
  448. ff = dirlookup(f, elem);
  449. if(ff == nil)
  450. goto Err;
  451. if(ff->dir.mode & ModeSnapshot)
  452. ff->mode = VtOREAD;
  453. if(vtfilelock(f->source, f->mode) < 0)
  454. goto Err;
  455. if(ff->dir.mode & ModeDir){
  456. ff->source = fileopensource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode);
  457. ff->msource = fileopensource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode);
  458. if(ff->source == nil || ff->msource == nil)
  459. goto Err1;
  460. }else{
  461. ff->source = fileopensource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode);
  462. if(ff->source == nil)
  463. goto Err1;
  464. }
  465. vtfileunlock(f->source);
  466. /* link in and up parent ref count */
  467. ff->next = f->down;
  468. f->down = ff;
  469. ff->up = f;
  470. vacfileincref(f);
  471. Exit:
  472. fileunlock(f);
  473. return ff;
  474. Err1:
  475. vtfileunlock(f->source);
  476. Err:
  477. fileunlock(f);
  478. if(ff != nil)
  479. vacfiledecref(ff);
  480. return nil;
  481. }
  482. /*
  483. * Open a path in the vac file system:
  484. * just walk each element one at a time.
  485. */
  486. VacFile*
  487. vacfileopen(VacFs *fs, char *path)
  488. {
  489. VacFile *f, *ff;
  490. char *p, elem[VtMaxStringSize], *opath;
  491. int n;
  492. f = fs->root;
  493. vacfileincref(f);
  494. opath = path;
  495. while(*path != 0){
  496. for(p = path; *p && *p != '/'; p++)
  497. ;
  498. n = p - path;
  499. if(n > 0){
  500. if(n > VtMaxStringSize){
  501. werrstr("%s: element too long", EBadPath);
  502. goto Err;
  503. }
  504. memmove(elem, path, n);
  505. elem[n] = 0;
  506. ff = vacfilewalk(f, elem);
  507. if(ff == nil){
  508. werrstr("%.*s: %r", utfnlen(opath, p-opath), opath);
  509. goto Err;
  510. }
  511. vacfiledecref(f);
  512. f = ff;
  513. }
  514. if(*p == '/')
  515. p++;
  516. path = p;
  517. }
  518. return f;
  519. Err:
  520. vacfiledecref(f);
  521. return nil;
  522. }
  523. /*
  524. * Extract the score for the bn'th block in f.
  525. */
  526. int
  527. vacfileblockscore(VacFile *f, uint32_t bn, uint8_t *score)
  528. {
  529. VtFile *s;
  530. uint64_t size;
  531. int dsize, ret;
  532. ret = -1;
  533. if(filerlock(f) < 0)
  534. return -1;
  535. if(vtfilelock(f->source, VtOREAD) < 0)
  536. goto out;
  537. s = f->source;
  538. dsize = s->dsize;
  539. size = vtfilegetsize(s);
  540. if((uint64_t)bn*dsize >= size)
  541. goto out1;
  542. ret = vtfileblockscore(f->source, bn, score);
  543. out1:
  544. vtfileunlock(f->source);
  545. out:
  546. filerunlock(f);
  547. return ret;
  548. }
  549. /*
  550. * Read data from f.
  551. */
  552. int
  553. vacfileread(VacFile *f, void *buf, int cnt, int64_t offset)
  554. {
  555. int n;
  556. if(offset < 0){
  557. werrstr(EBadOffset);
  558. return -1;
  559. }
  560. if(filerlock(f) < 0)
  561. return -1;
  562. if(vtfilelock(f->source, VtOREAD) < 0){
  563. filerunlock(f);
  564. return -1;
  565. }
  566. n = vtfileread(f->source, buf, cnt, offset);
  567. vtfileunlock(f->source);
  568. filerunlock(f);
  569. return n;
  570. }
  571. static int
  572. getentry(VtFile *f, VtEntry *e)
  573. {
  574. if(vtfilelock(f, VtOREAD) < 0)
  575. return -1;
  576. if(vtfilegetentry(f, e) < 0){
  577. vtfileunlock(f);
  578. return -1;
  579. }
  580. vtfileunlock(f);
  581. if(vtglobaltolocal(e->score) != NilBlock){
  582. werrstr("internal error - data not on venti");
  583. return -1;
  584. }
  585. return 0;
  586. }
  587. /*
  588. * Get the VtEntries for the data contained in f.
  589. */
  590. int
  591. vacfilegetentries(VacFile *f, VtEntry *e, VtEntry *me)
  592. {
  593. if(filerlock(f) < 0)
  594. return -1;
  595. if(e && getentry(f->source, e) < 0){
  596. filerunlock(f);
  597. return -1;
  598. }
  599. if(me){
  600. if(f->msource == nil)
  601. memset(me, 0, sizeof *me);
  602. else if(getentry(f->msource, me) < 0){
  603. filerunlock(f);
  604. return -1;
  605. }
  606. }
  607. filerunlock(f);
  608. return 0;
  609. }
  610. /*
  611. * Get the file's size.
  612. */
  613. int
  614. vacfilegetsize(VacFile *f, uint64_t *size)
  615. {
  616. if(filerlock(f) < 0)
  617. return -1;
  618. if(vtfilelock(f->source, VtOREAD) < 0){
  619. filerunlock(f);
  620. return -1;
  621. }
  622. *size = vtfilegetsize(f->source);
  623. vtfileunlock(f->source);
  624. filerunlock(f);
  625. return 0;
  626. }
  627. /*
  628. * Directory reading.
  629. *
  630. * A VacDirEnum is a buffer containing directory entries.
  631. * Directory entries contain malloced strings and need to
  632. * be cleaned up with vdcleanup. The invariant in the
  633. * VacDirEnum is that the directory entries between
  634. * vde->i and vde->n are owned by the vde and need to
  635. * be cleaned up if it is closed. Those from 0 up to vde->i
  636. * have been handed to the reader, and the reader must
  637. * take care of calling vdcleanup as appropriate.
  638. */
  639. VacDirEnum*
  640. vdeopen(VacFile *f)
  641. {
  642. VacDirEnum *vde;
  643. VacFile *p;
  644. if(!vacfileisdir(f)){
  645. werrstr(ENotDir);
  646. return nil;
  647. }
  648. /*
  649. * There might be changes to this directory's children
  650. * that have not been flushed out into the cache yet.
  651. * Those changes are only available if we look at the
  652. * VacFile structures directory. But the directory reader
  653. * is going to read the cache blocks directly, so update them.
  654. */
  655. if(filelock(f) < 0)
  656. return nil;
  657. for(p=f->down; p; p=p->next)
  658. filemetaflush(p, nil);
  659. fileunlock(f);
  660. vde = vtmallocz(sizeof(VacDirEnum));
  661. vde->file = vacfileincref(f);
  662. return vde;
  663. }
  664. /*
  665. * Figure out the size of the directory entry at offset.
  666. * The rest of the metadata is kept in the data half,
  667. * but since venti has to track the data size anyway,
  668. * we just use that one and avoid updating the directory
  669. * each time the file size changes.
  670. */
  671. static int
  672. direntrysize(VtFile *s, uint32_t offset, uint32_t gen, uint64_t *size)
  673. {
  674. VtBlock *b;
  675. uint32_t bn;
  676. VtEntry e;
  677. int epb;
  678. epb = s->dsize/VtEntrySize;
  679. bn = offset/epb;
  680. offset -= bn*epb;
  681. b = vtfileblock(s, bn, VtOREAD);
  682. if(b == nil)
  683. goto Err;
  684. if(vtentryunpack(&e, b->data, offset) < 0)
  685. goto Err;
  686. /* dangling entries are returned as zero size */
  687. if(!(e.flags & VtEntryActive) || e.gen != gen)
  688. *size = 0;
  689. else
  690. *size = e.size;
  691. vtblockput(b);
  692. return 0;
  693. Err:
  694. vtblockput(b);
  695. return -1;
  696. }
  697. /*
  698. * Fill in vde with a new batch of directory entries.
  699. */
  700. static int
  701. vdefill(VacDirEnum *vde)
  702. {
  703. int i, n;
  704. VtFile *meta, *source;
  705. MetaBlock mb;
  706. MetaEntry me;
  707. VacFile *f;
  708. VtBlock *b;
  709. VacDir *de;
  710. /* clean up first */
  711. for(i=vde->i; i<vde->n; i++)
  712. vdcleanup(vde->buf+i);
  713. vtfree(vde->buf);
  714. vde->buf = nil;
  715. vde->i = 0;
  716. vde->n = 0;
  717. f = vde->file;
  718. source = f->source;
  719. meta = f->msource;
  720. b = vtfileblock(meta, vde->boff, VtOREAD);
  721. if(b == nil)
  722. goto Err;
  723. if(mbunpack(&mb, b->data, meta->dsize) < 0)
  724. goto Err;
  725. n = mb.nindex;
  726. vde->buf = vtmalloc(n * sizeof(VacDir));
  727. for(i=0; i<n; i++){
  728. de = vde->buf + i;
  729. meunpack(&me, &mb, i);
  730. if(vdunpack(de, &me) < 0)
  731. goto Err;
  732. vde->n++;
  733. if(!(de->mode & ModeDir))
  734. if(direntrysize(source, de->entry, de->gen, &de->size) < 0)
  735. goto Err;
  736. }
  737. vde->boff++;
  738. vtblockput(b);
  739. return 0;
  740. Err:
  741. vtblockput(b);
  742. return -1;
  743. }
  744. /*
  745. * Read a single directory entry from vde into de.
  746. * Returns -1 on error, 0 on EOF, and 1 on success.
  747. * When it returns 1, it becomes the caller's responsibility
  748. * to call vdcleanup(de) to free the strings contained
  749. * inside, or else to call vdunread to give it back.
  750. */
  751. int
  752. vderead(VacDirEnum *vde, VacDir *de)
  753. {
  754. int ret;
  755. VacFile *f;
  756. uint32_t nb;
  757. f = vde->file;
  758. if(filerlock(f) < 0)
  759. return -1;
  760. if(vtfilelock2(f->source, f->msource, VtOREAD) < 0){
  761. filerunlock(f);
  762. return -1;
  763. }
  764. nb = (vtfilegetsize(f->msource)+f->msource->dsize-1)/f->msource->dsize;
  765. while(vde->i >= vde->n){
  766. if(vde->boff >= nb){
  767. ret = 0;
  768. goto Return;
  769. }
  770. if(vdefill(vde) < 0){
  771. ret = -1;
  772. goto Return;
  773. }
  774. }
  775. memmove(de, vde->buf + vde->i, sizeof(VacDir));
  776. vde->i++;
  777. ret = 1;
  778. Return:
  779. vtfileunlock(f->source);
  780. vtfileunlock(f->msource);
  781. filerunlock(f);
  782. return ret;
  783. }
  784. /*
  785. * "Unread" the last directory entry that was read,
  786. * so that the next vderead will return the same one.
  787. * If the caller calls vdeunread(vde) it should not call
  788. * vdcleanup on the entry being "unread".
  789. */
  790. int
  791. vdeunread(VacDirEnum *vde)
  792. {
  793. if(vde->i > 0){
  794. vde->i--;
  795. return 0;
  796. }
  797. return -1;
  798. }
  799. /*
  800. * Close the enumerator.
  801. */
  802. void
  803. vdeclose(VacDirEnum *vde)
  804. {
  805. int i;
  806. if(vde == nil)
  807. return;
  808. /* free the strings */
  809. for(i=vde->i; i<vde->n; i++)
  810. vdcleanup(vde->buf+i);
  811. vtfree(vde->buf);
  812. vacfiledecref(vde->file);
  813. vtfree(vde);
  814. }
  815. /*
  816. * On to mutation. If the vac file system has been opened
  817. * read-write, then the files and directories can all be edited.
  818. * Changes are kept in the in-memory cache until flushed out
  819. * to venti, so we must be careful to explicitly flush data
  820. * that we're not likely to modify again.
  821. *
  822. * Each VacFile has its own copy of its VacDir directory entry
  823. * in f->dir, but otherwise the cache is the authoratative source
  824. * for data. Thus, for the most part, it suffices if we just
  825. * call vtfileflushbefore and vtfileflush when we modify things.
  826. * There are a few places where we have to remember to write
  827. * changed VacDirs back into the cache. If f->dir *is* out of sync,
  828. * then f->dirty should be set.
  829. *
  830. * The metadata in a directory is, to venti, a plain data file,
  831. * but as mentioned above it is actually a sequence of
  832. * MetaBlocks that contain sorted lists of VacDir entries.
  833. * The filemetaxxx routines manipulate that stream.
  834. */
  835. /*
  836. * Find space in fp for the directory entry dir (not yet written to disk)
  837. * and write it to disk, returning NilBlock on failure,
  838. * or the block number on success.
  839. *
  840. * Start is a suggested block number to try.
  841. * The caller must have filemetalock'ed f and have
  842. * vtfilelock'ed f->up->msource.
  843. */
  844. static uint32_t
  845. filemetaalloc(VacFile *fp, VacDir *dir, uint32_t start)
  846. {
  847. uint32_t nb, bo;
  848. VtBlock *b;
  849. MetaBlock mb;
  850. int nn;
  851. uint8_t *p;
  852. int i, n;
  853. MetaEntry me;
  854. VtFile *ms;
  855. ms = fp->msource;
  856. n = vdsize(dir, VacDirVersion);
  857. /* Look for a block with room for a new entry of size n. */
  858. nb = (vtfilegetsize(ms)+ms->dsize-1)/ms->dsize;
  859. if(start == NilBlock){
  860. if(nb > 0)
  861. start = nb - 1;
  862. else
  863. start = 0;
  864. }
  865. if(start > nb)
  866. start = nb;
  867. for(bo=start; bo<nb; bo++){
  868. if((b = vtfileblock(ms, bo, VtOREAD)) == nil)
  869. goto Err;
  870. if(mbunpack(&mb, b->data, ms->dsize) < 0)
  871. goto Err;
  872. nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
  873. if(n <= nn && mb.nindex < mb.maxindex){
  874. /* reopen for writing */
  875. vtblockput(b);
  876. if((b = vtfileblock(ms, bo, VtORDWR)) == nil)
  877. goto Err;
  878. mbunpack(&mb, b->data, ms->dsize);
  879. goto Found;
  880. }
  881. vtblockput(b);
  882. }
  883. /* No block found, extend the file by one metablock. */
  884. vtfileflushbefore(ms, nb*(uint64_t)ms->dsize);
  885. if((b = vtfileblock(ms, nb, VtORDWR)) == nil)
  886. goto Err;
  887. vtfilesetsize(ms, (nb+1)*ms->dsize);
  888. mbinit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
  889. Found:
  890. /* Now we have a block; allocate space to write the entry. */
  891. p = mballoc(&mb, n);
  892. if(p == nil){
  893. /* mballoc might have changed block */
  894. mbpack(&mb);
  895. werrstr(EBadMeta);
  896. goto Err;
  897. }
  898. /* Figure out where to put the index entry, and write it. */
  899. mbsearch(&mb, dir->elem, &i, &me);
  900. assert(me.p == nil); /* not already there */
  901. me.p = p;
  902. me.size = n;
  903. vdpack(dir, &me, VacDirVersion);
  904. mbinsert(&mb, i, &me);
  905. mbpack(&mb);
  906. vtblockput(b);
  907. return bo;
  908. Err:
  909. vtblockput(b);
  910. return NilBlock;
  911. }
  912. /*
  913. * Update f's directory entry in the block cache.
  914. * We look for the directory entry by name;
  915. * if we're trying to rename the file, oelem is the old name.
  916. *
  917. * Assumes caller has filemetalock'ed f.
  918. */
  919. static int
  920. filemetaflush(VacFile *f, char *oelem)
  921. {
  922. int i, n;
  923. MetaBlock mb;
  924. MetaEntry me, me2;
  925. VacFile *fp;
  926. VtBlock *b;
  927. uint32_t bo;
  928. if(!f->dirty)
  929. return 0;
  930. if(oelem == nil)
  931. oelem = f->dir.elem;
  932. /*
  933. * Locate f's old metadata in the parent's metadata file.
  934. * We know which block it was in, but not exactly where
  935. * in the block.
  936. */
  937. fp = f->up;
  938. if(vtfilelock(fp->msource, -1) < 0)
  939. return -1;
  940. /* can happen if source is clri'ed out from under us */
  941. if(f->boff == NilBlock)
  942. goto Err1;
  943. b = vtfileblock(fp->msource, f->boff, VtORDWR);
  944. if(b == nil)
  945. goto Err1;
  946. if(mbunpack(&mb, b->data, fp->msource->dsize) < 0)
  947. goto Err;
  948. if(mbsearch(&mb, oelem, &i, &me) < 0)
  949. goto Err;
  950. /*
  951. * Check whether we can resize the entry and keep it
  952. * in this block.
  953. */
  954. n = vdsize(&f->dir, VacDirVersion);
  955. if(mbresize(&mb, &me, n) >= 0){
  956. /* Okay, can be done without moving to another block. */
  957. /* Remove old data */
  958. mbdelete(&mb, i, &me);
  959. /* Find new location if renaming */
  960. if(strcmp(f->dir.elem, oelem) != 0)
  961. mbsearch(&mb, f->dir.elem, &i, &me2);
  962. /* Pack new data into new location. */
  963. vdpack(&f->dir, &me, VacDirVersion);
  964. vdunpack(&f->dir, &me);
  965. mbinsert(&mb, i, &me);
  966. mbpack(&mb);
  967. /* Done */
  968. vtblockput(b);
  969. vtfileunlock(fp->msource);
  970. f->dirty = 0;
  971. return 0;
  972. }
  973. /*
  974. * The entry must be moved to another block.
  975. * This can only really happen on renames that
  976. * make the name very long.
  977. */
  978. /* Allocate a spot in a new block. */
  979. if((bo = filemetaalloc(fp, &f->dir, f->boff+1)) == NilBlock){
  980. /* mbresize above might have modified block */
  981. mbpack(&mb);
  982. goto Err;
  983. }
  984. f->boff = bo;
  985. /* Now we're committed. Delete entry in old block. */
  986. mbdelete(&mb, i, &me);
  987. mbpack(&mb);
  988. vtblockput(b);
  989. vtfileunlock(fp->msource);
  990. f->dirty = 0;
  991. return 0;
  992. Err:
  993. vtblockput(b);
  994. Err1:
  995. vtfileunlock(fp->msource);
  996. return -1;
  997. }
  998. /*
  999. * Remove the directory entry for f.
  1000. */
  1001. static int
  1002. filemetaremove(VacFile *f)
  1003. {
  1004. VtBlock *b;
  1005. MetaBlock mb;
  1006. MetaEntry me;
  1007. int i;
  1008. VacFile *fp;
  1009. b = nil;
  1010. fp = f->up;
  1011. filemetalock(f);
  1012. if(vtfilelock(fp->msource, VtORDWR) < 0)
  1013. goto Err;
  1014. b = vtfileblock(fp->msource, f->boff, VtORDWR);
  1015. if(b == nil)
  1016. goto Err;
  1017. if(mbunpack(&mb, b->data, fp->msource->dsize) < 0)
  1018. goto Err;
  1019. if(mbsearch(&mb, f->dir.elem, &i, &me) < 0)
  1020. goto Err;
  1021. mbdelete(&mb, i, &me);
  1022. mbpack(&mb);
  1023. vtblockput(b);
  1024. vtfileunlock(fp->msource);
  1025. f->removed = 1;
  1026. f->boff = NilBlock;
  1027. f->dirty = 0;
  1028. filemetaunlock(f);
  1029. return 0;
  1030. Err:
  1031. vtfileunlock(fp->msource);
  1032. vtblockput(b);
  1033. filemetaunlock(f);
  1034. return -1;
  1035. }
  1036. /*
  1037. * That was far too much effort for directory entries.
  1038. * Now we can write code that *does* things.
  1039. */
  1040. /*
  1041. * Flush all data associated with f out of the cache and onto venti.
  1042. * If recursive is set, flush f's children too.
  1043. * Vacfiledecref knows how to flush source and msource too.
  1044. */
  1045. int
  1046. vacfileflush(VacFile *f, int recursive)
  1047. {
  1048. int ret;
  1049. VacFile **kids, *p;
  1050. int i, nkids;
  1051. if(f->mode == VtOREAD)
  1052. return 0;
  1053. ret = 0;
  1054. filemetalock(f);
  1055. if(filemetaflush(f, nil) < 0)
  1056. ret = -1;
  1057. filemetaunlock(f);
  1058. if(filelock(f) < 0)
  1059. return -1;
  1060. /*
  1061. * Lock order prevents us from flushing kids while holding
  1062. * lock, so make a list and then flush without the lock.
  1063. */
  1064. nkids = 0;
  1065. kids = nil;
  1066. if(recursive){
  1067. nkids = 0;
  1068. for(p=f->down; p; p=p->next)
  1069. nkids++;
  1070. kids = vtmalloc(nkids*sizeof(VacFile*));
  1071. i = 0;
  1072. for(p=f->down; p; p=p->next){
  1073. kids[i++] = p;
  1074. p->ref++;
  1075. }
  1076. }
  1077. if(nkids > 0){
  1078. fileunlock(f);
  1079. for(i=0; i<nkids; i++){
  1080. if(vacfileflush(kids[i], 1) < 0)
  1081. ret = -1;
  1082. vacfiledecref(kids[i]);
  1083. }
  1084. filelock(f);
  1085. }
  1086. free(kids);
  1087. /*
  1088. * Now we can flush our own data.
  1089. */
  1090. vtfilelock(f->source, -1);
  1091. if(vtfileflush(f->source) < 0)
  1092. ret = -1;
  1093. vtfileunlock(f->source);
  1094. if(f->msource){
  1095. vtfilelock(f->msource, -1);
  1096. if(vtfileflush(f->msource) < 0)
  1097. ret = -1;
  1098. vtfileunlock(f->msource);
  1099. }
  1100. fileunlock(f);
  1101. return ret;
  1102. }
  1103. /*
  1104. * Create a new file named elem in fp with the given mode.
  1105. * The mode can be changed later except for the ModeDir bit.
  1106. */
  1107. VacFile*
  1108. vacfilecreate(VacFile *fp, char *elem, uint32_t mode)
  1109. {
  1110. VacFile *ff;
  1111. VacDir *dir;
  1112. VtFile *pr, *r, *mr;
  1113. int type;
  1114. uint32_t bo;
  1115. if(filelock(fp) < 0)
  1116. return nil;
  1117. /*
  1118. * First, look to see that there's not a file in memory
  1119. * with the same name.
  1120. */
  1121. for(ff = fp->down; ff; ff=ff->next){
  1122. if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
  1123. ff = nil;
  1124. werrstr(EExists);
  1125. goto Err1;
  1126. }
  1127. }
  1128. /*
  1129. * Next check the venti blocks.
  1130. */
  1131. ff = dirlookup(fp, elem);
  1132. if(ff != nil){
  1133. werrstr(EExists);
  1134. goto Err1;
  1135. }
  1136. /*
  1137. * By the way, you can't create in a read-only file system.
  1138. */
  1139. pr = fp->source;
  1140. if(pr->mode != VtORDWR){
  1141. werrstr(EReadOnly);
  1142. goto Err1;
  1143. }
  1144. /*
  1145. * Okay, time to actually create something. Lock the two
  1146. * halves of the directory and create a file.
  1147. */
  1148. if(vtfilelock2(fp->source, fp->msource, -1) < 0)
  1149. goto Err1;
  1150. ff = filealloc(fp->fs);
  1151. ff->qidoffset = fp->qidoffset; /* hopefully fp->qidoffset == 0 */
  1152. type = VtDataType;
  1153. if(mode & ModeDir)
  1154. type = VtDirType;
  1155. mr = nil;
  1156. if((r = vtfilecreate(pr, pr->psize, pr->dsize, type)) == nil)
  1157. goto Err;
  1158. if(mode & ModeDir)
  1159. if((mr = vtfilecreate(pr, pr->psize, pr->dsize, VtDataType)) == nil)
  1160. goto Err;
  1161. /*
  1162. * Fill in the directory entry and write it to disk.
  1163. */
  1164. dir = &ff->dir;
  1165. dir->elem = vtstrdup(elem);
  1166. dir->entry = r->offset;
  1167. dir->gen = r->gen;
  1168. if(mode & ModeDir){
  1169. dir->mentry = mr->offset;
  1170. dir->mgen = mr->gen;
  1171. }
  1172. dir->size = 0;
  1173. if(_vacfsnextqid(fp->fs, &dir->qid) < 0)
  1174. goto Err;
  1175. dir->uid = vtstrdup(fp->dir.uid);
  1176. dir->gid = vtstrdup(fp->dir.gid);
  1177. dir->mid = vtstrdup("");
  1178. dir->mtime = time(0L);
  1179. dir->mcount = 0;
  1180. dir->ctime = dir->mtime;
  1181. dir->atime = dir->mtime;
  1182. dir->mode = mode;
  1183. if((bo = filemetaalloc(fp, &ff->dir, NilBlock)) == NilBlock)
  1184. goto Err;
  1185. /*
  1186. * Now we're committed.
  1187. */
  1188. vtfileunlock(fp->source);
  1189. vtfileunlock(fp->msource);
  1190. ff->source = r;
  1191. ff->msource = mr;
  1192. ff->boff = bo;
  1193. /* Link into tree. */
  1194. ff->next = fp->down;
  1195. fp->down = ff;
  1196. ff->up = fp;
  1197. vacfileincref(fp);
  1198. fileunlock(fp);
  1199. filelock(ff);
  1200. vtfilelock(ff->source, -1);
  1201. vtfileunlock(ff->source);
  1202. fileunlock(ff);
  1203. return ff;
  1204. Err:
  1205. vtfileunlock(fp->source);
  1206. vtfileunlock(fp->msource);
  1207. if(r){
  1208. vtfilelock(r, -1);
  1209. vtfileremove(r);
  1210. }
  1211. if(mr){
  1212. vtfilelock(mr, -1);
  1213. vtfileremove(mr);
  1214. }
  1215. Err1:
  1216. if(ff)
  1217. vacfiledecref(ff);
  1218. fileunlock(fp);
  1219. return nil;
  1220. }
  1221. /*
  1222. * Change the size of the file f.
  1223. */
  1224. int
  1225. vacfilesetsize(VacFile *f, uint64_t size)
  1226. {
  1227. if(vacfileisdir(f)){
  1228. werrstr(ENotFile);
  1229. return -1;
  1230. }
  1231. if(filelock(f) < 0)
  1232. return -1;
  1233. if(f->source->mode != VtORDWR){
  1234. werrstr(EReadOnly);
  1235. goto Err;
  1236. }
  1237. if(vtfilelock(f->source, -1) < 0)
  1238. goto Err;
  1239. if(vtfilesetsize(f->source, size) < 0){
  1240. vtfileunlock(f->source);
  1241. goto Err;
  1242. }
  1243. vtfileunlock(f->source);
  1244. fileunlock(f);
  1245. return 0;
  1246. Err:
  1247. fileunlock(f);
  1248. return -1;
  1249. }
  1250. /*
  1251. * Write data to f.
  1252. */
  1253. int
  1254. vacfilewrite(VacFile *f, void *buf, int cnt, int64_t offset)
  1255. {
  1256. if(vacfileisdir(f)){
  1257. werrstr(ENotFile);
  1258. return -1;
  1259. }
  1260. if(filelock(f) < 0)
  1261. return -1;
  1262. if(f->source->mode != VtORDWR){
  1263. werrstr(EReadOnly);
  1264. goto Err;
  1265. }
  1266. if(offset < 0){
  1267. werrstr(EBadOffset);
  1268. goto Err;
  1269. }
  1270. if(vtfilelock(f->source, -1) < 0)
  1271. goto Err;
  1272. if(f->dir.mode & ModeAppend)
  1273. offset = vtfilegetsize(f->source);
  1274. if(vtfilewrite(f->source, buf, cnt, offset) != cnt
  1275. || vtfileflushbefore(f->source, offset) < 0){
  1276. vtfileunlock(f->source);
  1277. goto Err;
  1278. }
  1279. vtfileunlock(f->source);
  1280. fileunlock(f);
  1281. return cnt;
  1282. Err:
  1283. fileunlock(f);
  1284. return -1;
  1285. }
  1286. /*
  1287. * Set (!) the VtEntry for the data contained in f.
  1288. * This let's us efficiently copy data from one file to another.
  1289. */
  1290. int
  1291. vacfilesetentries(VacFile *f, VtEntry *e, VtEntry *me)
  1292. {
  1293. int ret;
  1294. vacfileflush(f, 0); /* flush blocks to venti, since we won't see them again */
  1295. if(!(e->flags&VtEntryActive)){
  1296. werrstr("missing entry for source");
  1297. return -1;
  1298. }
  1299. if(me && !(me->flags&VtEntryActive))
  1300. me = nil;
  1301. if(f->msource && !me){
  1302. werrstr("missing entry for msource");
  1303. return -1;
  1304. }
  1305. if(me && !f->msource){
  1306. werrstr("no msource to set");
  1307. return -1;
  1308. }
  1309. if(filelock(f) < 0)
  1310. return -1;
  1311. if(f->source->mode != VtORDWR
  1312. || (f->msource && f->msource->mode != VtORDWR)){
  1313. werrstr(EReadOnly);
  1314. fileunlock(f);
  1315. return -1;
  1316. }
  1317. if(vtfilelock2(f->source, f->msource, -1) < 0){
  1318. fileunlock(f);
  1319. return -1;
  1320. }
  1321. ret = 0;
  1322. if(vtfilesetentry(f->source, e) < 0)
  1323. ret = -1;
  1324. else if(me && vtfilesetentry(f->msource, me) < 0)
  1325. ret = -1;
  1326. vtfileunlock(f->source);
  1327. if(f->msource)
  1328. vtfileunlock(f->msource);
  1329. fileunlock(f);
  1330. return ret;
  1331. }
  1332. /*
  1333. * Get the directory entry for f.
  1334. */
  1335. int
  1336. vacfilegetdir(VacFile *f, VacDir *dir)
  1337. {
  1338. if(filerlock(f) < 0)
  1339. return -1;
  1340. filemetalock(f);
  1341. vdcopy(dir, &f->dir);
  1342. filemetaunlock(f);
  1343. if(!vacfileisdir(f)){
  1344. if(vtfilelock(f->source, VtOREAD) < 0){
  1345. filerunlock(f);
  1346. return -1;
  1347. }
  1348. dir->size = vtfilegetsize(f->source);
  1349. vtfileunlock(f->source);
  1350. }
  1351. filerunlock(f);
  1352. return 0;
  1353. }
  1354. /*
  1355. * Set the directory entry for f.
  1356. */
  1357. int
  1358. vacfilesetdir(VacFile *f, VacDir *dir)
  1359. {
  1360. VacFile *ff;
  1361. char *oelem;
  1362. uint32_t mask;
  1363. uint64_t size;
  1364. /* can not set permissions for the root */
  1365. if(vacfileisroot(f)){
  1366. werrstr(ERoot);
  1367. return -1;
  1368. }
  1369. if(filelock(f) < 0)
  1370. return -1;
  1371. filemetalock(f);
  1372. if(f->source->mode != VtORDWR){
  1373. werrstr(EReadOnly);
  1374. goto Err;
  1375. }
  1376. /* On rename, check new name does not already exist */
  1377. if(strcmp(f->dir.elem, dir->elem) != 0){
  1378. for(ff = f->up->down; ff; ff=ff->next){
  1379. if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
  1380. werrstr(EExists);
  1381. goto Err;
  1382. }
  1383. }
  1384. ff = dirlookup(f->up, dir->elem);
  1385. if(ff != nil){
  1386. vacfiledecref(ff);
  1387. werrstr(EExists);
  1388. goto Err;
  1389. }
  1390. werrstr(""); /* "failed" dirlookup poisoned it */
  1391. }
  1392. /* Get ready... */
  1393. if(vtfilelock2(f->source, f->msource, -1) < 0)
  1394. goto Err;
  1395. if(!vacfileisdir(f)){
  1396. size = vtfilegetsize(f->source);
  1397. if(size != dir->size){
  1398. if(vtfilesetsize(f->source, dir->size) < 0){
  1399. vtfileunlock(f->source);
  1400. if(f->msource)
  1401. vtfileunlock(f->msource);
  1402. goto Err;
  1403. }
  1404. }
  1405. }
  1406. /* ... now commited to changing it. */
  1407. vtfileunlock(f->source);
  1408. if(f->msource)
  1409. vtfileunlock(f->msource);
  1410. oelem = nil;
  1411. if(strcmp(f->dir.elem, dir->elem) != 0){
  1412. oelem = f->dir.elem;
  1413. f->dir.elem = vtstrdup(dir->elem);
  1414. }
  1415. if(strcmp(f->dir.uid, dir->uid) != 0){
  1416. vtfree(f->dir.uid);
  1417. f->dir.uid = vtstrdup(dir->uid);
  1418. }
  1419. if(strcmp(f->dir.gid, dir->gid) != 0){
  1420. vtfree(f->dir.gid);
  1421. f->dir.gid = vtstrdup(dir->gid);
  1422. }
  1423. if(strcmp(f->dir.mid, dir->mid) != 0){
  1424. vtfree(f->dir.mid);
  1425. f->dir.mid = vtstrdup(dir->mid);
  1426. }
  1427. f->dir.mtime = dir->mtime;
  1428. f->dir.atime = dir->atime;
  1429. mask = ~(ModeDir|ModeSnapshot);
  1430. f->dir.mode &= ~mask;
  1431. f->dir.mode |= mask & dir->mode;
  1432. f->dirty = 1;
  1433. if(filemetaflush(f, oelem) < 0){
  1434. vtfree(oelem);
  1435. goto Err; /* that sucks */
  1436. }
  1437. vtfree(oelem);
  1438. filemetaunlock(f);
  1439. fileunlock(f);
  1440. return 0;
  1441. Err:
  1442. filemetaunlock(f);
  1443. fileunlock(f);
  1444. return -1;
  1445. }
  1446. /*
  1447. * Set the qid space.
  1448. */
  1449. int
  1450. vacfilesetqidspace(VacFile *f, uint64_t offset, uint64_t max)
  1451. {
  1452. int ret;
  1453. if(filelock(f) < 0)
  1454. return -1;
  1455. if(f->source->mode != VtORDWR){
  1456. fileunlock(f);
  1457. werrstr(EReadOnly);
  1458. return -1;
  1459. }
  1460. filemetalock(f);
  1461. f->dir.qidspace = 1;
  1462. f->dir.qidoffset = offset;
  1463. f->dir.qidmax = max;
  1464. f->dirty = 1;
  1465. ret = filemetaflush(f, nil);
  1466. filemetaunlock(f);
  1467. fileunlock(f);
  1468. return ret;
  1469. }
  1470. /*
  1471. * Check that the file is empty, returning 0 if it is.
  1472. * Returns -1 on error (and not being empty is an error).
  1473. */
  1474. static int
  1475. filecheckempty(VacFile *f)
  1476. {
  1477. uint32_t i, n;
  1478. VtBlock *b;
  1479. MetaBlock mb;
  1480. VtFile *r;
  1481. r = f->msource;
  1482. n = (vtfilegetsize(r)+r->dsize-1)/r->dsize;
  1483. for(i=0; i<n; i++){
  1484. b = vtfileblock(r, i, VtOREAD);
  1485. if(b == nil)
  1486. return -1;
  1487. if(mbunpack(&mb, b->data, r->dsize) < 0)
  1488. goto Err;
  1489. if(mb.nindex > 0){
  1490. werrstr(ENotEmpty);
  1491. goto Err;
  1492. }
  1493. vtblockput(b);
  1494. }
  1495. return 0;
  1496. Err:
  1497. vtblockput(b);
  1498. return -1;
  1499. }
  1500. /*
  1501. * Remove the vac file f.
  1502. */
  1503. int
  1504. vacfileremove(VacFile *f)
  1505. {
  1506. VacFile *ff;
  1507. /* Cannot remove the root */
  1508. if(vacfileisroot(f)){
  1509. werrstr(ERoot);
  1510. return -1;
  1511. }
  1512. if(filelock(f) < 0)
  1513. return -1;
  1514. if(f->source->mode != VtORDWR){
  1515. werrstr(EReadOnly);
  1516. goto Err1;
  1517. }
  1518. if(vtfilelock2(f->source, f->msource, -1) < 0)
  1519. goto Err1;
  1520. if(vacfileisdir(f) && filecheckempty(f)<0)
  1521. goto Err;
  1522. for(ff=f->down; ff; ff=ff->next)
  1523. assert(ff->removed);
  1524. vtfileremove(f->source);
  1525. f->source = nil;
  1526. if(f->msource){
  1527. vtfileremove(f->msource);
  1528. f->msource = nil;
  1529. }
  1530. fileunlock(f);
  1531. if(filemetaremove(f) < 0)
  1532. return -1;
  1533. return 0;
  1534. Err:
  1535. vtfileunlock(f->source);
  1536. if(f->msource)
  1537. vtfileunlock(f->msource);
  1538. Err1:
  1539. fileunlock(f);
  1540. return -1;
  1541. }
  1542. /*
  1543. * Vac file system format.
  1544. */
  1545. static char EBadVacFormat[] = "bad format for vac file";
  1546. static VacFs *
  1547. vacfsalloc(VtConn *z, int bsize, int ncache, int mode)
  1548. {
  1549. VacFs *fs;
  1550. fs = vtmallocz(sizeof(VacFs));
  1551. fs->z = z;
  1552. fs->bsize = bsize;
  1553. fs->mode = mode;
  1554. fs->cache = vtcachealloc(z, bsize, ncache);
  1555. return fs;
  1556. }
  1557. static int
  1558. readscore(int fd, uint8_t score[VtScoreSize])
  1559. {
  1560. char buf[45], *pref;
  1561. int n;
  1562. n = readn(fd, buf, sizeof(buf)-1);
  1563. if(n < sizeof(buf)-1) {
  1564. werrstr("short read");
  1565. return -1;
  1566. }
  1567. buf[n] = 0;
  1568. if(vtparsescore(buf, &pref, score) < 0){
  1569. werrstr(EBadVacFormat);
  1570. return -1;
  1571. }
  1572. if(pref==nil || strcmp(pref, "vac") != 0) {
  1573. werrstr("not a vac file");
  1574. return -1;
  1575. }
  1576. return 0;
  1577. }
  1578. VacFs*
  1579. vacfsopen(VtConn *z, char *file, int mode, int ncache)
  1580. {
  1581. int fd;
  1582. uint8_t score[VtScoreSize];
  1583. char *prefix;
  1584. if(vtparsescore(file, &prefix, score) >= 0){
  1585. if(prefix == nil || strcmp(prefix, "vac") != 0){
  1586. werrstr("not a vac file");
  1587. return nil;
  1588. }
  1589. }else{
  1590. fd = open(file, OREAD);
  1591. if(fd < 0)
  1592. return nil;
  1593. if(readscore(fd, score) < 0){
  1594. close(fd);
  1595. return nil;
  1596. }
  1597. close(fd);
  1598. }
  1599. return vacfsopenscore(z, score, mode, ncache);
  1600. }
  1601. VacFs*
  1602. vacfsopenscore(VtConn *z, uint8_t *score, int mode, int ncache)
  1603. {
  1604. VacFs *fs;
  1605. int n;
  1606. VtRoot rt;
  1607. uint8_t buf[VtRootSize];
  1608. VacFile *root;
  1609. VtFile *r;
  1610. VtEntry e;
  1611. n = vtread(z, score, VtRootType, buf, VtRootSize);
  1612. if(n < 0)
  1613. return nil;
  1614. if(n != VtRootSize){
  1615. werrstr("vtread on root too short");
  1616. return nil;
  1617. }
  1618. if(vtrootunpack(&rt, buf) < 0)
  1619. return nil;
  1620. if(strcmp(rt.type, "vac") != 0) {
  1621. werrstr("not a vac root");
  1622. return nil;
  1623. }
  1624. fs = vacfsalloc(z, rt.blocksize, ncache, mode);
  1625. memmove(fs->score, score, VtScoreSize);
  1626. fs->mode = mode;
  1627. memmove(e.score, rt.score, VtScoreSize);
  1628. e.gen = 0;
  1629. e.psize = rt.blocksize;
  1630. e.dsize = rt.blocksize;
  1631. e.type = VtDirType;
  1632. e.flags = VtEntryActive;
  1633. e.size = 3*VtEntrySize;
  1634. root = nil;
  1635. if((r = vtfileopenroot(fs->cache, &e)) == nil)
  1636. goto Err;
  1637. if(debug)
  1638. fprint(2, "r %p\n", r);
  1639. root = _vacfileroot(fs, r);
  1640. if(debug)
  1641. fprint(2, "root %p\n", root);
  1642. vtfileclose(r);
  1643. if(root == nil)
  1644. goto Err;
  1645. fs->root = root;
  1646. return fs;
  1647. Err:
  1648. if(root)
  1649. vacfiledecref(root);
  1650. vacfsclose(fs);
  1651. return nil;
  1652. }
  1653. int
  1654. vacfsmode(VacFs *fs)
  1655. {
  1656. return fs->mode;
  1657. }
  1658. VacFile*
  1659. vacfsgetroot(VacFs *fs)
  1660. {
  1661. return vacfileincref(fs->root);
  1662. }
  1663. int
  1664. vacfsgetblocksize(VacFs *fs)
  1665. {
  1666. return fs->bsize;
  1667. }
  1668. int
  1669. vacfsgetscore(VacFs *fs, uint8_t *score)
  1670. {
  1671. memmove(score, fs->score, VtScoreSize);
  1672. return 0;
  1673. }
  1674. int
  1675. _vacfsnextqid(VacFs *fs, uint64_t *qid)
  1676. {
  1677. ++fs->qid;
  1678. *qid = fs->qid;
  1679. return 0;
  1680. }
  1681. void
  1682. vacfsjumpqid(VacFs *fs, uint64_t step)
  1683. {
  1684. fs->qid += step;
  1685. }
  1686. /*
  1687. * Set *maxqid to the maximum qid expected in this file system.
  1688. * In newer vac archives, the maximum qid is stored in the
  1689. * qidspace VacDir annotation. In older vac archives, the root
  1690. * got created last, so it had the maximum qid.
  1691. */
  1692. int
  1693. vacfsgetmaxqid(VacFs *fs, uint64_t *maxqid)
  1694. {
  1695. VacDir vd;
  1696. if(vacfilegetdir(fs->root, &vd) < 0)
  1697. return -1;
  1698. if(vd.qidspace)
  1699. *maxqid = vd.qidmax;
  1700. else
  1701. *maxqid = vd.qid;
  1702. vdcleanup(&vd);
  1703. return 0;
  1704. }
  1705. void
  1706. vacfsclose(VacFs *fs)
  1707. {
  1708. if(fs->root)
  1709. vacfiledecref(fs->root);
  1710. fs->root = nil;
  1711. vtcachefree(fs->cache);
  1712. vtfree(fs);
  1713. }
  1714. /*
  1715. * Create a fresh vac fs.
  1716. */
  1717. VacFs *
  1718. vacfscreate(VtConn *z, int bsize, int ncache)
  1719. {
  1720. VacFs *fs;
  1721. VtFile *f;
  1722. uint8_t buf[VtEntrySize], metascore[VtScoreSize];
  1723. VtEntry e;
  1724. VtBlock *b;
  1725. MetaBlock mb;
  1726. VacDir vd;
  1727. MetaEntry me;
  1728. int psize;
  1729. int mbsize;
  1730. if((fs = vacfsalloc(z, bsize, ncache, VtORDWR)) == nil)
  1731. return nil;
  1732. /*
  1733. * Fake up an empty vac fs.
  1734. */
  1735. psize = bsize;
  1736. f = vtfilecreateroot(fs->cache, psize, bsize, VtDirType);
  1737. vtfilelock(f, VtORDWR);
  1738. /* Metablocks can't be too big -- they have 16-bit offsets in them. */
  1739. mbsize = bsize;
  1740. if(mbsize >= 56*1024)
  1741. mbsize = 56*1024;
  1742. /* Write metablock containing root directory VacDir. */
  1743. b = vtcacheallocblock(fs->cache, VtDataType);
  1744. mbinit(&mb, b->data, mbsize, mbsize/BytesPerEntry);
  1745. memset(&vd, 0, sizeof vd);
  1746. vd.elem = "/";
  1747. vd.mode = 0777|ModeDir;
  1748. vd.uid = "vac";
  1749. vd.gid = "vac";
  1750. vd.mid = "";
  1751. me.size = vdsize(&vd, VacDirVersion);
  1752. me.p = mballoc(&mb, me.size);
  1753. vdpack(&vd, &me, VacDirVersion);
  1754. mbinsert(&mb, 0, &me);
  1755. mbpack(&mb);
  1756. vtblockwrite(b);
  1757. memmove(metascore, b->score, VtScoreSize);
  1758. vtblockput(b);
  1759. /* First entry: empty venti directory stream. */
  1760. memset(&e, 0, sizeof e);
  1761. e.flags = VtEntryActive;
  1762. e.psize = psize;
  1763. e.dsize = bsize;
  1764. e.type = VtDirType;
  1765. memmove(e.score, vtzeroscore, VtScoreSize);
  1766. vtentrypack(&e, buf, 0);
  1767. vtfilewrite(f, buf, VtEntrySize, 0);
  1768. /* Second entry: empty metadata stream. */
  1769. e.type = VtDataType;
  1770. e.dsize = mbsize;
  1771. vtentrypack(&e, buf, 0);
  1772. vtfilewrite(f, buf, VtEntrySize, VtEntrySize);
  1773. /* Third entry: metadata stream with root directory. */
  1774. memmove(e.score, metascore, VtScoreSize);
  1775. e.size = mbsize;
  1776. vtentrypack(&e, buf, 0);
  1777. vtfilewrite(f, buf, VtEntrySize, VtEntrySize*2);
  1778. vtfileflush(f);
  1779. vtfileunlock(f);
  1780. /* Now open it as a vac fs. */
  1781. fs->root = _vacfileroot(fs, f);
  1782. if(fs->root == nil){
  1783. werrstr("vacfileroot: %r");
  1784. vacfsclose(fs);
  1785. return nil;
  1786. }
  1787. return fs;
  1788. }
  1789. int
  1790. vacfssync(VacFs *fs)
  1791. {
  1792. uint8_t buf[1024];
  1793. VtEntry e;
  1794. VtFile *f;
  1795. VtRoot root;
  1796. /* Sync the entire vacfs to disk. */
  1797. if(vacfileflush(fs->root, 1) < 0)
  1798. return -1;
  1799. if(vtfilelock(fs->root->up->msource, -1) < 0)
  1800. return -1;
  1801. if(vtfileflush(fs->root->up->msource) < 0){
  1802. vtfileunlock(fs->root->up->msource);
  1803. return -1;
  1804. }
  1805. vtfileunlock(fs->root->up->msource);
  1806. /* Prepare the dir stream for the root block. */
  1807. if(getentry(fs->root->source, &e) < 0)
  1808. return -1;
  1809. vtentrypack(&e, buf, 0);
  1810. if(getentry(fs->root->msource, &e) < 0)
  1811. return -1;
  1812. vtentrypack(&e, buf, 1);
  1813. if(getentry(fs->root->up->msource, &e) < 0)
  1814. return -1;
  1815. vtentrypack(&e, buf, 2);
  1816. f = vtfilecreateroot(fs->cache, fs->bsize, fs->bsize, VtDirType);
  1817. vtfilelock(f, VtORDWR);
  1818. if(vtfilewrite(f, buf, 3*VtEntrySize, 0) < 0
  1819. || vtfileflush(f) < 0){
  1820. vtfileunlock(f);
  1821. vtfileclose(f);
  1822. return -1;
  1823. }
  1824. vtfileunlock(f);
  1825. if(getentry(f, &e) < 0){
  1826. vtfileclose(f);
  1827. return -1;
  1828. }
  1829. vtfileclose(f);
  1830. /* Build a root block. */
  1831. memset(&root, 0, sizeof root);
  1832. strcpy(root.type, "vac");
  1833. strcpy(root.name, fs->name);
  1834. memmove(root.score, e.score, VtScoreSize);
  1835. root.blocksize = fs->bsize;
  1836. memmove(root.prev, fs->score, VtScoreSize);
  1837. vtrootpack(&root, buf);
  1838. if(vtwrite(fs->z, fs->score, VtRootType, buf, VtRootSize) < 0){
  1839. werrstr("writing root: %r");
  1840. return -1;
  1841. }
  1842. if(vtsync(fs->z) < 0)
  1843. return -1;
  1844. return 0;
  1845. }
  1846. int
  1847. vacfiledsize(VacFile *f)
  1848. {
  1849. VtEntry e;
  1850. if(vacfilegetentries(f,&e,nil) < 0)
  1851. return -1;
  1852. return e.dsize;
  1853. }
  1854. /*
  1855. * Does block b of f have the same SHA1 hash as the n bytes at buf?
  1856. */
  1857. int
  1858. sha1matches(VacFile *f, uint32_t b, uint8_t *buf, int n)
  1859. {
  1860. uint8_t fscore[VtScoreSize];
  1861. uint8_t bufscore[VtScoreSize];
  1862. if(vacfileblockscore(f, b, fscore) < 0)
  1863. return 0;
  1864. n = vtzerotruncate(VtDataType, buf, n);
  1865. sha1(buf, n, bufscore, nil);
  1866. if(memcmp(bufscore, fscore, VtScoreSize) == 0)
  1867. return 1;
  1868. return 0;
  1869. }