Blame


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