1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro #include "9.h" /* for consPrint */
3 6f4d00ee 2013-09-23 0intro #include "dat.h"
4 6f4d00ee 2013-09-23 0intro #include "fns.h"
5 6f4d00ee 2013-09-23 0intro #include "error.h"
8 6f4d00ee 2013-09-23 0intro * locking order is upwards. A thread can hold the lock for a File
9 6f4d00ee 2013-09-23 0intro * and then acquire the lock of its parent
12 6f4d00ee 2013-09-23 0intro struct File {
13 6f4d00ee 2013-09-23 0intro Fs *fs; /* immutable */
15 6f4d00ee 2013-09-23 0intro /* meta data for file: protected by the lk in the parent */
16 6f4d00ee 2013-09-23 0intro int ref; /* holds this data structure up */
18 6f4d00ee 2013-09-23 0intro int partial; /* file was never really open */
19 6f4d00ee 2013-09-23 0intro int removed; /* file has been removed */
20 6f4d00ee 2013-09-23 0intro int dirty; /* dir is dirty with respect to meta data in block */
21 6f4d00ee 2013-09-23 0intro u32int boff; /* block offset within msource for this file's meta data */
23 6f4d00ee 2013-09-23 0intro DirEntry dir; /* meta data for this file, including component name */
25 6f4d00ee 2013-09-23 0intro File *up; /* parent file (directory) */
26 6f4d00ee 2013-09-23 0intro File *next; /* sibling */
28 6f4d00ee 2013-09-23 0intro /* data for file */
29 4b576658 2013-09-23 0intro RWLock lk; /* lock for the following */
30 6f4d00ee 2013-09-23 0intro Source *source;
31 6f4d00ee 2013-09-23 0intro Source *msource; /* for directories: meta data for children */
32 6f4d00ee 2013-09-23 0intro File *down; /* children */
35 6f4d00ee 2013-09-23 0intro int issnapshot;
38 6f4d00ee 2013-09-23 0intro static int fileMetaFlush2(File*, char*);
39 6f4d00ee 2013-09-23 0intro static u32int fileMetaAlloc(File*, DirEntry*, u32int);
40 6f4d00ee 2013-09-23 0intro static int fileRLock(File*);
41 6f4d00ee 2013-09-23 0intro static void fileRUnlock(File*);
42 6f4d00ee 2013-09-23 0intro static int fileLock(File*);
43 6f4d00ee 2013-09-23 0intro static void fileUnlock(File*);
44 6f4d00ee 2013-09-23 0intro static void fileMetaLock(File*);
45 6f4d00ee 2013-09-23 0intro static void fileMetaUnlock(File*);
46 6f4d00ee 2013-09-23 0intro static void fileRAccess(File*);
47 6f4d00ee 2013-09-23 0intro static void fileWAccess(File*, char*);
49 6f4d00ee 2013-09-23 0intro static File *
50 6f4d00ee 2013-09-23 0intro fileAlloc(Fs *fs)
54 4b576658 2013-09-23 0intro f = vtmallocz(sizeof(File));
55 6f4d00ee 2013-09-23 0intro f->ref = 1;
56 6f4d00ee 2013-09-23 0intro f->fs = fs;
57 6f4d00ee 2013-09-23 0intro f->boff = NilBlock;
58 6f4d00ee 2013-09-23 0intro f->mode = fs->mode;
62 6f4d00ee 2013-09-23 0intro static void
63 6f4d00ee 2013-09-23 0intro fileFree(File *f)
65 6f4d00ee 2013-09-23 0intro sourceClose(f->source);
66 6f4d00ee 2013-09-23 0intro sourceClose(f->msource);
67 6f4d00ee 2013-09-23 0intro deCleanup(&f->dir);
69 6f4d00ee 2013-09-23 0intro memset(f, ~0, sizeof(File));
70 4b576658 2013-09-23 0intro vtfree(f);
74 6f4d00ee 2013-09-23 0intro * the file is locked already
75 6f4d00ee 2013-09-23 0intro * f->msource is unlocked
77 6f4d00ee 2013-09-23 0intro static File *
78 6f4d00ee 2013-09-23 0intro dirLookup(File *f, char *elem)
81 6f4d00ee 2013-09-23 0intro MetaBlock mb;
82 6f4d00ee 2013-09-23 0intro MetaEntry me;
84 6f4d00ee 2013-09-23 0intro Source *meta;
86 6f4d00ee 2013-09-23 0intro u32int bo, nb;
88 6f4d00ee 2013-09-23 0intro meta = f->msource;
90 6f4d00ee 2013-09-23 0intro if(!sourceLock(meta, -1))
91 6f4d00ee 2013-09-23 0intro return nil;
92 6f4d00ee 2013-09-23 0intro nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize;
93 6f4d00ee 2013-09-23 0intro for(bo=0; bo<nb; bo++){
94 6f4d00ee 2013-09-23 0intro b = sourceBlock(meta, bo, OReadOnly);
95 6f4d00ee 2013-09-23 0intro if(b == nil)
97 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, meta->dsize))
99 6f4d00ee 2013-09-23 0intro if(mbSearch(&mb, elem, &i, &me)){
100 6f4d00ee 2013-09-23 0intro ff = fileAlloc(f->fs);
101 6f4d00ee 2013-09-23 0intro if(!deUnpack(&ff->dir, &me)){
102 6f4d00ee 2013-09-23 0intro fileFree(ff);
103 6f4d00ee 2013-09-23 0intro goto Err;
105 6f4d00ee 2013-09-23 0intro sourceUnlock(meta);
106 6f4d00ee 2013-09-23 0intro blockPut(b);
107 6f4d00ee 2013-09-23 0intro ff->boff = bo;
108 6f4d00ee 2013-09-23 0intro ff->mode = f->mode;
109 6f4d00ee 2013-09-23 0intro ff->issnapshot = f->issnapshot;
110 6f4d00ee 2013-09-23 0intro return ff;
113 6f4d00ee 2013-09-23 0intro blockPut(b);
116 4b576658 2013-09-23 0intro werrstr(ENoFile);
117 6f4d00ee 2013-09-23 0intro /* fall through */
119 6f4d00ee 2013-09-23 0intro sourceUnlock(meta);
120 6f4d00ee 2013-09-23 0intro blockPut(b);
121 6f4d00ee 2013-09-23 0intro return nil;
125 6f4d00ee 2013-09-23 0intro fileRoot(Source *r)
127 6f4d00ee 2013-09-23 0intro Block *b;
128 6f4d00ee 2013-09-23 0intro Source *r0, *r1, *r2;
129 6f4d00ee 2013-09-23 0intro MetaBlock mb;
130 6f4d00ee 2013-09-23 0intro MetaEntry me;
131 6f4d00ee 2013-09-23 0intro File *root, *mr;
135 6f4d00ee 2013-09-23 0intro root = nil;
136 6f4d00ee 2013-09-23 0intro mr = nil;
137 6f4d00ee 2013-09-23 0intro r1 = nil;
138 6f4d00ee 2013-09-23 0intro r2 = nil;
140 6f4d00ee 2013-09-23 0intro fs = r->fs;
141 6f4d00ee 2013-09-23 0intro if(!sourceLock(r, -1))
142 6f4d00ee 2013-09-23 0intro return nil;
143 6f4d00ee 2013-09-23 0intro r0 = sourceOpen(r, 0, fs->mode, 0);
144 6f4d00ee 2013-09-23 0intro if(r0 == nil)
145 6f4d00ee 2013-09-23 0intro goto Err;
146 6f4d00ee 2013-09-23 0intro r1 = sourceOpen(r, 1, fs->mode, 0);
147 6f4d00ee 2013-09-23 0intro if(r1 == nil)
148 6f4d00ee 2013-09-23 0intro goto Err;
149 6f4d00ee 2013-09-23 0intro r2 = sourceOpen(r, 2, fs->mode, 0);
150 6f4d00ee 2013-09-23 0intro if(r2 == nil)
151 6f4d00ee 2013-09-23 0intro goto Err;
153 6f4d00ee 2013-09-23 0intro mr = fileAlloc(fs);
154 6f4d00ee 2013-09-23 0intro mr->msource = r2;
155 6f4d00ee 2013-09-23 0intro r2 = nil;
157 6f4d00ee 2013-09-23 0intro root = fileAlloc(fs);
158 6f4d00ee 2013-09-23 0intro root->boff = 0;
159 6f4d00ee 2013-09-23 0intro root->up = mr;
160 6f4d00ee 2013-09-23 0intro root->source = r0;
161 6f4d00ee 2013-09-23 0intro r0->file = root; /* point back to source */
162 6f4d00ee 2013-09-23 0intro r0 = nil;
163 6f4d00ee 2013-09-23 0intro root->msource = r1;
164 6f4d00ee 2013-09-23 0intro r1 = nil;
166 6f4d00ee 2013-09-23 0intro mr->down = root;
168 6f4d00ee 2013-09-23 0intro if(!sourceLock(mr->msource, -1))
169 6f4d00ee 2013-09-23 0intro goto Err;
170 6f4d00ee 2013-09-23 0intro b = sourceBlock(mr->msource, 0, OReadOnly);
171 6f4d00ee 2013-09-23 0intro sourceUnlock(mr->msource);
172 6f4d00ee 2013-09-23 0intro if(b == nil)
173 6f4d00ee 2013-09-23 0intro goto Err;
175 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, mr->msource->dsize))
176 6f4d00ee 2013-09-23 0intro goto Err;
178 6f4d00ee 2013-09-23 0intro meUnpack(&me, &mb, 0);
179 6f4d00ee 2013-09-23 0intro if(!deUnpack(&root->dir, &me))
180 6f4d00ee 2013-09-23 0intro goto Err;
181 6f4d00ee 2013-09-23 0intro blockPut(b);
182 6f4d00ee 2013-09-23 0intro sourceUnlock(r);
183 6f4d00ee 2013-09-23 0intro fileRAccess(root);
185 6f4d00ee 2013-09-23 0intro return root;
187 6f4d00ee 2013-09-23 0intro blockPut(b);
189 6f4d00ee 2013-09-23 0intro sourceClose(r0);
191 6f4d00ee 2013-09-23 0intro sourceClose(r1);
193 6f4d00ee 2013-09-23 0intro sourceClose(r2);
195 6f4d00ee 2013-09-23 0intro fileFree(mr);
197 6f4d00ee 2013-09-23 0intro fileFree(root);
198 6f4d00ee 2013-09-23 0intro sourceUnlock(r);
200 6f4d00ee 2013-09-23 0intro return nil;
203 6f4d00ee 2013-09-23 0intro static Source *
204 6f4d00ee 2013-09-23 0intro fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode,
205 6f4d00ee 2013-09-23 0intro int issnapshot)
207 6f4d00ee 2013-09-23 0intro char *rname, *fname;
208 6f4d00ee 2013-09-23 0intro Source *r;
210 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, mode))
211 6f4d00ee 2013-09-23 0intro return nil;
212 6f4d00ee 2013-09-23 0intro r = sourceOpen(f->source, offset, mode, issnapshot);
213 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
214 6f4d00ee 2013-09-23 0intro if(r == nil)
215 6f4d00ee 2013-09-23 0intro return nil;
216 6f4d00ee 2013-09-23 0intro if(r->gen != gen){
217 4b576658 2013-09-23 0intro werrstr(ERemoved);
218 6f4d00ee 2013-09-23 0intro goto Err;
220 6f4d00ee 2013-09-23 0intro if(r->dir != dir && r->mode != -1){
221 6f4d00ee 2013-09-23 0intro /* this hasn't been as useful as we hoped it would be. */
222 6f4d00ee 2013-09-23 0intro rname = sourceName(r);
223 6f4d00ee 2013-09-23 0intro fname = fileName(f);
224 6f4d00ee 2013-09-23 0intro consPrint("%s: source %s for file %s: fileOpenSource: "
225 6f4d00ee 2013-09-23 0intro "dir mismatch %d %d\n",
226 6f4d00ee 2013-09-23 0intro f->source->fs->name, rname, fname, r->dir, dir);
227 6f4d00ee 2013-09-23 0intro free(rname);
228 6f4d00ee 2013-09-23 0intro free(fname);
230 4b576658 2013-09-23 0intro werrstr(EBadMeta);
231 6f4d00ee 2013-09-23 0intro goto Err;
233 6f4d00ee 2013-09-23 0intro return r;
235 6f4d00ee 2013-09-23 0intro sourceClose(r);
236 6f4d00ee 2013-09-23 0intro return nil;
240 6f4d00ee 2013-09-23 0intro _fileWalk(File *f, char *elem, int partial)
242 6f4d00ee 2013-09-23 0intro File *ff;
244 6f4d00ee 2013-09-23 0intro fileRAccess(f);
246 6f4d00ee 2013-09-23 0intro if(elem[0] == 0){
247 4b576658 2013-09-23 0intro werrstr(EBadPath);
248 6f4d00ee 2013-09-23 0intro return nil;
251 6f4d00ee 2013-09-23 0intro if(!fileIsDir(f)){
252 4b576658 2013-09-23 0intro werrstr(ENotDir);
253 6f4d00ee 2013-09-23 0intro return nil;
256 6f4d00ee 2013-09-23 0intro if(strcmp(elem, ".") == 0){
257 6f4d00ee 2013-09-23 0intro return fileIncRef(f);
260 6f4d00ee 2013-09-23 0intro if(strcmp(elem, "..") == 0){
261 6f4d00ee 2013-09-23 0intro if(fileIsRoot(f))
262 6f4d00ee 2013-09-23 0intro return fileIncRef(f);
263 6f4d00ee 2013-09-23 0intro return fileIncRef(f->up);
266 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
267 6f4d00ee 2013-09-23 0intro return nil;
269 6f4d00ee 2013-09-23 0intro for(ff = f->down; ff; ff=ff->next){
270 6f4d00ee 2013-09-23 0intro if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
271 6f4d00ee 2013-09-23 0intro ff->ref++;
272 6f4d00ee 2013-09-23 0intro goto Exit;
276 6f4d00ee 2013-09-23 0intro ff = dirLookup(f, elem);
277 6f4d00ee 2013-09-23 0intro if(ff == nil)
278 6f4d00ee 2013-09-23 0intro goto Err;
280 6f4d00ee 2013-09-23 0intro if(ff->dir.mode & ModeSnapshot){
281 6f4d00ee 2013-09-23 0intro ff->mode = OReadOnly;
282 6f4d00ee 2013-09-23 0intro ff->issnapshot = 1;
285 6f4d00ee 2013-09-23 0intro if(partial){
287 6f4d00ee 2013-09-23 0intro * Do nothing. We're opening this file only so we can clri it.
288 6f4d00ee 2013-09-23 0intro * Usually the sources can't be opened, hence we won't even bother.
289 6f4d00ee 2013-09-23 0intro * Be VERY careful with the returned file. If you hand it to a routine
290 6f4d00ee 2013-09-23 0intro * expecting ff->source and/or ff->msource to be non-nil, we're
291 6f4d00ee 2013-09-23 0intro * likely to dereference nil. FileClri should be the only routine
292 6f4d00ee 2013-09-23 0intro * setting partial.
294 6f4d00ee 2013-09-23 0intro ff->partial = 1;
295 6f4d00ee 2013-09-23 0intro }else if(ff->dir.mode & ModeDir){
296 6f4d00ee 2013-09-23 0intro ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
297 6f4d00ee 2013-09-23 0intro 1, ff->mode, ff->issnapshot);
298 6f4d00ee 2013-09-23 0intro ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen,
299 6f4d00ee 2013-09-23 0intro 0, ff->mode, ff->issnapshot);
300 6f4d00ee 2013-09-23 0intro if(ff->source == nil || ff->msource == nil)
301 6f4d00ee 2013-09-23 0intro goto Err;
303 6f4d00ee 2013-09-23 0intro ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
304 6f4d00ee 2013-09-23 0intro 0, ff->mode, ff->issnapshot);
305 6f4d00ee 2013-09-23 0intro if(ff->source == nil)
306 6f4d00ee 2013-09-23 0intro goto Err;
309 6f4d00ee 2013-09-23 0intro /* link in and up parent ref count */
310 6f4d00ee 2013-09-23 0intro if (ff->source)
311 6f4d00ee 2013-09-23 0intro ff->source->file = ff; /* point back */
312 6f4d00ee 2013-09-23 0intro ff->next = f->down;
313 6f4d00ee 2013-09-23 0intro f->down = ff;
314 6f4d00ee 2013-09-23 0intro ff->up = f;
315 6f4d00ee 2013-09-23 0intro fileIncRef(f);
317 6f4d00ee 2013-09-23 0intro fileUnlock(f);
318 6f4d00ee 2013-09-23 0intro return ff;
320 6f4d00ee 2013-09-23 0intro fileUnlock(f);
321 6f4d00ee 2013-09-23 0intro if(ff != nil)
322 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
323 6f4d00ee 2013-09-23 0intro return nil;
327 6f4d00ee 2013-09-23 0intro fileWalk(File *f, char *elem)
329 6f4d00ee 2013-09-23 0intro return _fileWalk(f, elem, 0);
333 6f4d00ee 2013-09-23 0intro _fileOpen(Fs *fs, char *path, int partial)
335 6f4d00ee 2013-09-23 0intro File *f, *ff;
336 6f4d00ee 2013-09-23 0intro char *p, elem[VtMaxStringSize], *opath;
339 6f4d00ee 2013-09-23 0intro f = fs->file;
340 6f4d00ee 2013-09-23 0intro fileIncRef(f);
341 6f4d00ee 2013-09-23 0intro opath = path;
342 6f4d00ee 2013-09-23 0intro while(*path != 0){
343 6f4d00ee 2013-09-23 0intro for(p = path; *p && *p != '/'; p++)
345 6f4d00ee 2013-09-23 0intro n = p - path;
346 6f4d00ee 2013-09-23 0intro if(n > 0){
347 6f4d00ee 2013-09-23 0intro if(n > VtMaxStringSize){
348 4b576658 2013-09-23 0intro werrstr("%s: element too long", EBadPath);
349 6f4d00ee 2013-09-23 0intro goto Err;
351 6f4d00ee 2013-09-23 0intro memmove(elem, path, n);
352 6f4d00ee 2013-09-23 0intro elem[n] = 0;
353 6f4d00ee 2013-09-23 0intro ff = _fileWalk(f, elem, partial && *p=='\0');
354 6f4d00ee 2013-09-23 0intro if(ff == nil){
355 4b576658 2013-09-23 0intro werrstr("%.*s: %r", utfnlen(opath, p-opath),
357 6f4d00ee 2013-09-23 0intro goto Err;
359 6f4d00ee 2013-09-23 0intro fileDecRef(f);
362 6f4d00ee 2013-09-23 0intro if(*p == '/')
364 6f4d00ee 2013-09-23 0intro path = p;
366 6f4d00ee 2013-09-23 0intro return f;
368 6f4d00ee 2013-09-23 0intro fileDecRef(f);
369 6f4d00ee 2013-09-23 0intro return nil;
373 6f4d00ee 2013-09-23 0intro fileOpen(Fs *fs, char *path)
375 6f4d00ee 2013-09-23 0intro return _fileOpen(fs, path, 0);
378 6f4d00ee 2013-09-23 0intro static void
379 6f4d00ee 2013-09-23 0intro fileSetTmp(File *f, int istmp)
383 6f4d00ee 2013-09-23 0intro Source *r;
385 6f4d00ee 2013-09-23 0intro for(i=0; i<2; i++){
387 6f4d00ee 2013-09-23 0intro r = f->source;
389 6f4d00ee 2013-09-23 0intro r = f->msource;
390 6f4d00ee 2013-09-23 0intro if(r == nil)
391 6f4d00ee 2013-09-23 0intro continue;
392 6f4d00ee 2013-09-23 0intro if(!sourceGetEntry(r, &e)){
393 6f4d00ee 2013-09-23 0intro fprint(2, "sourceGetEntry failed (cannot happen): %r\n");
394 6f4d00ee 2013-09-23 0intro continue;
396 6f4d00ee 2013-09-23 0intro if(istmp)
397 6f4d00ee 2013-09-23 0intro e.flags |= VtEntryNoArchive;
399 6f4d00ee 2013-09-23 0intro e.flags &= ~VtEntryNoArchive;
400 6f4d00ee 2013-09-23 0intro if(!sourceSetEntry(r, &e)){
401 6f4d00ee 2013-09-23 0intro fprint(2, "sourceSetEntry failed (cannot happen): %r\n");
402 6f4d00ee 2013-09-23 0intro continue;
408 6f4d00ee 2013-09-23 0intro fileCreate(File *f, char *elem, ulong mode, char *uid)
410 6f4d00ee 2013-09-23 0intro File *ff;
411 6f4d00ee 2013-09-23 0intro DirEntry *dir;
412 6f4d00ee 2013-09-23 0intro Source *pr, *r, *mr;
413 6f4d00ee 2013-09-23 0intro int isdir;
415 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
416 6f4d00ee 2013-09-23 0intro return nil;
419 6f4d00ee 2013-09-23 0intro mr = nil;
420 6f4d00ee 2013-09-23 0intro for(ff = f->down; ff; ff=ff->next){
421 6f4d00ee 2013-09-23 0intro if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
422 6f4d00ee 2013-09-23 0intro ff = nil;
423 4b576658 2013-09-23 0intro werrstr(EExists);
424 6f4d00ee 2013-09-23 0intro goto Err1;
428 6f4d00ee 2013-09-23 0intro ff = dirLookup(f, elem);
429 6f4d00ee 2013-09-23 0intro if(ff != nil){
430 4b576658 2013-09-23 0intro werrstr(EExists);
431 6f4d00ee 2013-09-23 0intro goto Err1;
434 6f4d00ee 2013-09-23 0intro pr = f->source;
435 6f4d00ee 2013-09-23 0intro if(pr->mode != OReadWrite){
436 4b576658 2013-09-23 0intro werrstr(EReadOnly);
437 6f4d00ee 2013-09-23 0intro goto Err1;
440 6f4d00ee 2013-09-23 0intro if(!sourceLock2(f->source, f->msource, -1))
441 6f4d00ee 2013-09-23 0intro goto Err1;
443 6f4d00ee 2013-09-23 0intro ff = fileAlloc(f->fs);
444 6f4d00ee 2013-09-23 0intro isdir = mode & ModeDir;
446 6f4d00ee 2013-09-23 0intro r = sourceCreate(pr, pr->dsize, isdir, 0);
447 6f4d00ee 2013-09-23 0intro if(r == nil)
448 6f4d00ee 2013-09-23 0intro goto Err;
449 6f4d00ee 2013-09-23 0intro if(isdir){
450 6f4d00ee 2013-09-23 0intro mr = sourceCreate(pr, pr->dsize, 0, r->offset);
451 6f4d00ee 2013-09-23 0intro if(mr == nil)
452 6f4d00ee 2013-09-23 0intro goto Err;
455 6f4d00ee 2013-09-23 0intro dir = &ff->dir;
456 4b576658 2013-09-23 0intro dir->elem = vtstrdup(elem);
457 6f4d00ee 2013-09-23 0intro dir->entry = r->offset;
458 6f4d00ee 2013-09-23 0intro dir->gen = r->gen;
459 6f4d00ee 2013-09-23 0intro if(isdir){
460 6f4d00ee 2013-09-23 0intro dir->mentry = mr->offset;
461 6f4d00ee 2013-09-23 0intro dir->mgen = mr->gen;
463 6f4d00ee 2013-09-23 0intro dir->size = 0;
464 6f4d00ee 2013-09-23 0intro if(!fsNextQid(f->fs, &dir->qid))
465 6f4d00ee 2013-09-23 0intro goto Err;
466 4b576658 2013-09-23 0intro dir->uid = vtstrdup(uid);
467 4b576658 2013-09-23 0intro dir->gid = vtstrdup(f->dir.gid);
468 4b576658 2013-09-23 0intro dir->mid = vtstrdup(uid);
469 6f4d00ee 2013-09-23 0intro dir->mtime = time(0L);
470 6f4d00ee 2013-09-23 0intro dir->mcount = 0;
471 6f4d00ee 2013-09-23 0intro dir->ctime = dir->mtime;
472 6f4d00ee 2013-09-23 0intro dir->atime = dir->mtime;
473 6f4d00ee 2013-09-23 0intro dir->mode = mode;
475 6f4d00ee 2013-09-23 0intro ff->boff = fileMetaAlloc(f, dir, 0);
476 6f4d00ee 2013-09-23 0intro if(ff->boff == NilBlock)
477 6f4d00ee 2013-09-23 0intro goto Err;
479 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
480 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
482 6f4d00ee 2013-09-23 0intro ff->source = r;
483 6f4d00ee 2013-09-23 0intro r->file = ff; /* point back */
484 6f4d00ee 2013-09-23 0intro ff->msource = mr;
486 6f4d00ee 2013-09-23 0intro if(mode&ModeTemporary){
487 6f4d00ee 2013-09-23 0intro if(!sourceLock2(r, mr, -1))
488 6f4d00ee 2013-09-23 0intro goto Err1;
489 6f4d00ee 2013-09-23 0intro fileSetTmp(ff, 1);
490 6f4d00ee 2013-09-23 0intro sourceUnlock(r);
492 6f4d00ee 2013-09-23 0intro sourceUnlock(mr);
495 6f4d00ee 2013-09-23 0intro /* committed */
497 6f4d00ee 2013-09-23 0intro /* link in and up parent ref count */
498 6f4d00ee 2013-09-23 0intro ff->next = f->down;
499 6f4d00ee 2013-09-23 0intro f->down = ff;
500 6f4d00ee 2013-09-23 0intro ff->up = f;
501 6f4d00ee 2013-09-23 0intro fileIncRef(f);
503 6f4d00ee 2013-09-23 0intro fileWAccess(f, uid);
505 6f4d00ee 2013-09-23 0intro fileUnlock(f);
506 6f4d00ee 2013-09-23 0intro return ff;
509 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
510 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
513 6f4d00ee 2013-09-23 0intro sourceLock(r, -1);
514 6f4d00ee 2013-09-23 0intro sourceRemove(r);
517 6f4d00ee 2013-09-23 0intro sourceLock(mr, -1);
518 6f4d00ee 2013-09-23 0intro sourceRemove(mr);
521 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
522 6f4d00ee 2013-09-23 0intro fileUnlock(f);
523 6f4d00ee 2013-09-23 0intro return 0;
527 6f4d00ee 2013-09-23 0intro fileRead(File *f, void *buf, int cnt, vlong offset)
529 6f4d00ee 2013-09-23 0intro Source *s;
530 6f4d00ee 2013-09-23 0intro uvlong size;
531 6f4d00ee 2013-09-23 0intro u32int bn;
532 6f4d00ee 2013-09-23 0intro int off, dsize, n, nn;
533 6f4d00ee 2013-09-23 0intro Block *b;
534 6f4d00ee 2013-09-23 0intro uchar *p;
536 6f4d00ee 2013-09-23 0intro if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
538 6f4d00ee 2013-09-23 0intro if(!fileRLock(f))
539 6f4d00ee 2013-09-23 0intro return -1;
541 6f4d00ee 2013-09-23 0intro if(offset < 0){
542 4b576658 2013-09-23 0intro werrstr(EBadOffset);
543 6f4d00ee 2013-09-23 0intro goto Err1;
546 6f4d00ee 2013-09-23 0intro fileRAccess(f);
548 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, OReadOnly))
549 6f4d00ee 2013-09-23 0intro goto Err1;
551 6f4d00ee 2013-09-23 0intro s = f->source;
552 6f4d00ee 2013-09-23 0intro dsize = s->dsize;
553 6f4d00ee 2013-09-23 0intro size = sourceGetSize(s);
555 6f4d00ee 2013-09-23 0intro if(offset >= size)
556 6f4d00ee 2013-09-23 0intro offset = size;
558 6f4d00ee 2013-09-23 0intro if(cnt > size-offset)
559 6f4d00ee 2013-09-23 0intro cnt = size-offset;
560 6f4d00ee 2013-09-23 0intro bn = offset/dsize;
561 6f4d00ee 2013-09-23 0intro off = offset%dsize;
563 6f4d00ee 2013-09-23 0intro while(cnt > 0){
564 6f4d00ee 2013-09-23 0intro b = sourceBlock(s, bn, OReadOnly);
565 6f4d00ee 2013-09-23 0intro if(b == nil)
566 6f4d00ee 2013-09-23 0intro goto Err;
568 6f4d00ee 2013-09-23 0intro if(n > dsize-off)
569 6f4d00ee 2013-09-23 0intro n = dsize-off;
570 6f4d00ee 2013-09-23 0intro nn = dsize-off;
571 6f4d00ee 2013-09-23 0intro if(nn > n)
573 6f4d00ee 2013-09-23 0intro memmove(p, b->data+off, nn);
574 6f4d00ee 2013-09-23 0intro memset(p+nn, 0, nn-n);
577 6f4d00ee 2013-09-23 0intro cnt -= n;
579 6f4d00ee 2013-09-23 0intro blockPut(b);
581 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
582 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
583 6f4d00ee 2013-09-23 0intro return p-(uchar*)buf;
586 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
588 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
589 6f4d00ee 2013-09-23 0intro return -1;
593 6f4d00ee 2013-09-23 0intro * Changes the file block bn to be the given block score.
594 6f4d00ee 2013-09-23 0intro * Very sneaky. Only used by flfmt.
597 6f4d00ee 2013-09-23 0intro fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag)
599 6f4d00ee 2013-09-23 0intro Block *b;
601 6f4d00ee 2013-09-23 0intro Source *s;
603 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
604 6f4d00ee 2013-09-23 0intro return 0;
607 6f4d00ee 2013-09-23 0intro if(f->dir.mode & ModeDir){
608 4b576658 2013-09-23 0intro werrstr(ENotFile);
609 6f4d00ee 2013-09-23 0intro goto Err;
612 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
613 4b576658 2013-09-23 0intro werrstr(EReadOnly);
614 6f4d00ee 2013-09-23 0intro goto Err;
617 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, -1))
618 6f4d00ee 2013-09-23 0intro goto Err;
620 6f4d00ee 2013-09-23 0intro s = f->source;
621 6f4d00ee 2013-09-23 0intro b = _sourceBlock(s, bn, OReadWrite, 1, tag);
622 6f4d00ee 2013-09-23 0intro if(b == nil)
623 6f4d00ee 2013-09-23 0intro goto Err;
625 6f4d00ee 2013-09-23 0intro if(!sourceGetEntry(s, &e))
626 6f4d00ee 2013-09-23 0intro goto Err;
627 6f4d00ee 2013-09-23 0intro if(b->l.type == BtDir){
628 6f4d00ee 2013-09-23 0intro memmove(e.score, score, VtScoreSize);
629 6f4d00ee 2013-09-23 0intro assert(e.tag == tag || e.tag == 0);
630 6f4d00ee 2013-09-23 0intro e.tag = tag;
631 6f4d00ee 2013-09-23 0intro e.flags |= VtEntryLocal;
632 6f4d00ee 2013-09-23 0intro entryPack(&e, b->data, f->source->offset % f->source->epb);
634 6f4d00ee 2013-09-23 0intro memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
635 6f4d00ee 2013-09-23 0intro blockDirty(b);
636 6f4d00ee 2013-09-23 0intro blockPut(b);
637 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
638 6f4d00ee 2013-09-23 0intro fileUnlock(f);
639 6f4d00ee 2013-09-23 0intro return 1;
643 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
644 6f4d00ee 2013-09-23 0intro fileUnlock(f);
645 6f4d00ee 2013-09-23 0intro return 0;
649 6f4d00ee 2013-09-23 0intro fileSetSize(File *f, uvlong size)
653 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
654 6f4d00ee 2013-09-23 0intro return 0;
656 6f4d00ee 2013-09-23 0intro if(f->dir.mode & ModeDir){
657 4b576658 2013-09-23 0intro werrstr(ENotFile);
658 6f4d00ee 2013-09-23 0intro goto Err;
660 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
661 4b576658 2013-09-23 0intro werrstr(EReadOnly);
662 6f4d00ee 2013-09-23 0intro goto Err;
664 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, -1))
665 6f4d00ee 2013-09-23 0intro goto Err;
666 6f4d00ee 2013-09-23 0intro r = sourceSetSize(f->source, size);
667 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
669 6f4d00ee 2013-09-23 0intro fileUnlock(f);
670 6f4d00ee 2013-09-23 0intro return r;
674 6f4d00ee 2013-09-23 0intro fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid)
676 6f4d00ee 2013-09-23 0intro Source *s;
677 6f4d00ee 2013-09-23 0intro ulong bn;
678 6f4d00ee 2013-09-23 0intro int off, dsize, n;
679 6f4d00ee 2013-09-23 0intro Block *b;
680 6f4d00ee 2013-09-23 0intro uchar *p;
681 6f4d00ee 2013-09-23 0intro vlong eof;
683 6f4d00ee 2013-09-23 0intro if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
685 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
686 6f4d00ee 2013-09-23 0intro return -1;
689 6f4d00ee 2013-09-23 0intro if(f->dir.mode & ModeDir){
690 4b576658 2013-09-23 0intro werrstr(ENotFile);
691 6f4d00ee 2013-09-23 0intro goto Err;
694 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
695 4b576658 2013-09-23 0intro werrstr(EReadOnly);
696 6f4d00ee 2013-09-23 0intro goto Err;
698 6f4d00ee 2013-09-23 0intro if(offset < 0){
699 4b576658 2013-09-23 0intro werrstr(EBadOffset);
700 6f4d00ee 2013-09-23 0intro goto Err;
703 6f4d00ee 2013-09-23 0intro fileWAccess(f, uid);
705 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, -1))
706 6f4d00ee 2013-09-23 0intro goto Err;
707 6f4d00ee 2013-09-23 0intro s = f->source;
708 6f4d00ee 2013-09-23 0intro dsize = s->dsize;
710 6f4d00ee 2013-09-23 0intro eof = sourceGetSize(s);
711 6f4d00ee 2013-09-23 0intro if(f->dir.mode & ModeAppend)
712 6f4d00ee 2013-09-23 0intro offset = eof;
713 6f4d00ee 2013-09-23 0intro bn = offset/dsize;
714 6f4d00ee 2013-09-23 0intro off = offset%dsize;
716 6f4d00ee 2013-09-23 0intro while(cnt > 0){
718 6f4d00ee 2013-09-23 0intro if(n > dsize-off)
719 6f4d00ee 2013-09-23 0intro n = dsize-off;
720 6f4d00ee 2013-09-23 0intro b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite);
721 6f4d00ee 2013-09-23 0intro if(b == nil){
722 6f4d00ee 2013-09-23 0intro if(offset > eof)
723 6f4d00ee 2013-09-23 0intro sourceSetSize(s, offset);
724 6f4d00ee 2013-09-23 0intro goto Err;
726 6f4d00ee 2013-09-23 0intro memmove(b->data+off, p, n);
728 6f4d00ee 2013-09-23 0intro cnt -= n;
730 6f4d00ee 2013-09-23 0intro offset += n;
732 6f4d00ee 2013-09-23 0intro blockDirty(b);
733 6f4d00ee 2013-09-23 0intro blockPut(b);
735 6f4d00ee 2013-09-23 0intro if(offset > eof && !sourceSetSize(s, offset))
736 6f4d00ee 2013-09-23 0intro goto Err;
737 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
738 6f4d00ee 2013-09-23 0intro fileUnlock(f);
739 6f4d00ee 2013-09-23 0intro return p-(uchar*)buf;
742 6f4d00ee 2013-09-23 0intro sourceUnlock(s);
743 6f4d00ee 2013-09-23 0intro fileUnlock(f);
744 6f4d00ee 2013-09-23 0intro return -1;
748 6f4d00ee 2013-09-23 0intro fileGetDir(File *f, DirEntry *dir)
750 6f4d00ee 2013-09-23 0intro if(!fileRLock(f))
751 6f4d00ee 2013-09-23 0intro return 0;
753 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
754 6f4d00ee 2013-09-23 0intro deCopy(dir, &f->dir);
755 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
757 6f4d00ee 2013-09-23 0intro if(!fileIsDir(f)){
758 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, OReadOnly)){
759 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
760 6f4d00ee 2013-09-23 0intro return 0;
762 6f4d00ee 2013-09-23 0intro dir->size = sourceGetSize(f->source);
763 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
765 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
767 6f4d00ee 2013-09-23 0intro return 1;
771 6f4d00ee 2013-09-23 0intro fileTruncate(File *f, char *uid)
773 6f4d00ee 2013-09-23 0intro if(fileIsDir(f)){
774 4b576658 2013-09-23 0intro werrstr(ENotFile);
775 6f4d00ee 2013-09-23 0intro return 0;
778 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
779 6f4d00ee 2013-09-23 0intro return 0;
781 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
782 4b576658 2013-09-23 0intro werrstr(EReadOnly);
783 6f4d00ee 2013-09-23 0intro fileUnlock(f);
784 6f4d00ee 2013-09-23 0intro return 0;
786 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, -1)){
787 6f4d00ee 2013-09-23 0intro fileUnlock(f);
788 6f4d00ee 2013-09-23 0intro return 0;
790 6f4d00ee 2013-09-23 0intro if(!sourceTruncate(f->source)){
791 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
792 6f4d00ee 2013-09-23 0intro fileUnlock(f);
793 6f4d00ee 2013-09-23 0intro return 0;
795 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
796 6f4d00ee 2013-09-23 0intro fileUnlock(f);
798 6f4d00ee 2013-09-23 0intro fileWAccess(f, uid);
800 6f4d00ee 2013-09-23 0intro return 1;
804 6f4d00ee 2013-09-23 0intro fileSetDir(File *f, DirEntry *dir, char *uid)
806 6f4d00ee 2013-09-23 0intro File *ff;
807 6f4d00ee 2013-09-23 0intro char *oelem;
808 6f4d00ee 2013-09-23 0intro u32int mask;
809 6f4d00ee 2013-09-23 0intro u64int size;
811 6f4d00ee 2013-09-23 0intro /* can not set permissions for the root */
812 6f4d00ee 2013-09-23 0intro if(fileIsRoot(f)){
813 4b576658 2013-09-23 0intro werrstr(ERoot);
814 6f4d00ee 2013-09-23 0intro return 0;
817 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
818 6f4d00ee 2013-09-23 0intro return 0;
820 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
821 4b576658 2013-09-23 0intro werrstr(EReadOnly);
822 6f4d00ee 2013-09-23 0intro fileUnlock(f);
823 6f4d00ee 2013-09-23 0intro return 0;
826 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
828 6f4d00ee 2013-09-23 0intro /* check new name does not already exist */
829 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.elem, dir->elem) != 0){
830 6f4d00ee 2013-09-23 0intro for(ff = f->up->down; ff; ff=ff->next){
831 6f4d00ee 2013-09-23 0intro if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
832 4b576658 2013-09-23 0intro werrstr(EExists);
833 6f4d00ee 2013-09-23 0intro goto Err;
837 6f4d00ee 2013-09-23 0intro ff = dirLookup(f->up, dir->elem);
838 6f4d00ee 2013-09-23 0intro if(ff != nil){
839 6f4d00ee 2013-09-23 0intro fileDecRef(ff);
840 4b576658 2013-09-23 0intro werrstr(EExists);
841 6f4d00ee 2013-09-23 0intro goto Err;
845 6f4d00ee 2013-09-23 0intro if(!sourceLock2(f->source, f->msource, -1))
846 6f4d00ee 2013-09-23 0intro goto Err;
847 6f4d00ee 2013-09-23 0intro if(!fileIsDir(f)){
848 6f4d00ee 2013-09-23 0intro size = sourceGetSize(f->source);
849 6f4d00ee 2013-09-23 0intro if(size != dir->size){
850 6f4d00ee 2013-09-23 0intro if(!sourceSetSize(f->source, dir->size)){
851 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
852 6f4d00ee 2013-09-23 0intro if(f->msource)
853 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
854 6f4d00ee 2013-09-23 0intro goto Err;
856 6f4d00ee 2013-09-23 0intro /* commited to changing it now */
859 6f4d00ee 2013-09-23 0intro /* commited to changing it now */
860 6f4d00ee 2013-09-23 0intro if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
861 6f4d00ee 2013-09-23 0intro fileSetTmp(f, dir->mode&ModeTemporary);
862 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
863 6f4d00ee 2013-09-23 0intro if(f->msource)
864 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
866 6f4d00ee 2013-09-23 0intro oelem = nil;
867 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.elem, dir->elem) != 0){
868 6f4d00ee 2013-09-23 0intro oelem = f->dir.elem;
869 4b576658 2013-09-23 0intro f->dir.elem = vtstrdup(dir->elem);
872 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.uid, dir->uid) != 0){
873 4b576658 2013-09-23 0intro vtfree(f->dir.uid);
874 4b576658 2013-09-23 0intro f->dir.uid = vtstrdup(dir->uid);
877 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.gid, dir->gid) != 0){
878 4b576658 2013-09-23 0intro vtfree(f->dir.gid);
879 4b576658 2013-09-23 0intro f->dir.gid = vtstrdup(dir->gid);
882 6f4d00ee 2013-09-23 0intro f->dir.mtime = dir->mtime;
883 6f4d00ee 2013-09-23 0intro f->dir.atime = dir->atime;
885 6f4d00ee 2013-09-23 0intro //fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
886 6f4d00ee 2013-09-23 0intro mask = ~(ModeDir|ModeSnapshot);
887 6f4d00ee 2013-09-23 0intro f->dir.mode &= ~mask;
888 6f4d00ee 2013-09-23 0intro f->dir.mode |= mask & dir->mode;
889 6f4d00ee 2013-09-23 0intro f->dirty = 1;
890 6f4d00ee 2013-09-23 0intro //fprint(2, "->%x\n", f->dir.mode);
892 6f4d00ee 2013-09-23 0intro fileMetaFlush2(f, oelem);
893 4b576658 2013-09-23 0intro vtfree(oelem);
895 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
896 6f4d00ee 2013-09-23 0intro fileUnlock(f);
898 6f4d00ee 2013-09-23 0intro fileWAccess(f->up, uid);
900 6f4d00ee 2013-09-23 0intro return 1;
902 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
903 6f4d00ee 2013-09-23 0intro fileUnlock(f);
904 6f4d00ee 2013-09-23 0intro return 0;
908 6f4d00ee 2013-09-23 0intro fileSetQidSpace(File *f, u64int offset, u64int max)
912 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
913 6f4d00ee 2013-09-23 0intro return 0;
914 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
915 6f4d00ee 2013-09-23 0intro f->dir.qidSpace = 1;
916 6f4d00ee 2013-09-23 0intro f->dir.qidOffset = offset;
917 6f4d00ee 2013-09-23 0intro f->dir.qidMax = max;
918 6f4d00ee 2013-09-23 0intro ret = fileMetaFlush2(f, nil)>=0;
919 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
920 6f4d00ee 2013-09-23 0intro fileUnlock(f);
921 6f4d00ee 2013-09-23 0intro return ret;
926 6f4d00ee 2013-09-23 0intro fileGetId(File *f)
928 6f4d00ee 2013-09-23 0intro /* immutable */
929 6f4d00ee 2013-09-23 0intro return f->dir.qid;
933 6f4d00ee 2013-09-23 0intro fileGetMcount(File *f)
935 6f4d00ee 2013-09-23 0intro ulong mcount;
937 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
938 6f4d00ee 2013-09-23 0intro mcount = f->dir.mcount;
939 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
940 6f4d00ee 2013-09-23 0intro return mcount;
944 6f4d00ee 2013-09-23 0intro fileGetMode(File *f)
946 6f4d00ee 2013-09-23 0intro ulong mode;
948 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
949 6f4d00ee 2013-09-23 0intro mode = f->dir.mode;
950 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
951 6f4d00ee 2013-09-23 0intro return mode;
955 6f4d00ee 2013-09-23 0intro fileIsDir(File *f)
957 6f4d00ee 2013-09-23 0intro /* immutable */
958 6f4d00ee 2013-09-23 0intro return (f->dir.mode & ModeDir) != 0;
962 6f4d00ee 2013-09-23 0intro fileIsAppend(File *f)
964 6f4d00ee 2013-09-23 0intro return (f->dir.mode & ModeAppend) != 0;
968 6f4d00ee 2013-09-23 0intro fileIsExclusive(File *f)
970 6f4d00ee 2013-09-23 0intro return (f->dir.mode & ModeExclusive) != 0;
974 6f4d00ee 2013-09-23 0intro fileIsTemporary(File *f)
976 6f4d00ee 2013-09-23 0intro return (f->dir.mode & ModeTemporary) != 0;
980 6f4d00ee 2013-09-23 0intro fileIsRoot(File *f)
982 6f4d00ee 2013-09-23 0intro return f == f->fs->file;
986 6f4d00ee 2013-09-23 0intro fileIsRoFs(File *f)
988 6f4d00ee 2013-09-23 0intro return f->fs->mode == OReadOnly;
992 6f4d00ee 2013-09-23 0intro fileGetSize(File *f, uvlong *size)
994 6f4d00ee 2013-09-23 0intro if(!fileRLock(f))
995 6f4d00ee 2013-09-23 0intro return 0;
996 6f4d00ee 2013-09-23 0intro if(!sourceLock(f->source, OReadOnly)){
997 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
998 6f4d00ee 2013-09-23 0intro return 0;
1000 6f4d00ee 2013-09-23 0intro *size = sourceGetSize(f->source);
1001 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
1002 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
1004 6f4d00ee 2013-09-23 0intro return 1;
1008 6f4d00ee 2013-09-23 0intro fileMetaFlush(File *f, int rec)
1010 6f4d00ee 2013-09-23 0intro File **kids, *p;
1011 6f4d00ee 2013-09-23 0intro int nkids;
1012 6f4d00ee 2013-09-23 0intro int i, rv;
1014 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
1015 6f4d00ee 2013-09-23 0intro rv = fileMetaFlush2(f, nil);
1016 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1018 6f4d00ee 2013-09-23 0intro if(!rec || !fileIsDir(f))
1019 6f4d00ee 2013-09-23 0intro return rv;
1021 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
1022 6f4d00ee 2013-09-23 0intro return rv;
1023 6f4d00ee 2013-09-23 0intro nkids = 0;
1024 6f4d00ee 2013-09-23 0intro for(p=f->down; p; p=p->next)
1025 6f4d00ee 2013-09-23 0intro nkids++;
1026 4b576658 2013-09-23 0intro kids = vtmalloc(nkids*sizeof(File*));
1028 6f4d00ee 2013-09-23 0intro for(p=f->down; p; p=p->next){
1029 6f4d00ee 2013-09-23 0intro kids[i++] = p;
1030 6f4d00ee 2013-09-23 0intro p->ref++;
1032 6f4d00ee 2013-09-23 0intro fileUnlock(f);
1034 6f4d00ee 2013-09-23 0intro for(i=0; i<nkids; i++){
1035 6f4d00ee 2013-09-23 0intro rv |= fileMetaFlush(kids[i], 1);
1036 6f4d00ee 2013-09-23 0intro fileDecRef(kids[i]);
1038 4b576658 2013-09-23 0intro vtfree(kids);
1039 6f4d00ee 2013-09-23 0intro return rv;
1042 6f4d00ee 2013-09-23 0intro /* assumes metaLock is held */
1043 6f4d00ee 2013-09-23 0intro static int
1044 6f4d00ee 2013-09-23 0intro fileMetaFlush2(File *f, char *oelem)
1046 6f4d00ee 2013-09-23 0intro File *fp;
1047 6f4d00ee 2013-09-23 0intro Block *b, *bb;
1048 6f4d00ee 2013-09-23 0intro MetaBlock mb;
1049 6f4d00ee 2013-09-23 0intro MetaEntry me, me2;
1050 6f4d00ee 2013-09-23 0intro int i, n;
1051 6f4d00ee 2013-09-23 0intro u32int boff;
1053 6f4d00ee 2013-09-23 0intro if(!f->dirty)
1054 6f4d00ee 2013-09-23 0intro return 0;
1056 6f4d00ee 2013-09-23 0intro if(oelem == nil)
1057 6f4d00ee 2013-09-23 0intro oelem = f->dir.elem;
1059 6f4d00ee 2013-09-23 0intro //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem);
1061 6f4d00ee 2013-09-23 0intro fp = f->up;
1063 6f4d00ee 2013-09-23 0intro if(!sourceLock(fp->msource, -1))
1064 6f4d00ee 2013-09-23 0intro return -1;
1065 6f4d00ee 2013-09-23 0intro /* can happen if source is clri'ed out from under us */
1066 6f4d00ee 2013-09-23 0intro if(f->boff == NilBlock)
1067 6f4d00ee 2013-09-23 0intro goto Err1;
1068 6f4d00ee 2013-09-23 0intro b = sourceBlock(fp->msource, f->boff, OReadWrite);
1069 6f4d00ee 2013-09-23 0intro if(b == nil)
1070 6f4d00ee 2013-09-23 0intro goto Err1;
1072 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, fp->msource->dsize))
1073 6f4d00ee 2013-09-23 0intro goto Err;
1074 6f4d00ee 2013-09-23 0intro if(!mbSearch(&mb, oelem, &i, &me))
1075 6f4d00ee 2013-09-23 0intro goto Err;
1077 6f4d00ee 2013-09-23 0intro n = deSize(&f->dir);
1078 6f4d00ee 2013-09-23 0intro if(0)fprint(2, "old size %d new size %d\n", me.size, n);
1080 6f4d00ee 2013-09-23 0intro if(mbResize(&mb, &me, n)){
1081 6f4d00ee 2013-09-23 0intro /* fits in the block */
1082 6f4d00ee 2013-09-23 0intro mbDelete(&mb, i);
1083 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.elem, oelem) != 0)
1084 6f4d00ee 2013-09-23 0intro mbSearch(&mb, f->dir.elem, &i, &me2);
1085 6f4d00ee 2013-09-23 0intro dePack(&f->dir, &me);
1086 6f4d00ee 2013-09-23 0intro mbInsert(&mb, i, &me);
1087 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1088 6f4d00ee 2013-09-23 0intro blockDirty(b);
1089 6f4d00ee 2013-09-23 0intro blockPut(b);
1090 6f4d00ee 2013-09-23 0intro sourceUnlock(fp->msource);
1091 6f4d00ee 2013-09-23 0intro f->dirty = 0;
1093 6f4d00ee 2013-09-23 0intro return 1;
1097 6f4d00ee 2013-09-23 0intro * moving entry to another block
1098 6f4d00ee 2013-09-23 0intro * it is feasible for the fs to crash leaving two copies
1099 6f4d00ee 2013-09-23 0intro * of the directory entry. This is just too much work to
1100 6f4d00ee 2013-09-23 0intro * fix. Given that entries are only allocated in a block that
1101 6f4d00ee 2013-09-23 0intro * is less than PercentageFull, most modifications of meta data
1102 6f4d00ee 2013-09-23 0intro * will fit within the block. i.e. this code should almost
1103 6f4d00ee 2013-09-23 0intro * never be executed.
1105 6f4d00ee 2013-09-23 0intro boff = fileMetaAlloc(fp, &f->dir, f->boff+1);
1106 6f4d00ee 2013-09-23 0intro if(boff == NilBlock){
1107 6f4d00ee 2013-09-23 0intro /* mbResize might have modified block */
1108 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1109 6f4d00ee 2013-09-23 0intro blockDirty(b);
1110 6f4d00ee 2013-09-23 0intro goto Err;
1112 6f4d00ee 2013-09-23 0intro fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
1113 6f4d00ee 2013-09-23 0intro f->boff = boff;
1115 6f4d00ee 2013-09-23 0intro /* make sure deletion goes to disk after new entry */
1116 6f4d00ee 2013-09-23 0intro bb = sourceBlock(fp->msource, f->boff, OReadWrite);
1117 6f4d00ee 2013-09-23 0intro mbDelete(&mb, i);
1118 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1119 6f4d00ee 2013-09-23 0intro blockDependency(b, bb, -1, nil, nil);
1120 6f4d00ee 2013-09-23 0intro blockPut(bb);
1121 6f4d00ee 2013-09-23 0intro blockDirty(b);
1122 6f4d00ee 2013-09-23 0intro blockPut(b);
1123 6f4d00ee 2013-09-23 0intro sourceUnlock(fp->msource);
1125 6f4d00ee 2013-09-23 0intro f->dirty = 0;
1127 6f4d00ee 2013-09-23 0intro return 1;
1130 6f4d00ee 2013-09-23 0intro blockPut(b);
1132 6f4d00ee 2013-09-23 0intro sourceUnlock(fp->msource);
1133 6f4d00ee 2013-09-23 0intro return -1;
1136 6f4d00ee 2013-09-23 0intro static int
1137 6f4d00ee 2013-09-23 0intro fileMetaRemove(File *f, char *uid)
1139 6f4d00ee 2013-09-23 0intro Block *b;
1140 6f4d00ee 2013-09-23 0intro MetaBlock mb;
1141 6f4d00ee 2013-09-23 0intro MetaEntry me;
1143 6f4d00ee 2013-09-23 0intro File *up;
1145 6f4d00ee 2013-09-23 0intro up = f->up;
1147 6f4d00ee 2013-09-23 0intro fileWAccess(up, uid);
1149 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
1151 6f4d00ee 2013-09-23 0intro sourceLock(up->msource, OReadWrite);
1152 6f4d00ee 2013-09-23 0intro b = sourceBlock(up->msource, f->boff, OReadWrite);
1153 6f4d00ee 2013-09-23 0intro if(b == nil)
1154 6f4d00ee 2013-09-23 0intro goto Err;
1156 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, up->msource->dsize))
1158 6f4d00ee 2013-09-23 0intro fprint(2, "U\n");
1159 6f4d00ee 2013-09-23 0intro goto Err;
1161 6f4d00ee 2013-09-23 0intro if(!mbSearch(&mb, f->dir.elem, &i, &me))
1163 6f4d00ee 2013-09-23 0intro fprint(2, "S\n");
1164 6f4d00ee 2013-09-23 0intro goto Err;
1166 6f4d00ee 2013-09-23 0intro mbDelete(&mb, i);
1167 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1168 6f4d00ee 2013-09-23 0intro sourceUnlock(up->msource);
1170 6f4d00ee 2013-09-23 0intro blockDirty(b);
1171 6f4d00ee 2013-09-23 0intro blockPut(b);
1173 6f4d00ee 2013-09-23 0intro f->removed = 1;
1174 6f4d00ee 2013-09-23 0intro f->boff = NilBlock;
1175 6f4d00ee 2013-09-23 0intro f->dirty = 0;
1177 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1178 6f4d00ee 2013-09-23 0intro return 1;
1181 6f4d00ee 2013-09-23 0intro sourceUnlock(up->msource);
1182 6f4d00ee 2013-09-23 0intro blockPut(b);
1183 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1184 6f4d00ee 2013-09-23 0intro return 0;
1187 6f4d00ee 2013-09-23 0intro /* assume file is locked, assume f->msource is locked */
1188 6f4d00ee 2013-09-23 0intro static int
1189 6f4d00ee 2013-09-23 0intro fileCheckEmpty(File *f)
1191 6f4d00ee 2013-09-23 0intro u32int i, n;
1192 6f4d00ee 2013-09-23 0intro Block *b;
1193 6f4d00ee 2013-09-23 0intro MetaBlock mb;
1194 6f4d00ee 2013-09-23 0intro Source *r;
1196 6f4d00ee 2013-09-23 0intro r = f->msource;
1197 6f4d00ee 2013-09-23 0intro n = (sourceGetSize(r)+r->dsize-1)/r->dsize;
1198 6f4d00ee 2013-09-23 0intro for(i=0; i<n; i++){
1199 6f4d00ee 2013-09-23 0intro b = sourceBlock(r, i, OReadOnly);
1200 6f4d00ee 2013-09-23 0intro if(b == nil)
1201 6f4d00ee 2013-09-23 0intro goto Err;
1202 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, r->dsize))
1203 6f4d00ee 2013-09-23 0intro goto Err;
1204 6f4d00ee 2013-09-23 0intro if(mb.nindex > 0){
1205 4b576658 2013-09-23 0intro werrstr(ENotEmpty);
1206 6f4d00ee 2013-09-23 0intro goto Err;
1208 6f4d00ee 2013-09-23 0intro blockPut(b);
1210 6f4d00ee 2013-09-23 0intro return 1;
1212 6f4d00ee 2013-09-23 0intro blockPut(b);
1213 6f4d00ee 2013-09-23 0intro return 0;
1217 6f4d00ee 2013-09-23 0intro fileRemove(File *f, char *uid)
1219 6f4d00ee 2013-09-23 0intro File *ff;
1221 6f4d00ee 2013-09-23 0intro /* can not remove the root */
1222 6f4d00ee 2013-09-23 0intro if(fileIsRoot(f)){
1223 4b576658 2013-09-23 0intro werrstr(ERoot);
1224 6f4d00ee 2013-09-23 0intro return 0;
1227 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
1228 6f4d00ee 2013-09-23 0intro return 0;
1230 6f4d00ee 2013-09-23 0intro if(f->source->mode != OReadWrite){
1231 4b576658 2013-09-23 0intro werrstr(EReadOnly);
1232 6f4d00ee 2013-09-23 0intro goto Err1;
1234 6f4d00ee 2013-09-23 0intro if(!sourceLock2(f->source, f->msource, -1))
1235 6f4d00ee 2013-09-23 0intro goto Err1;
1236 6f4d00ee 2013-09-23 0intro if(fileIsDir(f) && !fileCheckEmpty(f))
1237 6f4d00ee 2013-09-23 0intro goto Err;
1239 6f4d00ee 2013-09-23 0intro for(ff=f->down; ff; ff=ff->next)
1240 6f4d00ee 2013-09-23 0intro assert(ff->removed);
1242 6f4d00ee 2013-09-23 0intro sourceRemove(f->source);
1243 6f4d00ee 2013-09-23 0intro f->source->file = nil; /* erase back pointer */
1244 6f4d00ee 2013-09-23 0intro f->source = nil;
1245 6f4d00ee 2013-09-23 0intro if(f->msource){
1246 6f4d00ee 2013-09-23 0intro sourceRemove(f->msource);
1247 6f4d00ee 2013-09-23 0intro f->msource = nil;
1250 6f4d00ee 2013-09-23 0intro fileUnlock(f);
1252 6f4d00ee 2013-09-23 0intro if(!fileMetaRemove(f, uid))
1253 6f4d00ee 2013-09-23 0intro return 0;
1255 6f4d00ee 2013-09-23 0intro return 1;
1258 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
1259 6f4d00ee 2013-09-23 0intro if(f->msource)
1260 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
1262 6f4d00ee 2013-09-23 0intro fileUnlock(f);
1263 6f4d00ee 2013-09-23 0intro return 0;
1266 6f4d00ee 2013-09-23 0intro static int
1267 6f4d00ee 2013-09-23 0intro clri(File *f, char *uid)
1271 6f4d00ee 2013-09-23 0intro if(f == nil)
1272 6f4d00ee 2013-09-23 0intro return 0;
1273 6f4d00ee 2013-09-23 0intro if(f->up->source->mode != OReadWrite){
1274 4b576658 2013-09-23 0intro werrstr(EReadOnly);
1275 6f4d00ee 2013-09-23 0intro fileDecRef(f);
1276 6f4d00ee 2013-09-23 0intro return 0;
1278 6f4d00ee 2013-09-23 0intro r = fileMetaRemove(f, uid);
1279 6f4d00ee 2013-09-23 0intro fileDecRef(f);
1280 6f4d00ee 2013-09-23 0intro return r;
1284 6f4d00ee 2013-09-23 0intro fileClriPath(Fs *fs, char *path, char *uid)
1286 6f4d00ee 2013-09-23 0intro return clri(_fileOpen(fs, path, 1), uid);
1290 6f4d00ee 2013-09-23 0intro fileClri(File *dir, char *elem, char *uid)
1292 6f4d00ee 2013-09-23 0intro return clri(_fileWalk(dir, elem, 1), uid);
1296 6f4d00ee 2013-09-23 0intro fileIncRef(File *vf)
1298 6f4d00ee 2013-09-23 0intro fileMetaLock(vf);
1299 6f4d00ee 2013-09-23 0intro assert(vf->ref > 0);
1300 6f4d00ee 2013-09-23 0intro vf->ref++;
1301 6f4d00ee 2013-09-23 0intro fileMetaUnlock(vf);
1302 6f4d00ee 2013-09-23 0intro return vf;
1306 6f4d00ee 2013-09-23 0intro fileDecRef(File *f)
1308 6f4d00ee 2013-09-23 0intro File *p, *q, **qq;
1310 6f4d00ee 2013-09-23 0intro if(f->up == nil){
1311 6f4d00ee 2013-09-23 0intro /* never linked in */
1312 6f4d00ee 2013-09-23 0intro assert(f->ref == 1);
1313 6f4d00ee 2013-09-23 0intro fileFree(f);
1314 6f4d00ee 2013-09-23 0intro return 1;
1317 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
1318 6f4d00ee 2013-09-23 0intro f->ref--;
1319 6f4d00ee 2013-09-23 0intro if(f->ref > 0){
1320 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1321 6f4d00ee 2013-09-23 0intro return 0;
1323 6f4d00ee 2013-09-23 0intro assert(f->ref == 0);
1324 6f4d00ee 2013-09-23 0intro assert(f->down == nil);
1326 6f4d00ee 2013-09-23 0intro fileMetaFlush2(f, nil);
1328 6f4d00ee 2013-09-23 0intro p = f->up;
1329 6f4d00ee 2013-09-23 0intro qq = &p->down;
1330 6f4d00ee 2013-09-23 0intro for(q = *qq; q; q = *qq){
1331 6f4d00ee 2013-09-23 0intro if(q == f)
1333 6f4d00ee 2013-09-23 0intro qq = &q->next;
1335 6f4d00ee 2013-09-23 0intro assert(q != nil);
1336 6f4d00ee 2013-09-23 0intro *qq = f->next;
1338 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1339 6f4d00ee 2013-09-23 0intro fileFree(f);
1341 6f4d00ee 2013-09-23 0intro fileDecRef(p);
1342 6f4d00ee 2013-09-23 0intro return 1;
1346 6f4d00ee 2013-09-23 0intro fileGetParent(File *f)
1348 6f4d00ee 2013-09-23 0intro if(fileIsRoot(f))
1349 6f4d00ee 2013-09-23 0intro return fileIncRef(f);
1350 6f4d00ee 2013-09-23 0intro return fileIncRef(f->up);
1353 6f4d00ee 2013-09-23 0intro DirEntryEnum *
1354 6f4d00ee 2013-09-23 0intro deeOpen(File *f)
1356 6f4d00ee 2013-09-23 0intro DirEntryEnum *dee;
1357 6f4d00ee 2013-09-23 0intro File *p;
1359 6f4d00ee 2013-09-23 0intro if(!fileIsDir(f)){
1360 4b576658 2013-09-23 0intro werrstr(ENotDir);
1361 6f4d00ee 2013-09-23 0intro fileDecRef(f);
1362 6f4d00ee 2013-09-23 0intro return nil;
1365 6f4d00ee 2013-09-23 0intro /* flush out meta data */
1366 6f4d00ee 2013-09-23 0intro if(!fileLock(f))
1367 6f4d00ee 2013-09-23 0intro return nil;
1368 6f4d00ee 2013-09-23 0intro for(p=f->down; p; p=p->next)
1369 6f4d00ee 2013-09-23 0intro fileMetaFlush2(p, nil);
1370 6f4d00ee 2013-09-23 0intro fileUnlock(f);
1372 4b576658 2013-09-23 0intro dee = vtmallocz(sizeof(DirEntryEnum));
1373 6f4d00ee 2013-09-23 0intro dee->file = fileIncRef(f);
1375 6f4d00ee 2013-09-23 0intro return dee;
1378 6f4d00ee 2013-09-23 0intro static int
1379 6f4d00ee 2013-09-23 0intro dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size)
1381 6f4d00ee 2013-09-23 0intro Block *b;
1382 6f4d00ee 2013-09-23 0intro ulong bn;
1383 6f4d00ee 2013-09-23 0intro Entry e;
1384 6f4d00ee 2013-09-23 0intro int epb;
1386 6f4d00ee 2013-09-23 0intro epb = s->dsize/VtEntrySize;
1387 6f4d00ee 2013-09-23 0intro bn = elem/epb;
1388 6f4d00ee 2013-09-23 0intro elem -= bn*epb;
1390 6f4d00ee 2013-09-23 0intro b = sourceBlock(s, bn, OReadOnly);
1391 6f4d00ee 2013-09-23 0intro if(b == nil)
1392 6f4d00ee 2013-09-23 0intro goto Err;
1393 6f4d00ee 2013-09-23 0intro if(!entryUnpack(&e, b->data, elem))
1394 6f4d00ee 2013-09-23 0intro goto Err;
1396 6f4d00ee 2013-09-23 0intro /* hanging entries are returned as zero size */
1397 6f4d00ee 2013-09-23 0intro if(!(e.flags & VtEntryActive) || e.gen != gen)
1398 6f4d00ee 2013-09-23 0intro *size = 0;
1400 6f4d00ee 2013-09-23 0intro *size = e.size;
1401 6f4d00ee 2013-09-23 0intro blockPut(b);
1402 6f4d00ee 2013-09-23 0intro return 1;
1405 6f4d00ee 2013-09-23 0intro blockPut(b);
1406 6f4d00ee 2013-09-23 0intro return 0;
1409 6f4d00ee 2013-09-23 0intro static int
1410 6f4d00ee 2013-09-23 0intro deeFill(DirEntryEnum *dee)
1412 6f4d00ee 2013-09-23 0intro int i, n;
1413 6f4d00ee 2013-09-23 0intro Source *meta, *source;
1414 6f4d00ee 2013-09-23 0intro MetaBlock mb;
1415 6f4d00ee 2013-09-23 0intro MetaEntry me;
1416 6f4d00ee 2013-09-23 0intro File *f;
1417 6f4d00ee 2013-09-23 0intro Block *b;
1418 6f4d00ee 2013-09-23 0intro DirEntry *de;
1420 6f4d00ee 2013-09-23 0intro /* clean up first */
1421 6f4d00ee 2013-09-23 0intro for(i=dee->i; i<dee->n; i++)
1422 6f4d00ee 2013-09-23 0intro deCleanup(dee->buf+i);
1423 4b576658 2013-09-23 0intro vtfree(dee->buf);
1424 6f4d00ee 2013-09-23 0intro dee->buf = nil;
1425 6f4d00ee 2013-09-23 0intro dee->i = 0;
1426 6f4d00ee 2013-09-23 0intro dee->n = 0;
1428 6f4d00ee 2013-09-23 0intro f = dee->file;
1430 6f4d00ee 2013-09-23 0intro source = f->source;
1431 6f4d00ee 2013-09-23 0intro meta = f->msource;
1433 6f4d00ee 2013-09-23 0intro b = sourceBlock(meta, dee->boff, OReadOnly);
1434 6f4d00ee 2013-09-23 0intro if(b == nil)
1435 6f4d00ee 2013-09-23 0intro goto Err;
1436 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, meta->dsize))
1437 6f4d00ee 2013-09-23 0intro goto Err;
1439 6f4d00ee 2013-09-23 0intro n = mb.nindex;
1440 4b576658 2013-09-23 0intro dee->buf = vtmalloc(n * sizeof(DirEntry));
1442 6f4d00ee 2013-09-23 0intro for(i=0; i<n; i++){
1443 6f4d00ee 2013-09-23 0intro de = dee->buf + i;
1444 6f4d00ee 2013-09-23 0intro meUnpack(&me, &mb, i);
1445 6f4d00ee 2013-09-23 0intro if(!deUnpack(de, &me))
1446 6f4d00ee 2013-09-23 0intro goto Err;
1447 6f4d00ee 2013-09-23 0intro dee->n++;
1448 6f4d00ee 2013-09-23 0intro if(!(de->mode & ModeDir))
1449 6f4d00ee 2013-09-23 0intro if(!dirEntrySize(source, de->entry, de->gen, &de->size))
1450 6f4d00ee 2013-09-23 0intro goto Err;
1452 6f4d00ee 2013-09-23 0intro dee->boff++;
1453 6f4d00ee 2013-09-23 0intro blockPut(b);
1454 6f4d00ee 2013-09-23 0intro return 1;
1456 6f4d00ee 2013-09-23 0intro blockPut(b);
1457 6f4d00ee 2013-09-23 0intro return 0;
1461 6f4d00ee 2013-09-23 0intro deeRead(DirEntryEnum *dee, DirEntry *de)
1463 6f4d00ee 2013-09-23 0intro int ret, didread;
1464 6f4d00ee 2013-09-23 0intro File *f;
1465 6f4d00ee 2013-09-23 0intro u32int nb;
1467 6f4d00ee 2013-09-23 0intro if(dee == nil){
1468 4b576658 2013-09-23 0intro werrstr("cannot happen in deeRead");
1469 6f4d00ee 2013-09-23 0intro return -1;
1472 6f4d00ee 2013-09-23 0intro f = dee->file;
1473 6f4d00ee 2013-09-23 0intro if(!fileRLock(f))
1474 6f4d00ee 2013-09-23 0intro return -1;
1476 6f4d00ee 2013-09-23 0intro if(!sourceLock2(f->source, f->msource, OReadOnly)){
1477 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
1478 6f4d00ee 2013-09-23 0intro return -1;
1481 6f4d00ee 2013-09-23 0intro nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize;
1483 6f4d00ee 2013-09-23 0intro didread = 0;
1484 6f4d00ee 2013-09-23 0intro while(dee->i >= dee->n){
1485 6f4d00ee 2013-09-23 0intro if(dee->boff >= nb){
1486 6f4d00ee 2013-09-23 0intro ret = 0;
1487 6f4d00ee 2013-09-23 0intro goto Return;
1489 6f4d00ee 2013-09-23 0intro didread = 1;
1490 6f4d00ee 2013-09-23 0intro if(!deeFill(dee)){
1491 6f4d00ee 2013-09-23 0intro ret = -1;
1492 6f4d00ee 2013-09-23 0intro goto Return;
1496 6f4d00ee 2013-09-23 0intro memmove(de, dee->buf + dee->i, sizeof(DirEntry));
1497 6f4d00ee 2013-09-23 0intro dee->i++;
1498 6f4d00ee 2013-09-23 0intro ret = 1;
1501 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
1502 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
1503 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
1505 6f4d00ee 2013-09-23 0intro if(didread)
1506 6f4d00ee 2013-09-23 0intro fileRAccess(f);
1507 6f4d00ee 2013-09-23 0intro return ret;
1511 6f4d00ee 2013-09-23 0intro deeClose(DirEntryEnum *dee)
1514 6f4d00ee 2013-09-23 0intro if(dee == nil)
1516 6f4d00ee 2013-09-23 0intro for(i=dee->i; i<dee->n; i++)
1517 6f4d00ee 2013-09-23 0intro deCleanup(dee->buf+i);
1518 4b576658 2013-09-23 0intro vtfree(dee->buf);
1519 6f4d00ee 2013-09-23 0intro fileDecRef(dee->file);
1520 4b576658 2013-09-23 0intro vtfree(dee);
1524 6f4d00ee 2013-09-23 0intro * caller must lock f->source and f->msource
1525 6f4d00ee 2013-09-23 0intro * caller must NOT lock the source and msource
1526 6f4d00ee 2013-09-23 0intro * referenced by dir.
1528 6f4d00ee 2013-09-23 0intro static u32int
1529 6f4d00ee 2013-09-23 0intro fileMetaAlloc(File *f, DirEntry *dir, u32int start)
1531 6f4d00ee 2013-09-23 0intro u32int nb, bo;
1532 6f4d00ee 2013-09-23 0intro Block *b, *bb;
1533 6f4d00ee 2013-09-23 0intro MetaBlock mb;
1535 6f4d00ee 2013-09-23 0intro uchar *p;
1536 6f4d00ee 2013-09-23 0intro int i, n, epb;
1537 6f4d00ee 2013-09-23 0intro MetaEntry me;
1538 6f4d00ee 2013-09-23 0intro Source *s, *ms;
1540 6f4d00ee 2013-09-23 0intro s = f->source;
1541 6f4d00ee 2013-09-23 0intro ms = f->msource;
1543 6f4d00ee 2013-09-23 0intro n = deSize(dir);
1544 6f4d00ee 2013-09-23 0intro nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize;
1545 6f4d00ee 2013-09-23 0intro b = nil;
1546 6f4d00ee 2013-09-23 0intro if(start > nb)
1547 6f4d00ee 2013-09-23 0intro start = nb;
1548 6f4d00ee 2013-09-23 0intro for(bo=start; bo<nb; bo++){
1549 6f4d00ee 2013-09-23 0intro b = sourceBlock(ms, bo, OReadWrite);
1550 6f4d00ee 2013-09-23 0intro if(b == nil)
1551 6f4d00ee 2013-09-23 0intro goto Err;
1552 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, ms->dsize))
1553 6f4d00ee 2013-09-23 0intro goto Err;
1554 6f4d00ee 2013-09-23 0intro nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
1555 6f4d00ee 2013-09-23 0intro if(n <= nn && mb.nindex < mb.maxindex)
1557 6f4d00ee 2013-09-23 0intro blockPut(b);
1558 6f4d00ee 2013-09-23 0intro b = nil;
1561 6f4d00ee 2013-09-23 0intro /* add block to meta file */
1562 6f4d00ee 2013-09-23 0intro if(b == nil){
1563 6f4d00ee 2013-09-23 0intro b = sourceBlock(ms, bo, OReadWrite);
1564 6f4d00ee 2013-09-23 0intro if(b == nil)
1565 6f4d00ee 2013-09-23 0intro goto Err;
1566 6f4d00ee 2013-09-23 0intro sourceSetSize(ms, (nb+1)*ms->dsize);
1567 6f4d00ee 2013-09-23 0intro mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
1570 6f4d00ee 2013-09-23 0intro p = mbAlloc(&mb, n);
1571 6f4d00ee 2013-09-23 0intro if(p == nil){
1572 6f4d00ee 2013-09-23 0intro /* mbAlloc might have changed block */
1573 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1574 6f4d00ee 2013-09-23 0intro blockDirty(b);
1575 4b576658 2013-09-23 0intro werrstr(EBadMeta);
1576 6f4d00ee 2013-09-23 0intro goto Err;
1579 6f4d00ee 2013-09-23 0intro mbSearch(&mb, dir->elem, &i, &me);
1580 6f4d00ee 2013-09-23 0intro assert(me.p == nil);
1581 6f4d00ee 2013-09-23 0intro me.p = p;
1582 6f4d00ee 2013-09-23 0intro me.size = n;
1583 6f4d00ee 2013-09-23 0intro dePack(dir, &me);
1584 6f4d00ee 2013-09-23 0intro mbInsert(&mb, i, &me);
1585 6f4d00ee 2013-09-23 0intro mbPack(&mb);
1587 6f4d00ee 2013-09-23 0intro /* meta block depends on super block for qid ... */
1588 6f4d00ee 2013-09-23 0intro bb = cacheLocal(b->c, PartSuper, 0, OReadOnly);
1589 6f4d00ee 2013-09-23 0intro blockDependency(b, bb, -1, nil, nil);
1590 6f4d00ee 2013-09-23 0intro blockPut(bb);
1592 6f4d00ee 2013-09-23 0intro /* ... and one or two dir entries */
1593 6f4d00ee 2013-09-23 0intro epb = s->dsize/VtEntrySize;
1594 6f4d00ee 2013-09-23 0intro bb = sourceBlock(s, dir->entry/epb, OReadOnly);
1595 6f4d00ee 2013-09-23 0intro blockDependency(b, bb, -1, nil, nil);
1596 6f4d00ee 2013-09-23 0intro blockPut(bb);
1597 6f4d00ee 2013-09-23 0intro if(dir->mode & ModeDir){
1598 6f4d00ee 2013-09-23 0intro bb = sourceBlock(s, dir->mentry/epb, OReadOnly);
1599 6f4d00ee 2013-09-23 0intro blockDependency(b, bb, -1, nil, nil);
1600 6f4d00ee 2013-09-23 0intro blockPut(bb);
1603 6f4d00ee 2013-09-23 0intro blockDirty(b);
1604 6f4d00ee 2013-09-23 0intro blockPut(b);
1605 6f4d00ee 2013-09-23 0intro return bo;
1607 6f4d00ee 2013-09-23 0intro blockPut(b);
1608 6f4d00ee 2013-09-23 0intro return NilBlock;
1611 6f4d00ee 2013-09-23 0intro static int
1612 6f4d00ee 2013-09-23 0intro chkSource(File *f)
1614 6f4d00ee 2013-09-23 0intro if(f->partial)
1615 6f4d00ee 2013-09-23 0intro return 1;
1617 6f4d00ee 2013-09-23 0intro if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){
1618 4b576658 2013-09-23 0intro werrstr(ERemoved);
1619 6f4d00ee 2013-09-23 0intro return 0;
1621 6f4d00ee 2013-09-23 0intro return 1;
1624 6f4d00ee 2013-09-23 0intro static int
1625 6f4d00ee 2013-09-23 0intro fileRLock(File *f)
1627 4b576658 2013-09-23 0intro assert(!canwlock(&f->fs->elk));
1628 4b576658 2013-09-23 0intro rlock(&f->lk);
1629 6f4d00ee 2013-09-23 0intro if(!chkSource(f)){
1630 6f4d00ee 2013-09-23 0intro fileRUnlock(f);
1631 6f4d00ee 2013-09-23 0intro return 0;
1633 6f4d00ee 2013-09-23 0intro return 1;
1636 6f4d00ee 2013-09-23 0intro static void
1637 6f4d00ee 2013-09-23 0intro fileRUnlock(File *f)
1639 4b576658 2013-09-23 0intro runlock(&f->lk);
1642 6f4d00ee 2013-09-23 0intro static int
1643 6f4d00ee 2013-09-23 0intro fileLock(File *f)
1645 4b576658 2013-09-23 0intro assert(!canwlock(&f->fs->elk));
1646 4b576658 2013-09-23 0intro wlock(&f->lk);
1647 6f4d00ee 2013-09-23 0intro if(!chkSource(f)){
1648 6f4d00ee 2013-09-23 0intro fileUnlock(f);
1649 6f4d00ee 2013-09-23 0intro return 0;
1651 6f4d00ee 2013-09-23 0intro return 1;
1654 6f4d00ee 2013-09-23 0intro static void
1655 6f4d00ee 2013-09-23 0intro fileUnlock(File *f)
1657 4b576658 2013-09-23 0intro wunlock(&f->lk);
1661 6f4d00ee 2013-09-23 0intro * f->source and f->msource must NOT be locked.
1662 6f4d00ee 2013-09-23 0intro * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2).
1663 6f4d00ee 2013-09-23 0intro * We have to respect that ordering.
1665 6f4d00ee 2013-09-23 0intro static void
1666 6f4d00ee 2013-09-23 0intro fileMetaLock(File *f)
1668 6f4d00ee 2013-09-23 0intro if(f->up == nil)
1669 6f4d00ee 2013-09-23 0intro fprint(2, "f->elem = %s\n", f->dir.elem);
1670 6f4d00ee 2013-09-23 0intro assert(f->up != nil);
1671 4b576658 2013-09-23 0intro assert(!canwlock(&f->fs->elk));
1672 4b576658 2013-09-23 0intro wlock(&f->up->lk);
1675 6f4d00ee 2013-09-23 0intro static void
1676 6f4d00ee 2013-09-23 0intro fileMetaUnlock(File *f)
1678 4b576658 2013-09-23 0intro wunlock(&f->up->lk);
1682 6f4d00ee 2013-09-23 0intro * f->source and f->msource must NOT be locked.
1683 6f4d00ee 2013-09-23 0intro * see fileMetaLock.
1685 6f4d00ee 2013-09-23 0intro static void
1686 6f4d00ee 2013-09-23 0intro fileRAccess(File* f)
1688 6f4d00ee 2013-09-23 0intro if(f->mode == OReadOnly || f->fs->noatimeupd)
1691 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
1692 6f4d00ee 2013-09-23 0intro f->dir.atime = time(0L);
1693 6f4d00ee 2013-09-23 0intro f->dirty = 1;
1694 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1698 6f4d00ee 2013-09-23 0intro * f->source and f->msource must NOT be locked.
1699 6f4d00ee 2013-09-23 0intro * see fileMetaLock.
1701 6f4d00ee 2013-09-23 0intro static void
1702 6f4d00ee 2013-09-23 0intro fileWAccess(File* f, char *mid)
1704 6f4d00ee 2013-09-23 0intro if(f->mode == OReadOnly)
1707 6f4d00ee 2013-09-23 0intro fileMetaLock(f);
1708 6f4d00ee 2013-09-23 0intro f->dir.atime = f->dir.mtime = time(0L);
1709 6f4d00ee 2013-09-23 0intro if(strcmp(f->dir.mid, mid) != 0){
1710 4b576658 2013-09-23 0intro vtfree(f->dir.mid);
1711 4b576658 2013-09-23 0intro f->dir.mid = vtstrdup(mid);
1713 6f4d00ee 2013-09-23 0intro f->dir.mcount++;
1714 6f4d00ee 2013-09-23 0intro f->dirty = 1;
1715 6f4d00ee 2013-09-23 0intro fileMetaUnlock(f);
1717 6f4d00ee 2013-09-23 0intro /*RSC: let's try this */
1718 6f4d00ee 2013-09-23 0intro /*presotto - lets not
1719 6f4d00ee 2013-09-23 0intro if(f->up)
1720 6f4d00ee 2013-09-23 0intro fileWAccess(f->up, mid);
1724 6f4d00ee 2013-09-23 0intro static int
1725 6f4d00ee 2013-09-23 0intro getEntry(Source *r, Entry *e, int checkepoch)
1727 6f4d00ee 2013-09-23 0intro u32int epoch;
1728 6f4d00ee 2013-09-23 0intro Block *b;
1730 6f4d00ee 2013-09-23 0intro if(r == nil){
1731 6f4d00ee 2013-09-23 0intro memset(&e, 0, sizeof e);
1732 6f4d00ee 2013-09-23 0intro return 1;
1735 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly);
1736 6f4d00ee 2013-09-23 0intro if(b == nil)
1737 6f4d00ee 2013-09-23 0intro return 0;
1738 6f4d00ee 2013-09-23 0intro if(!entryUnpack(e, b->data, r->offset % r->epb)){
1739 6f4d00ee 2013-09-23 0intro blockPut(b);
1740 6f4d00ee 2013-09-23 0intro return 0;
1742 6f4d00ee 2013-09-23 0intro epoch = b->l.epoch;
1743 6f4d00ee 2013-09-23 0intro blockPut(b);
1745 6f4d00ee 2013-09-23 0intro if(checkepoch){
1746 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, e->score, entryType(e), e->tag, OReadOnly);
1748 6f4d00ee 2013-09-23 0intro if(b->l.epoch >= epoch)
1749 6f4d00ee 2013-09-23 0intro fprint(2, "warning: entry %p epoch not older %#.8ux/%d %V/%d in getEntry\n",
1750 6f4d00ee 2013-09-23 0intro r, b->addr, b->l.epoch, r->score, epoch);
1751 6f4d00ee 2013-09-23 0intro blockPut(b);
1755 6f4d00ee 2013-09-23 0intro return 1;
1758 6f4d00ee 2013-09-23 0intro static int
1759 6f4d00ee 2013-09-23 0intro setEntry(Source *r, Entry *e)
1761 6f4d00ee 2013-09-23 0intro Block *b;
1762 6f4d00ee 2013-09-23 0intro Entry oe;
1764 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
1765 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
1766 6f4d00ee 2013-09-23 0intro if(b == nil)
1767 6f4d00ee 2013-09-23 0intro return 0;
1768 6f4d00ee 2013-09-23 0intro if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
1769 6f4d00ee 2013-09-23 0intro blockPut(b);
1770 6f4d00ee 2013-09-23 0intro return 0;
1772 6f4d00ee 2013-09-23 0intro e->gen = oe.gen;
1773 6f4d00ee 2013-09-23 0intro entryPack(e, b->data, r->offset % r->epb);
1775 6f4d00ee 2013-09-23 0intro /* BUG b should depend on the entry pointer */
1777 6f4d00ee 2013-09-23 0intro blockDirty(b);
1778 6f4d00ee 2013-09-23 0intro blockPut(b);
1779 6f4d00ee 2013-09-23 0intro return 1;
1782 6f4d00ee 2013-09-23 0intro /* assumes hold elk */
1784 6f4d00ee 2013-09-23 0intro fileSnapshot(File *dst, File *src, u32int epoch, int doarchive)
1786 6f4d00ee 2013-09-23 0intro Entry e, ee;
1788 6f4d00ee 2013-09-23 0intro /* add link to snapshot */
1789 6f4d00ee 2013-09-23 0intro if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1))
1790 6f4d00ee 2013-09-23 0intro return 0;
1792 6f4d00ee 2013-09-23 0intro e.snap = epoch;
1793 6f4d00ee 2013-09-23 0intro e.archive = doarchive;
1794 6f4d00ee 2013-09-23 0intro ee.snap = epoch;
1795 6f4d00ee 2013-09-23 0intro ee.archive = doarchive;
1797 6f4d00ee 2013-09-23 0intro if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee))
1798 6f4d00ee 2013-09-23 0intro return 0;
1799 6f4d00ee 2013-09-23 0intro return 1;
1803 6f4d00ee 2013-09-23 0intro fileGetSources(File *f, Entry *e, Entry *ee)
1805 6f4d00ee 2013-09-23 0intro if(!getEntry(f->source, e, 0)
1806 6f4d00ee 2013-09-23 0intro || !getEntry(f->msource, ee, 0))
1807 6f4d00ee 2013-09-23 0intro return 0;
1808 6f4d00ee 2013-09-23 0intro return 1;
1812 6f4d00ee 2013-09-23 0intro * Walk down to the block(s) containing the Entries
1813 6f4d00ee 2013-09-23 0intro * for f->source and f->msource, copying as we go.
1816 6f4d00ee 2013-09-23 0intro fileWalkSources(File *f)
1818 6f4d00ee 2013-09-23 0intro if(f->mode == OReadOnly){
1819 6f4d00ee 2013-09-23 0intro fprint(2, "readonly in fileWalkSources\n");
1820 6f4d00ee 2013-09-23 0intro return 1;
1822 6f4d00ee 2013-09-23 0intro if(!sourceLock2(f->source, f->msource, OReadWrite)){
1823 6f4d00ee 2013-09-23 0intro fprint(2, "sourceLock2 failed in fileWalkSources\n");
1824 6f4d00ee 2013-09-23 0intro return 0;
1826 6f4d00ee 2013-09-23 0intro sourceUnlock(f->source);
1827 6f4d00ee 2013-09-23 0intro sourceUnlock(f->msource);
1828 6f4d00ee 2013-09-23 0intro return 1;
1832 6f4d00ee 2013-09-23 0intro * convert File* to full path name in malloced string.
1833 6f4d00ee 2013-09-23 0intro * this hasn't been as useful as we hoped it would be.
1836 6f4d00ee 2013-09-23 0intro fileName(File *f)
1838 6f4d00ee 2013-09-23 0intro char *name, *pname;
1839 6f4d00ee 2013-09-23 0intro File *p;
1840 6f4d00ee 2013-09-23 0intro static char root[] = "/";
1842 6f4d00ee 2013-09-23 0intro if (f == nil)
1843 4b576658 2013-09-23 0intro return vtstrdup("/**GOK**");
1845 6f4d00ee 2013-09-23 0intro p = fileGetParent(f);
1846 6f4d00ee 2013-09-23 0intro if (p == f)
1847 4b576658 2013-09-23 0intro name = vtstrdup(root);
1849 6f4d00ee 2013-09-23 0intro pname = fileName(p);
1850 6f4d00ee 2013-09-23 0intro if (strcmp(pname, root) == 0)
1851 6f4d00ee 2013-09-23 0intro name = smprint("/%s", f->dir.elem);
1853 6f4d00ee 2013-09-23 0intro name = smprint("%s/%s", pname, f->dir.elem);
1854 6f4d00ee 2013-09-23 0intro free(pname);
1856 6f4d00ee 2013-09-23 0intro fileDecRef(p);
1857 6f4d00ee 2013-09-23 0intro return name;