15e96a66cSDavid du Colombier #include "stdinc.h"
23b86f2f8SDavid du Colombier #include "9.h" /* for consPrint */
35e96a66cSDavid du Colombier #include "dat.h"
45e96a66cSDavid du Colombier #include "fns.h"
55e96a66cSDavid du Colombier #include "error.h"
65e96a66cSDavid du Colombier
75e96a66cSDavid du Colombier /*
85e96a66cSDavid du Colombier * locking order is upwards. A thread can hold the lock for a File
95e96a66cSDavid du Colombier * and then acquire the lock of its parent
105e96a66cSDavid du Colombier */
115e96a66cSDavid du Colombier
125e96a66cSDavid du Colombier struct File {
135e96a66cSDavid du Colombier Fs *fs; /* immutable */
145e96a66cSDavid du Colombier
155e96a66cSDavid du Colombier /* meta data for file: protected by the lk in the parent */
165e96a66cSDavid du Colombier int ref; /* holds this data structure up */
175e96a66cSDavid du Colombier
185e96a66cSDavid du Colombier int partial; /* file was never really open */
195e96a66cSDavid du Colombier int removed; /* file has been removed */
205e96a66cSDavid du Colombier int dirty; /* dir is dirty with respect to meta data in block */
215e96a66cSDavid du Colombier u32int boff; /* block offset within msource for this file's meta data */
225e96a66cSDavid du Colombier
233b86f2f8SDavid du Colombier DirEntry dir; /* meta data for this file, including component name */
245e96a66cSDavid du Colombier
253b86f2f8SDavid du Colombier File *up; /* parent file (directory) */
265e96a66cSDavid du Colombier File *next; /* sibling */
275e96a66cSDavid du Colombier
285e96a66cSDavid du Colombier /* data for file */
295e96a66cSDavid du Colombier VtLock *lk; /* lock for the following */
305e96a66cSDavid du Colombier Source *source;
315e96a66cSDavid du Colombier Source *msource; /* for directories: meta data for children */
325e96a66cSDavid du Colombier File *down; /* children */
335e96a66cSDavid du Colombier
345e96a66cSDavid du Colombier int mode;
3557195852SDavid du Colombier int issnapshot;
365e96a66cSDavid du Colombier };
375e96a66cSDavid du Colombier
385e96a66cSDavid du Colombier static int fileMetaFlush2(File*, char*);
395e96a66cSDavid du Colombier static u32int fileMetaAlloc(File*, DirEntry*, u32int);
405e96a66cSDavid du Colombier static int fileRLock(File*);
415e96a66cSDavid du Colombier static void fileRUnlock(File*);
425e96a66cSDavid du Colombier static int fileLock(File*);
435e96a66cSDavid du Colombier static void fileUnlock(File*);
445e96a66cSDavid du Colombier static void fileMetaLock(File*);
455e96a66cSDavid du Colombier static void fileMetaUnlock(File*);
465e96a66cSDavid du Colombier static void fileRAccess(File*);
475e96a66cSDavid du Colombier static void fileWAccess(File*, char*);
485e96a66cSDavid du Colombier
495e96a66cSDavid du Colombier static File *
fileAlloc(Fs * fs)505e96a66cSDavid du Colombier fileAlloc(Fs *fs)
515e96a66cSDavid du Colombier {
525e96a66cSDavid du Colombier File *f;
535e96a66cSDavid du Colombier
545e96a66cSDavid du Colombier f = vtMemAllocZ(sizeof(File));
555e96a66cSDavid du Colombier f->lk = vtLockAlloc();
565e96a66cSDavid du Colombier f->ref = 1;
575e96a66cSDavid du Colombier f->fs = fs;
585e96a66cSDavid du Colombier f->boff = NilBlock;
595e96a66cSDavid du Colombier f->mode = fs->mode;
605e96a66cSDavid du Colombier return f;
615e96a66cSDavid du Colombier }
625e96a66cSDavid du Colombier
635e96a66cSDavid du Colombier static void
fileFree(File * f)645e96a66cSDavid du Colombier fileFree(File *f)
655e96a66cSDavid du Colombier {
665e96a66cSDavid du Colombier sourceClose(f->source);
675e96a66cSDavid du Colombier vtLockFree(f->lk);
685e96a66cSDavid du Colombier sourceClose(f->msource);
695e96a66cSDavid du Colombier deCleanup(&f->dir);
705e96a66cSDavid du Colombier
715e96a66cSDavid du Colombier memset(f, ~0, sizeof(File));
725e96a66cSDavid du Colombier vtMemFree(f);
735e96a66cSDavid du Colombier }
745e96a66cSDavid du Colombier
755e96a66cSDavid du Colombier /*
765e96a66cSDavid du Colombier * the file is locked already
775e96a66cSDavid du Colombier * f->msource is unlocked
785e96a66cSDavid du Colombier */
795e96a66cSDavid du Colombier static File *
dirLookup(File * f,char * elem)805e96a66cSDavid du Colombier dirLookup(File *f, char *elem)
815e96a66cSDavid du Colombier {
825e96a66cSDavid du Colombier int i;
835e96a66cSDavid du Colombier MetaBlock mb;
845e96a66cSDavid du Colombier MetaEntry me;
855e96a66cSDavid du Colombier Block *b;
865e96a66cSDavid du Colombier Source *meta;
875e96a66cSDavid du Colombier File *ff;
885e96a66cSDavid du Colombier u32int bo, nb;
895e96a66cSDavid du Colombier
905e96a66cSDavid du Colombier meta = f->msource;
915e96a66cSDavid du Colombier b = nil;
925e96a66cSDavid du Colombier if(!sourceLock(meta, -1))
935e96a66cSDavid du Colombier return nil;
945e96a66cSDavid du Colombier nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize;
955e96a66cSDavid du Colombier for(bo=0; bo<nb; bo++){
965e96a66cSDavid du Colombier b = sourceBlock(meta, bo, OReadOnly);
975e96a66cSDavid du Colombier if(b == nil)
985e96a66cSDavid du Colombier goto Err;
995e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize))
1005e96a66cSDavid du Colombier goto Err;
1015e96a66cSDavid du Colombier if(mbSearch(&mb, elem, &i, &me)){
1025e96a66cSDavid du Colombier ff = fileAlloc(f->fs);
1035e96a66cSDavid du Colombier if(!deUnpack(&ff->dir, &me)){
1045e96a66cSDavid du Colombier fileFree(ff);
1055e96a66cSDavid du Colombier goto Err;
1065e96a66cSDavid du Colombier }
1075e96a66cSDavid du Colombier sourceUnlock(meta);
1085e96a66cSDavid du Colombier blockPut(b);
1095e96a66cSDavid du Colombier ff->boff = bo;
1105e96a66cSDavid du Colombier ff->mode = f->mode;
11157195852SDavid du Colombier ff->issnapshot = f->issnapshot;
1125e96a66cSDavid du Colombier return ff;
1135e96a66cSDavid du Colombier }
1145e96a66cSDavid du Colombier
1155e96a66cSDavid du Colombier blockPut(b);
1165e96a66cSDavid du Colombier b = nil;
1175e96a66cSDavid du Colombier }
1185e96a66cSDavid du Colombier vtSetError(ENoFile);
1195e96a66cSDavid du Colombier /* fall through */
1205e96a66cSDavid du Colombier Err:
1215e96a66cSDavid du Colombier sourceUnlock(meta);
1225e96a66cSDavid du Colombier blockPut(b);
1235e96a66cSDavid du Colombier return nil;
1245e96a66cSDavid du Colombier }
1255e96a66cSDavid du Colombier
1265e96a66cSDavid du Colombier File *
fileRoot(Source * r)1275e96a66cSDavid du Colombier fileRoot(Source *r)
1285e96a66cSDavid du Colombier {
1295e96a66cSDavid du Colombier Block *b;
1305e96a66cSDavid du Colombier Source *r0, *r1, *r2;
1315e96a66cSDavid du Colombier MetaBlock mb;
1325e96a66cSDavid du Colombier MetaEntry me;
1335e96a66cSDavid du Colombier File *root, *mr;
1345e96a66cSDavid du Colombier Fs *fs;
1355e96a66cSDavid du Colombier
1365e96a66cSDavid du Colombier b = nil;
1375e96a66cSDavid du Colombier root = nil;
1385e96a66cSDavid du Colombier mr = nil;
1395e96a66cSDavid du Colombier r1 = nil;
1405e96a66cSDavid du Colombier r2 = nil;
1415e96a66cSDavid du Colombier
1425e96a66cSDavid du Colombier fs = r->fs;
1435e96a66cSDavid du Colombier if(!sourceLock(r, -1))
1445e96a66cSDavid du Colombier return nil;
14557195852SDavid du Colombier r0 = sourceOpen(r, 0, fs->mode, 0);
1465e96a66cSDavid du Colombier if(r0 == nil)
1475e96a66cSDavid du Colombier goto Err;
14857195852SDavid du Colombier r1 = sourceOpen(r, 1, fs->mode, 0);
1495e96a66cSDavid du Colombier if(r1 == nil)
1505e96a66cSDavid du Colombier goto Err;
15157195852SDavid du Colombier r2 = sourceOpen(r, 2, fs->mode, 0);
1525e96a66cSDavid du Colombier if(r2 == nil)
1535e96a66cSDavid du Colombier goto Err;
1545e96a66cSDavid du Colombier
1555e96a66cSDavid du Colombier mr = fileAlloc(fs);
1565e96a66cSDavid du Colombier mr->msource = r2;
1575e96a66cSDavid du Colombier r2 = nil;
1585e96a66cSDavid du Colombier
1595e96a66cSDavid du Colombier root = fileAlloc(fs);
1605e96a66cSDavid du Colombier root->boff = 0;
1615e96a66cSDavid du Colombier root->up = mr;
1625e96a66cSDavid du Colombier root->source = r0;
1633b86f2f8SDavid du Colombier r0->file = root; /* point back to source */
1645e96a66cSDavid du Colombier r0 = nil;
1655e96a66cSDavid du Colombier root->msource = r1;
1665e96a66cSDavid du Colombier r1 = nil;
1675e96a66cSDavid du Colombier
1685e96a66cSDavid du Colombier mr->down = root;
1695e96a66cSDavid du Colombier
1705e96a66cSDavid du Colombier if(!sourceLock(mr->msource, -1))
1715e96a66cSDavid du Colombier goto Err;
1725e96a66cSDavid du Colombier b = sourceBlock(mr->msource, 0, OReadOnly);
1735e96a66cSDavid du Colombier sourceUnlock(mr->msource);
1745e96a66cSDavid du Colombier if(b == nil)
1755e96a66cSDavid du Colombier goto Err;
1765e96a66cSDavid du Colombier
1775e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, mr->msource->dsize))
1785e96a66cSDavid du Colombier goto Err;
1795e96a66cSDavid du Colombier
1805e96a66cSDavid du Colombier meUnpack(&me, &mb, 0);
1815e96a66cSDavid du Colombier if(!deUnpack(&root->dir, &me))
1825e96a66cSDavid du Colombier goto Err;
1835e96a66cSDavid du Colombier blockPut(b);
1845e96a66cSDavid du Colombier sourceUnlock(r);
1855e96a66cSDavid du Colombier fileRAccess(root);
1865e96a66cSDavid du Colombier
1875e96a66cSDavid du Colombier return root;
1885e96a66cSDavid du Colombier Err:
1895e96a66cSDavid du Colombier blockPut(b);
1905e96a66cSDavid du Colombier if(r0)
1915e96a66cSDavid du Colombier sourceClose(r0);
1925e96a66cSDavid du Colombier if(r1)
1935e96a66cSDavid du Colombier sourceClose(r1);
1945e96a66cSDavid du Colombier if(r2)
1955e96a66cSDavid du Colombier sourceClose(r2);
1965e96a66cSDavid du Colombier if(mr)
1975e96a66cSDavid du Colombier fileFree(mr);
1985e96a66cSDavid du Colombier if(root)
1995e96a66cSDavid du Colombier fileFree(root);
2005e96a66cSDavid du Colombier sourceUnlock(r);
2015e96a66cSDavid du Colombier
2025e96a66cSDavid du Colombier return nil;
2035e96a66cSDavid du Colombier }
2045e96a66cSDavid du Colombier
2055e96a66cSDavid du Colombier static Source *
fileOpenSource(File * f,u32int offset,u32int gen,int dir,uint mode,int issnapshot)2063b86f2f8SDavid du Colombier fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode,
2073b86f2f8SDavid du Colombier int issnapshot)
2085e96a66cSDavid du Colombier {
2093b86f2f8SDavid du Colombier char *rname, *fname;
2105e96a66cSDavid du Colombier Source *r;
2115e96a66cSDavid du Colombier
2125e96a66cSDavid du Colombier if(!sourceLock(f->source, mode))
2135e96a66cSDavid du Colombier return nil;
21457195852SDavid du Colombier r = sourceOpen(f->source, offset, mode, issnapshot);
2155e96a66cSDavid du Colombier sourceUnlock(f->source);
2165e96a66cSDavid du Colombier if(r == nil)
2175e96a66cSDavid du Colombier return nil;
2185e96a66cSDavid du Colombier if(r->gen != gen){
2195e96a66cSDavid du Colombier vtSetError(ERemoved);
2205e96a66cSDavid du Colombier goto Err;
2215e96a66cSDavid du Colombier }
2225e96a66cSDavid du Colombier if(r->dir != dir && r->mode != -1){
2233b86f2f8SDavid du Colombier /* this hasn't been as useful as we hoped it would be. */
2243b86f2f8SDavid du Colombier rname = sourceName(r);
2253b86f2f8SDavid du Colombier fname = fileName(f);
2263b86f2f8SDavid du Colombier consPrint("%s: source %s for file %s: fileOpenSource: "
2273b86f2f8SDavid du Colombier "dir mismatch %d %d\n",
2283b86f2f8SDavid du Colombier f->source->fs->name, rname, fname, r->dir, dir);
2293b86f2f8SDavid du Colombier free(rname);
2303b86f2f8SDavid du Colombier free(fname);
2313b86f2f8SDavid du Colombier
2325e96a66cSDavid du Colombier vtSetError(EBadMeta);
2335e96a66cSDavid du Colombier goto Err;
2345e96a66cSDavid du Colombier }
2355e96a66cSDavid du Colombier return r;
2365e96a66cSDavid du Colombier Err:
2375e96a66cSDavid du Colombier sourceClose(r);
2385e96a66cSDavid du Colombier return nil;
2395e96a66cSDavid du Colombier }
2405e96a66cSDavid du Colombier
2415e96a66cSDavid du Colombier File *
_fileWalk(File * f,char * elem,int partial)2425e96a66cSDavid du Colombier _fileWalk(File *f, char *elem, int partial)
2435e96a66cSDavid du Colombier {
2445e96a66cSDavid du Colombier File *ff;
2455e96a66cSDavid du Colombier
2465e96a66cSDavid du Colombier fileRAccess(f);
2475e96a66cSDavid du Colombier
2485e96a66cSDavid du Colombier if(elem[0] == 0){
2495e96a66cSDavid du Colombier vtSetError(EBadPath);
2505e96a66cSDavid du Colombier return nil;
2515e96a66cSDavid du Colombier }
2525e96a66cSDavid du Colombier
2535e96a66cSDavid du Colombier if(!fileIsDir(f)){
2545e96a66cSDavid du Colombier vtSetError(ENotDir);
2555e96a66cSDavid du Colombier return nil;
2565e96a66cSDavid du Colombier }
2575e96a66cSDavid du Colombier
2585e96a66cSDavid du Colombier if(strcmp(elem, ".") == 0){
2595e96a66cSDavid du Colombier return fileIncRef(f);
2605e96a66cSDavid du Colombier }
2615e96a66cSDavid du Colombier
2625e96a66cSDavid du Colombier if(strcmp(elem, "..") == 0){
2635e96a66cSDavid du Colombier if(fileIsRoot(f))
2645e96a66cSDavid du Colombier return fileIncRef(f);
2655e96a66cSDavid du Colombier return fileIncRef(f->up);
2665e96a66cSDavid du Colombier }
2675e96a66cSDavid du Colombier
2685e96a66cSDavid du Colombier if(!fileLock(f))
2695e96a66cSDavid du Colombier return nil;
2705e96a66cSDavid du Colombier
2715e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){
2725e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
2735e96a66cSDavid du Colombier ff->ref++;
2745e96a66cSDavid du Colombier goto Exit;
2755e96a66cSDavid du Colombier }
2765e96a66cSDavid du Colombier }
2775e96a66cSDavid du Colombier
2785e96a66cSDavid du Colombier ff = dirLookup(f, elem);
2795e96a66cSDavid du Colombier if(ff == nil)
2805e96a66cSDavid du Colombier goto Err;
2815e96a66cSDavid du Colombier
28257195852SDavid du Colombier if(ff->dir.mode & ModeSnapshot){
2835e96a66cSDavid du Colombier ff->mode = OReadOnly;
28457195852SDavid du Colombier ff->issnapshot = 1;
28557195852SDavid du Colombier }
2865e96a66cSDavid du Colombier
2875e96a66cSDavid du Colombier if(partial){
2885e96a66cSDavid du Colombier /*
2895e96a66cSDavid du Colombier * Do nothing. We're opening this file only so we can clri it.
2905e96a66cSDavid du Colombier * Usually the sources can't be opened, hence we won't even bother.
2915e96a66cSDavid du Colombier * Be VERY careful with the returned file. If you hand it to a routine
2925e96a66cSDavid du Colombier * expecting ff->source and/or ff->msource to be non-nil, we're
2935e96a66cSDavid du Colombier * likely to dereference nil. FileClri should be the only routine
2945e96a66cSDavid du Colombier * setting partial.
2955e96a66cSDavid du Colombier */
2965e96a66cSDavid du Colombier ff->partial = 1;
2975e96a66cSDavid du Colombier }else if(ff->dir.mode & ModeDir){
2983b86f2f8SDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
2993b86f2f8SDavid du Colombier 1, ff->mode, ff->issnapshot);
3003b86f2f8SDavid du Colombier ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen,
3013b86f2f8SDavid du Colombier 0, ff->mode, ff->issnapshot);
3025e96a66cSDavid du Colombier if(ff->source == nil || ff->msource == nil)
3035e96a66cSDavid du Colombier goto Err;
3045e96a66cSDavid du Colombier }else{
3053b86f2f8SDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
3063b86f2f8SDavid du Colombier 0, ff->mode, ff->issnapshot);
3075e96a66cSDavid du Colombier if(ff->source == nil)
3085e96a66cSDavid du Colombier goto Err;
3095e96a66cSDavid du Colombier }
3105e96a66cSDavid du Colombier
3115e96a66cSDavid du Colombier /* link in and up parent ref count */
3123b86f2f8SDavid du Colombier if (ff->source)
3133b86f2f8SDavid du Colombier ff->source->file = ff; /* point back */
3145e96a66cSDavid du Colombier ff->next = f->down;
3155e96a66cSDavid du Colombier f->down = ff;
3165e96a66cSDavid du Colombier ff->up = f;
3175e96a66cSDavid du Colombier fileIncRef(f);
3185e96a66cSDavid du Colombier Exit:
3195e96a66cSDavid du Colombier fileUnlock(f);
3205e96a66cSDavid du Colombier return ff;
3215e96a66cSDavid du Colombier Err:
3225e96a66cSDavid du Colombier fileUnlock(f);
3235e96a66cSDavid du Colombier if(ff != nil)
3245e96a66cSDavid du Colombier fileDecRef(ff);
3255e96a66cSDavid du Colombier return nil;
3265e96a66cSDavid du Colombier }
3275e96a66cSDavid du Colombier
3285e96a66cSDavid du Colombier File *
fileWalk(File * f,char * elem)3295e96a66cSDavid du Colombier fileWalk(File *f, char *elem)
3305e96a66cSDavid du Colombier {
3315e96a66cSDavid du Colombier return _fileWalk(f, elem, 0);
3325e96a66cSDavid du Colombier }
3335e96a66cSDavid du Colombier
3345e96a66cSDavid du Colombier File *
_fileOpen(Fs * fs,char * path,int partial)3355e96a66cSDavid du Colombier _fileOpen(Fs *fs, char *path, int partial)
3365e96a66cSDavid du Colombier {
3375e96a66cSDavid du Colombier File *f, *ff;
338f8e525acSDavid du Colombier char *p, elem[VtMaxStringSize], *opath;
3395e96a66cSDavid du Colombier int n;
3405e96a66cSDavid du Colombier
3415e96a66cSDavid du Colombier f = fs->file;
3425e96a66cSDavid du Colombier fileIncRef(f);
343f8e525acSDavid du Colombier opath = path;
3445e96a66cSDavid du Colombier while(*path != 0){
3455e96a66cSDavid du Colombier for(p = path; *p && *p != '/'; p++)
3465e96a66cSDavid du Colombier ;
3475e96a66cSDavid du Colombier n = p - path;
3485e96a66cSDavid du Colombier if(n > 0){
3495e96a66cSDavid du Colombier if(n > VtMaxStringSize){
350f8e525acSDavid du Colombier vtSetError("%s: element too long", EBadPath);
3515e96a66cSDavid du Colombier goto Err;
3525e96a66cSDavid du Colombier }
3535e96a66cSDavid du Colombier memmove(elem, path, n);
3545e96a66cSDavid du Colombier elem[n] = 0;
3555e96a66cSDavid du Colombier ff = _fileWalk(f, elem, partial && *p=='\0');
356f8e525acSDavid du Colombier if(ff == nil){
3573b86f2f8SDavid du Colombier vtSetError("%.*s: %R", utfnlen(opath, p-opath),
3583b86f2f8SDavid du Colombier opath);
3595e96a66cSDavid du Colombier goto Err;
360f8e525acSDavid du Colombier }
3615e96a66cSDavid du Colombier fileDecRef(f);
3625e96a66cSDavid du Colombier f = ff;
3635e96a66cSDavid du Colombier }
3645e96a66cSDavid du Colombier if(*p == '/')
3655e96a66cSDavid du Colombier p++;
3665e96a66cSDavid du Colombier path = p;
3675e96a66cSDavid du Colombier }
3685e96a66cSDavid du Colombier return f;
3695e96a66cSDavid du Colombier Err:
3705e96a66cSDavid du Colombier fileDecRef(f);
3715e96a66cSDavid du Colombier return nil;
3725e96a66cSDavid du Colombier }
3735e96a66cSDavid du Colombier
3745e96a66cSDavid du Colombier File*
fileOpen(Fs * fs,char * path)3755e96a66cSDavid du Colombier fileOpen(Fs *fs, char *path)
3765e96a66cSDavid du Colombier {
3775e96a66cSDavid du Colombier return _fileOpen(fs, path, 0);
3785e96a66cSDavid du Colombier }
3795e96a66cSDavid du Colombier
380fe853e23SDavid du Colombier static void
fileSetTmp(File * f,int istmp)381fe853e23SDavid du Colombier fileSetTmp(File *f, int istmp)
382fe853e23SDavid du Colombier {
383fe853e23SDavid du Colombier int i;
384fe853e23SDavid du Colombier Entry e;
385fe853e23SDavid du Colombier Source *r;
386fe853e23SDavid du Colombier
387fe853e23SDavid du Colombier for(i=0; i<2; i++){
388fe853e23SDavid du Colombier if(i==0)
389fe853e23SDavid du Colombier r = f->source;
390fe853e23SDavid du Colombier else
391fe853e23SDavid du Colombier r = f->msource;
392fe853e23SDavid du Colombier if(r == nil)
393fe853e23SDavid du Colombier continue;
394f352e144SDavid du Colombier if(!sourceGetEntry(r, &e)){
395fe853e23SDavid du Colombier fprint(2, "sourceGetEntry failed (cannot happen): %r\n");
396fe853e23SDavid du Colombier continue;
397fe853e23SDavid du Colombier }
398fe853e23SDavid du Colombier if(istmp)
399fe853e23SDavid du Colombier e.flags |= VtEntryNoArchive;
400fe853e23SDavid du Colombier else
401fe853e23SDavid du Colombier e.flags &= ~VtEntryNoArchive;
402f352e144SDavid du Colombier if(!sourceSetEntry(r, &e)){
403fe853e23SDavid du Colombier fprint(2, "sourceSetEntry failed (cannot happen): %r\n");
404fe853e23SDavid du Colombier continue;
405fe853e23SDavid du Colombier }
406fe853e23SDavid du Colombier }
407fe853e23SDavid du Colombier }
408fe853e23SDavid du Colombier
4095e96a66cSDavid du Colombier File *
fileCreate(File * f,char * elem,ulong mode,char * uid)4105e96a66cSDavid du Colombier fileCreate(File *f, char *elem, ulong mode, char *uid)
4115e96a66cSDavid du Colombier {
4125e96a66cSDavid du Colombier File *ff;
4135e96a66cSDavid du Colombier DirEntry *dir;
4145e96a66cSDavid du Colombier Source *pr, *r, *mr;
4155e96a66cSDavid du Colombier int isdir;
4165e96a66cSDavid du Colombier
4175e96a66cSDavid du Colombier if(!fileLock(f))
4185e96a66cSDavid du Colombier return nil;
4195e96a66cSDavid du Colombier
4205e96a66cSDavid du Colombier r = nil;
4215e96a66cSDavid du Colombier mr = nil;
4225e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){
4235e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
4245e96a66cSDavid du Colombier ff = nil;
4255e96a66cSDavid du Colombier vtSetError(EExists);
4265e96a66cSDavid du Colombier goto Err1;
4275e96a66cSDavid du Colombier }
4285e96a66cSDavid du Colombier }
4295e96a66cSDavid du Colombier
4305e96a66cSDavid du Colombier ff = dirLookup(f, elem);
4315e96a66cSDavid du Colombier if(ff != nil){
4325e96a66cSDavid du Colombier vtSetError(EExists);
4335e96a66cSDavid du Colombier goto Err1;
4345e96a66cSDavid du Colombier }
4355e96a66cSDavid du Colombier
4365e96a66cSDavid du Colombier pr = f->source;
4375e96a66cSDavid du Colombier if(pr->mode != OReadWrite){
4385e96a66cSDavid du Colombier vtSetError(EReadOnly);
4395e96a66cSDavid du Colombier goto Err1;
4405e96a66cSDavid du Colombier }
4415e96a66cSDavid du Colombier
4425e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1))
4435e96a66cSDavid du Colombier goto Err1;
4445e96a66cSDavid du Colombier
4455e96a66cSDavid du Colombier ff = fileAlloc(f->fs);
4465e96a66cSDavid du Colombier isdir = mode & ModeDir;
4475e96a66cSDavid du Colombier
4485e96a66cSDavid du Colombier r = sourceCreate(pr, pr->dsize, isdir, 0);
4495e96a66cSDavid du Colombier if(r == nil)
4505e96a66cSDavid du Colombier goto Err;
4515e96a66cSDavid du Colombier if(isdir){
4525e96a66cSDavid du Colombier mr = sourceCreate(pr, pr->dsize, 0, r->offset);
4535e96a66cSDavid du Colombier if(mr == nil)
4545e96a66cSDavid du Colombier goto Err;
4555e96a66cSDavid du Colombier }
4565e96a66cSDavid du Colombier
4575e96a66cSDavid du Colombier dir = &ff->dir;
4585e96a66cSDavid du Colombier dir->elem = vtStrDup(elem);
4595e96a66cSDavid du Colombier dir->entry = r->offset;
4605e96a66cSDavid du Colombier dir->gen = r->gen;
4615e96a66cSDavid du Colombier if(isdir){
4625e96a66cSDavid du Colombier dir->mentry = mr->offset;
4635e96a66cSDavid du Colombier dir->mgen = mr->gen;
4645e96a66cSDavid du Colombier }
4655e96a66cSDavid du Colombier dir->size = 0;
4665e96a66cSDavid du Colombier if(!fsNextQid(f->fs, &dir->qid))
4675e96a66cSDavid du Colombier goto Err;
4685e96a66cSDavid du Colombier dir->uid = vtStrDup(uid);
4695e96a66cSDavid du Colombier dir->gid = vtStrDup(f->dir.gid);
4705e96a66cSDavid du Colombier dir->mid = vtStrDup(uid);
4715e96a66cSDavid du Colombier dir->mtime = time(0L);
4725e96a66cSDavid du Colombier dir->mcount = 0;
4735e96a66cSDavid du Colombier dir->ctime = dir->mtime;
4745e96a66cSDavid du Colombier dir->atime = dir->mtime;
4755e96a66cSDavid du Colombier dir->mode = mode;
4765e96a66cSDavid du Colombier
4775e96a66cSDavid du Colombier ff->boff = fileMetaAlloc(f, dir, 0);
4785e96a66cSDavid du Colombier if(ff->boff == NilBlock)
4795e96a66cSDavid du Colombier goto Err;
4805e96a66cSDavid du Colombier
4815e96a66cSDavid du Colombier sourceUnlock(f->source);
4825e96a66cSDavid du Colombier sourceUnlock(f->msource);
4835e96a66cSDavid du Colombier
4845e96a66cSDavid du Colombier ff->source = r;
4853b86f2f8SDavid du Colombier r->file = ff; /* point back */
4865e96a66cSDavid du Colombier ff->msource = mr;
4875e96a66cSDavid du Colombier
488fe853e23SDavid du Colombier if(mode&ModeTemporary){
489fe853e23SDavid du Colombier if(!sourceLock2(r, mr, -1))
490fe853e23SDavid du Colombier goto Err1;
491fe853e23SDavid du Colombier fileSetTmp(ff, 1);
492fe853e23SDavid du Colombier sourceUnlock(r);
493fe853e23SDavid du Colombier if(mr)
494fe853e23SDavid du Colombier sourceUnlock(mr);
495fe853e23SDavid du Colombier }
496fe853e23SDavid du Colombier
497fe853e23SDavid du Colombier /* committed */
498fe853e23SDavid du Colombier
4995e96a66cSDavid du Colombier /* link in and up parent ref count */
5005e96a66cSDavid du Colombier ff->next = f->down;
5015e96a66cSDavid du Colombier f->down = ff;
5025e96a66cSDavid du Colombier ff->up = f;
5035e96a66cSDavid du Colombier fileIncRef(f);
5045e96a66cSDavid du Colombier
5055e96a66cSDavid du Colombier fileWAccess(f, uid);
5065e96a66cSDavid du Colombier
5075e96a66cSDavid du Colombier fileUnlock(f);
5085e96a66cSDavid du Colombier return ff;
5095e96a66cSDavid du Colombier
5105e96a66cSDavid du Colombier Err:
5115e96a66cSDavid du Colombier sourceUnlock(f->source);
5125e96a66cSDavid du Colombier sourceUnlock(f->msource);
5135e96a66cSDavid du Colombier Err1:
514dc5a79c1SDavid du Colombier if(r){
515dc5a79c1SDavid du Colombier sourceLock(r, -1);
5165e96a66cSDavid du Colombier sourceRemove(r);
517dc5a79c1SDavid du Colombier }
518dc5a79c1SDavid du Colombier if(mr){
519dc5a79c1SDavid du Colombier sourceLock(mr, -1);
5205e96a66cSDavid du Colombier sourceRemove(mr);
521dc5a79c1SDavid du Colombier }
5225e96a66cSDavid du Colombier if(ff)
5235e96a66cSDavid du Colombier fileDecRef(ff);
5245e96a66cSDavid du Colombier fileUnlock(f);
5255e96a66cSDavid du Colombier return 0;
5265e96a66cSDavid du Colombier }
5275e96a66cSDavid du Colombier
5285e96a66cSDavid du Colombier int
fileRead(File * f,void * buf,int cnt,vlong offset)5295e96a66cSDavid du Colombier fileRead(File *f, void *buf, int cnt, vlong offset)
5305e96a66cSDavid du Colombier {
5315e96a66cSDavid du Colombier Source *s;
5325e96a66cSDavid du Colombier uvlong size;
5335e96a66cSDavid du Colombier u32int bn;
5345e96a66cSDavid du Colombier int off, dsize, n, nn;
5355e96a66cSDavid du Colombier Block *b;
5365e96a66cSDavid du Colombier uchar *p;
5375e96a66cSDavid du Colombier
5385e96a66cSDavid du Colombier if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
5395e96a66cSDavid du Colombier
5405e96a66cSDavid du Colombier if(!fileRLock(f))
5415e96a66cSDavid du Colombier return -1;
5425e96a66cSDavid du Colombier
5435e96a66cSDavid du Colombier if(offset < 0){
5445e96a66cSDavid du Colombier vtSetError(EBadOffset);
5455e96a66cSDavid du Colombier goto Err1;
5465e96a66cSDavid du Colombier }
5475e96a66cSDavid du Colombier
5485e96a66cSDavid du Colombier fileRAccess(f);
5495e96a66cSDavid du Colombier
5505e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly))
5515e96a66cSDavid du Colombier goto Err1;
5525e96a66cSDavid du Colombier
5535e96a66cSDavid du Colombier s = f->source;
5545e96a66cSDavid du Colombier dsize = s->dsize;
5555e96a66cSDavid du Colombier size = sourceGetSize(s);
5565e96a66cSDavid du Colombier
5575e96a66cSDavid du Colombier if(offset >= size)
5585e96a66cSDavid du Colombier offset = size;
5595e96a66cSDavid du Colombier
5605e96a66cSDavid du Colombier if(cnt > size-offset)
5615e96a66cSDavid du Colombier cnt = size-offset;
5625e96a66cSDavid du Colombier bn = offset/dsize;
5635e96a66cSDavid du Colombier off = offset%dsize;
5645e96a66cSDavid du Colombier p = buf;
5655e96a66cSDavid du Colombier while(cnt > 0){
5665e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly);
5675e96a66cSDavid du Colombier if(b == nil)
5685e96a66cSDavid du Colombier goto Err;
5695e96a66cSDavid du Colombier n = cnt;
5705e96a66cSDavid du Colombier if(n > dsize-off)
5715e96a66cSDavid du Colombier n = dsize-off;
5725e96a66cSDavid du Colombier nn = dsize-off;
5735e96a66cSDavid du Colombier if(nn > n)
5745e96a66cSDavid du Colombier nn = n;
5755e96a66cSDavid du Colombier memmove(p, b->data+off, nn);
5765e96a66cSDavid du Colombier memset(p+nn, 0, nn-n);
5775e96a66cSDavid du Colombier off = 0;
5785e96a66cSDavid du Colombier bn++;
5795e96a66cSDavid du Colombier cnt -= n;
5805e96a66cSDavid du Colombier p += n;
5815e96a66cSDavid du Colombier blockPut(b);
5825e96a66cSDavid du Colombier }
5835e96a66cSDavid du Colombier sourceUnlock(s);
5845e96a66cSDavid du Colombier fileRUnlock(f);
5855e96a66cSDavid du Colombier return p-(uchar*)buf;
5865e96a66cSDavid du Colombier
5875e96a66cSDavid du Colombier Err:
5885e96a66cSDavid du Colombier sourceUnlock(s);
5895e96a66cSDavid du Colombier Err1:
5905e96a66cSDavid du Colombier fileRUnlock(f);
5915e96a66cSDavid du Colombier return -1;
5925e96a66cSDavid du Colombier }
5935e96a66cSDavid du Colombier
594fe853e23SDavid du Colombier /*
595fe853e23SDavid du Colombier * Changes the file block bn to be the given block score.
596fe853e23SDavid du Colombier * Very sneaky. Only used by flfmt.
597fe853e23SDavid du Colombier */
598fe853e23SDavid du Colombier int
fileMapBlock(File * f,ulong bn,uchar score[VtScoreSize],ulong tag)599fe853e23SDavid du Colombier fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag)
600fe853e23SDavid du Colombier {
601fe853e23SDavid du Colombier Block *b;
602fe853e23SDavid du Colombier Entry e;
603fe853e23SDavid du Colombier Source *s;
604fe853e23SDavid du Colombier
605fe853e23SDavid du Colombier if(!fileLock(f))
606fe853e23SDavid du Colombier return 0;
607fe853e23SDavid du Colombier
608fe853e23SDavid du Colombier s = nil;
609fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){
610fe853e23SDavid du Colombier vtSetError(ENotFile);
611fe853e23SDavid du Colombier goto Err;
612fe853e23SDavid du Colombier }
613fe853e23SDavid du Colombier
614fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){
615fe853e23SDavid du Colombier vtSetError(EReadOnly);
616fe853e23SDavid du Colombier goto Err;
617fe853e23SDavid du Colombier }
618fe853e23SDavid du Colombier
619fe853e23SDavid du Colombier if(!sourceLock(f->source, -1))
620fe853e23SDavid du Colombier goto Err;
621fe853e23SDavid du Colombier
622fe853e23SDavid du Colombier s = f->source;
623fe853e23SDavid du Colombier b = _sourceBlock(s, bn, OReadWrite, 1, tag);
624fe853e23SDavid du Colombier if(b == nil)
625fe853e23SDavid du Colombier goto Err;
626fe853e23SDavid du Colombier
627fe853e23SDavid du Colombier if(!sourceGetEntry(s, &e))
628fe853e23SDavid du Colombier goto Err;
629fe853e23SDavid du Colombier if(b->l.type == BtDir){
630fe853e23SDavid du Colombier memmove(e.score, score, VtScoreSize);
631fe853e23SDavid du Colombier assert(e.tag == tag || e.tag == 0);
632fe853e23SDavid du Colombier e.tag = tag;
633fe853e23SDavid du Colombier e.flags |= VtEntryLocal;
634fe853e23SDavid du Colombier entryPack(&e, b->data, f->source->offset % f->source->epb);
635fe853e23SDavid du Colombier }else
636fe853e23SDavid du Colombier memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
637fe853e23SDavid du Colombier blockDirty(b);
638fe853e23SDavid du Colombier blockPut(b);
639fe853e23SDavid du Colombier sourceUnlock(s);
640fe853e23SDavid du Colombier fileUnlock(f);
641fe853e23SDavid du Colombier return 1;
642fe853e23SDavid du Colombier
643fe853e23SDavid du Colombier Err:
644fe853e23SDavid du Colombier if(s)
645fe853e23SDavid du Colombier sourceUnlock(s);
646fe853e23SDavid du Colombier fileUnlock(f);
647fe853e23SDavid du Colombier return 0;
648fe853e23SDavid du Colombier }
649fe853e23SDavid du Colombier
650fe853e23SDavid du Colombier int
fileSetSize(File * f,uvlong size)651fe853e23SDavid du Colombier fileSetSize(File *f, uvlong size)
652fe853e23SDavid du Colombier {
653fe853e23SDavid du Colombier int r;
654fe853e23SDavid du Colombier
655fe853e23SDavid du Colombier if(!fileLock(f))
656fe853e23SDavid du Colombier return 0;
657fe853e23SDavid du Colombier r = 0;
658fe853e23SDavid du Colombier if(f->dir.mode & ModeDir){
659fe853e23SDavid du Colombier vtSetError(ENotFile);
660fe853e23SDavid du Colombier goto Err;
661fe853e23SDavid du Colombier }
662fe853e23SDavid du Colombier if(f->source->mode != OReadWrite){
663fe853e23SDavid du Colombier vtSetError(EReadOnly);
664fe853e23SDavid du Colombier goto Err;
665fe853e23SDavid du Colombier }
666fe853e23SDavid du Colombier if(!sourceLock(f->source, -1))
667fe853e23SDavid du Colombier goto Err;
668fe853e23SDavid du Colombier r = sourceSetSize(f->source, size);
669fe853e23SDavid du Colombier sourceUnlock(f->source);
670fe853e23SDavid du Colombier Err:
671fe853e23SDavid du Colombier fileUnlock(f);
672fe853e23SDavid du Colombier return r;
673fe853e23SDavid du Colombier }
674fe853e23SDavid du Colombier
6755e96a66cSDavid du Colombier int
fileWrite(File * f,void * buf,int cnt,vlong offset,char * uid)6765e96a66cSDavid du Colombier fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid)
6775e96a66cSDavid du Colombier {
6785e96a66cSDavid du Colombier Source *s;
6795e96a66cSDavid du Colombier ulong bn;
6805e96a66cSDavid du Colombier int off, dsize, n;
6815e96a66cSDavid du Colombier Block *b;
6825e96a66cSDavid du Colombier uchar *p;
6835e96a66cSDavid du Colombier vlong eof;
6845e96a66cSDavid du Colombier
6855e96a66cSDavid du Colombier if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
6865e96a66cSDavid du Colombier
6875e96a66cSDavid du Colombier if(!fileLock(f))
6885e96a66cSDavid du Colombier return -1;
6895e96a66cSDavid du Colombier
6905e96a66cSDavid du Colombier s = nil;
6915e96a66cSDavid du Colombier if(f->dir.mode & ModeDir){
6925e96a66cSDavid du Colombier vtSetError(ENotFile);
6935e96a66cSDavid du Colombier goto Err;
6945e96a66cSDavid du Colombier }
6955e96a66cSDavid du Colombier
6965e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){
6975e96a66cSDavid du Colombier vtSetError(EReadOnly);
6985e96a66cSDavid du Colombier goto Err;
6995e96a66cSDavid du Colombier }
7005e96a66cSDavid du Colombier if(offset < 0){
7015e96a66cSDavid du Colombier vtSetError(EBadOffset);
7025e96a66cSDavid du Colombier goto Err;
7035e96a66cSDavid du Colombier }
7045e96a66cSDavid du Colombier
7055e96a66cSDavid du Colombier fileWAccess(f, uid);
7065e96a66cSDavid du Colombier
7075e96a66cSDavid du Colombier if(!sourceLock(f->source, -1))
7085e96a66cSDavid du Colombier goto Err;
7095e96a66cSDavid du Colombier s = f->source;
7105e96a66cSDavid du Colombier dsize = s->dsize;
7115e96a66cSDavid du Colombier
7125e96a66cSDavid du Colombier eof = sourceGetSize(s);
7135e96a66cSDavid du Colombier if(f->dir.mode & ModeAppend)
7145e96a66cSDavid du Colombier offset = eof;
7155e96a66cSDavid du Colombier bn = offset/dsize;
7165e96a66cSDavid du Colombier off = offset%dsize;
7175e96a66cSDavid du Colombier p = buf;
7185e96a66cSDavid du Colombier while(cnt > 0){
7195e96a66cSDavid du Colombier n = cnt;
7205e96a66cSDavid du Colombier if(n > dsize-off)
7215e96a66cSDavid du Colombier n = dsize-off;
7225e96a66cSDavid du Colombier b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite);
7235e96a66cSDavid du Colombier if(b == nil){
7245e96a66cSDavid du Colombier if(offset > eof)
7255e96a66cSDavid du Colombier sourceSetSize(s, offset);
7265e96a66cSDavid du Colombier goto Err;
7275e96a66cSDavid du Colombier }
7285e96a66cSDavid du Colombier memmove(b->data+off, p, n);
7295e96a66cSDavid du Colombier off = 0;
7305e96a66cSDavid du Colombier cnt -= n;
7315e96a66cSDavid du Colombier p += n;
7325e96a66cSDavid du Colombier offset += n;
7335e96a66cSDavid du Colombier bn++;
7345e96a66cSDavid du Colombier blockDirty(b);
7355e96a66cSDavid du Colombier blockPut(b);
7365e96a66cSDavid du Colombier }
7375e96a66cSDavid du Colombier if(offset > eof && !sourceSetSize(s, offset))
7385e96a66cSDavid du Colombier goto Err;
7395e96a66cSDavid du Colombier sourceUnlock(s);
7405e96a66cSDavid du Colombier fileUnlock(f);
7415e96a66cSDavid du Colombier return p-(uchar*)buf;
7425e96a66cSDavid du Colombier Err:
7435e96a66cSDavid du Colombier if(s)
7445e96a66cSDavid du Colombier sourceUnlock(s);
7455e96a66cSDavid du Colombier fileUnlock(f);
7465e96a66cSDavid du Colombier return -1;
7475e96a66cSDavid du Colombier }
7485e96a66cSDavid du Colombier
7495e96a66cSDavid du Colombier int
fileGetDir(File * f,DirEntry * dir)7505e96a66cSDavid du Colombier fileGetDir(File *f, DirEntry *dir)
7515e96a66cSDavid du Colombier {
7525e96a66cSDavid du Colombier if(!fileRLock(f))
7535e96a66cSDavid du Colombier return 0;
7545e96a66cSDavid du Colombier
7555e96a66cSDavid du Colombier fileMetaLock(f);
7565e96a66cSDavid du Colombier deCopy(dir, &f->dir);
7575e96a66cSDavid du Colombier fileMetaUnlock(f);
7585e96a66cSDavid du Colombier
7595e96a66cSDavid du Colombier if(!fileIsDir(f)){
7605e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){
7615e96a66cSDavid du Colombier fileRUnlock(f);
7625e96a66cSDavid du Colombier return 0;
7635e96a66cSDavid du Colombier }
7645e96a66cSDavid du Colombier dir->size = sourceGetSize(f->source);
7655e96a66cSDavid du Colombier sourceUnlock(f->source);
7665e96a66cSDavid du Colombier }
7675e96a66cSDavid du Colombier fileRUnlock(f);
7685e96a66cSDavid du Colombier
7695e96a66cSDavid du Colombier return 1;
7705e96a66cSDavid du Colombier }
7715e96a66cSDavid du Colombier
7725e96a66cSDavid du Colombier int
fileTruncate(File * f,char * uid)7735e96a66cSDavid du Colombier fileTruncate(File *f, char *uid)
7745e96a66cSDavid du Colombier {
7755e96a66cSDavid du Colombier if(fileIsDir(f)){
7765e96a66cSDavid du Colombier vtSetError(ENotFile);
7775e96a66cSDavid du Colombier return 0;
7785e96a66cSDavid du Colombier }
7795e96a66cSDavid du Colombier
7805e96a66cSDavid du Colombier if(!fileLock(f))
7815e96a66cSDavid du Colombier return 0;
7825e96a66cSDavid du Colombier
7835e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){
7845e96a66cSDavid du Colombier vtSetError(EReadOnly);
7855e96a66cSDavid du Colombier fileUnlock(f);
7865e96a66cSDavid du Colombier return 0;
7875e96a66cSDavid du Colombier }
7885e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)){
7895e96a66cSDavid du Colombier fileUnlock(f);
7905e96a66cSDavid du Colombier return 0;
7915e96a66cSDavid du Colombier }
7925e96a66cSDavid du Colombier if(!sourceTruncate(f->source)){
7935e96a66cSDavid du Colombier sourceUnlock(f->source);
7945e96a66cSDavid du Colombier fileUnlock(f);
7955e96a66cSDavid du Colombier return 0;
7965e96a66cSDavid du Colombier }
7975e96a66cSDavid du Colombier sourceUnlock(f->source);
7985e96a66cSDavid du Colombier fileUnlock(f);
7995e96a66cSDavid du Colombier
800a960ed1cSDavid du Colombier fileWAccess(f, uid);
8015e96a66cSDavid du Colombier
8025e96a66cSDavid du Colombier return 1;
8035e96a66cSDavid du Colombier }
8045e96a66cSDavid du Colombier
8055e96a66cSDavid du Colombier int
fileSetDir(File * f,DirEntry * dir,char * uid)8065e96a66cSDavid du Colombier fileSetDir(File *f, DirEntry *dir, char *uid)
8075e96a66cSDavid du Colombier {
8085e96a66cSDavid du Colombier File *ff;
8095e96a66cSDavid du Colombier char *oelem;
8105e96a66cSDavid du Colombier u32int mask;
8115e96a66cSDavid du Colombier u64int size;
8125e96a66cSDavid du Colombier
8135e96a66cSDavid du Colombier /* can not set permissions for the root */
8145e96a66cSDavid du Colombier if(fileIsRoot(f)){
8155e96a66cSDavid du Colombier vtSetError(ERoot);
8165e96a66cSDavid du Colombier return 0;
8175e96a66cSDavid du Colombier }
8185e96a66cSDavid du Colombier
8195e96a66cSDavid du Colombier if(!fileLock(f))
8205e96a66cSDavid du Colombier return 0;
8215e96a66cSDavid du Colombier
8225e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){
8235e96a66cSDavid du Colombier vtSetError(EReadOnly);
8245e96a66cSDavid du Colombier fileUnlock(f);
8255e96a66cSDavid du Colombier return 0;
8265e96a66cSDavid du Colombier }
8275e96a66cSDavid du Colombier
8285e96a66cSDavid du Colombier fileMetaLock(f);
8295e96a66cSDavid du Colombier
8305e96a66cSDavid du Colombier /* check new name does not already exist */
8315e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){
8325e96a66cSDavid du Colombier for(ff = f->up->down; ff; ff=ff->next){
8335e96a66cSDavid du Colombier if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
8345e96a66cSDavid du Colombier vtSetError(EExists);
8355e96a66cSDavid du Colombier goto Err;
8365e96a66cSDavid du Colombier }
8375e96a66cSDavid du Colombier }
8385e96a66cSDavid du Colombier
8395e96a66cSDavid du Colombier ff = dirLookup(f->up, dir->elem);
8405e96a66cSDavid du Colombier if(ff != nil){
8415e96a66cSDavid du Colombier fileDecRef(ff);
8425e96a66cSDavid du Colombier vtSetError(EExists);
8435e96a66cSDavid du Colombier goto Err;
8445e96a66cSDavid du Colombier }
8455e96a66cSDavid du Colombier }
8465e96a66cSDavid du Colombier
847fe853e23SDavid du Colombier if(!sourceLock2(f->source, f->msource, -1))
8485e96a66cSDavid du Colombier goto Err;
849fe853e23SDavid du Colombier if(!fileIsDir(f)){
8505e96a66cSDavid du Colombier size = sourceGetSize(f->source);
8515e96a66cSDavid du Colombier if(size != dir->size){
8525e96a66cSDavid du Colombier if(!sourceSetSize(f->source, dir->size)){
8535e96a66cSDavid du Colombier sourceUnlock(f->source);
854fe853e23SDavid du Colombier if(f->msource)
855fe853e23SDavid du Colombier sourceUnlock(f->msource);
8565e96a66cSDavid du Colombier goto Err;
8575e96a66cSDavid du Colombier }
8585e96a66cSDavid du Colombier /* commited to changing it now */
8595e96a66cSDavid du Colombier }
8605e96a66cSDavid du Colombier }
8615e96a66cSDavid du Colombier /* commited to changing it now */
862fe853e23SDavid du Colombier if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
863fe853e23SDavid du Colombier fileSetTmp(f, dir->mode&ModeTemporary);
864fe853e23SDavid du Colombier sourceUnlock(f->source);
865fe853e23SDavid du Colombier if(f->msource)
866fe853e23SDavid du Colombier sourceUnlock(f->msource);
867fe853e23SDavid du Colombier
8685e96a66cSDavid du Colombier oelem = nil;
8695e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){
8705e96a66cSDavid du Colombier oelem = f->dir.elem;
8715e96a66cSDavid du Colombier f->dir.elem = vtStrDup(dir->elem);
8725e96a66cSDavid du Colombier }
8735e96a66cSDavid du Colombier
8745e96a66cSDavid du Colombier if(strcmp(f->dir.uid, dir->uid) != 0){
8755e96a66cSDavid du Colombier vtMemFree(f->dir.uid);
8765e96a66cSDavid du Colombier f->dir.uid = vtStrDup(dir->uid);
8775e96a66cSDavid du Colombier }
8785e96a66cSDavid du Colombier
8795e96a66cSDavid du Colombier if(strcmp(f->dir.gid, dir->gid) != 0){
8805e96a66cSDavid du Colombier vtMemFree(f->dir.gid);
8815e96a66cSDavid du Colombier f->dir.gid = vtStrDup(dir->gid);
8825e96a66cSDavid du Colombier }
8835e96a66cSDavid du Colombier
8845e96a66cSDavid du Colombier f->dir.mtime = dir->mtime;
8855e96a66cSDavid du Colombier f->dir.atime = dir->atime;
8865e96a66cSDavid du Colombier
8875e96a66cSDavid du Colombier //fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
8885e96a66cSDavid du Colombier mask = ~(ModeDir|ModeSnapshot);
8895e96a66cSDavid du Colombier f->dir.mode &= ~mask;
8905e96a66cSDavid du Colombier f->dir.mode |= mask & dir->mode;
8915e96a66cSDavid du Colombier f->dirty = 1;
8925e96a66cSDavid du Colombier //fprint(2, "->%x\n", f->dir.mode);
8935e96a66cSDavid du Colombier
8945e96a66cSDavid du Colombier fileMetaFlush2(f, oelem);
8955e96a66cSDavid du Colombier vtMemFree(oelem);
8965e96a66cSDavid du Colombier
8975e96a66cSDavid du Colombier fileMetaUnlock(f);
8985e96a66cSDavid du Colombier fileUnlock(f);
8995e96a66cSDavid du Colombier
9005e96a66cSDavid du Colombier fileWAccess(f->up, uid);
9015e96a66cSDavid du Colombier
9025e96a66cSDavid du Colombier return 1;
9035e96a66cSDavid du Colombier Err:
9045e96a66cSDavid du Colombier fileMetaUnlock(f);
9055e96a66cSDavid du Colombier fileUnlock(f);
9065e96a66cSDavid du Colombier return 0;
9075e96a66cSDavid du Colombier }
9085e96a66cSDavid du Colombier
9095e96a66cSDavid du Colombier int
fileSetQidSpace(File * f,u64int offset,u64int max)9105e96a66cSDavid du Colombier fileSetQidSpace(File *f, u64int offset, u64int max)
9115e96a66cSDavid du Colombier {
9125e96a66cSDavid du Colombier int ret;
9135e96a66cSDavid du Colombier
9145e96a66cSDavid du Colombier if(!fileLock(f))
9155e96a66cSDavid du Colombier return 0;
9165e96a66cSDavid du Colombier fileMetaLock(f);
9175e96a66cSDavid du Colombier f->dir.qidSpace = 1;
9185e96a66cSDavid du Colombier f->dir.qidOffset = offset;
9195e96a66cSDavid du Colombier f->dir.qidMax = max;
9200b9a5132SDavid du Colombier ret = fileMetaFlush2(f, nil)>=0;
9215e96a66cSDavid du Colombier fileMetaUnlock(f);
9225e96a66cSDavid du Colombier fileUnlock(f);
9235e96a66cSDavid du Colombier return ret;
9245e96a66cSDavid du Colombier }
9255e96a66cSDavid du Colombier
9265e96a66cSDavid du Colombier
9275e96a66cSDavid du Colombier uvlong
fileGetId(File * f)9285e96a66cSDavid du Colombier fileGetId(File *f)
9295e96a66cSDavid du Colombier {
9305e96a66cSDavid du Colombier /* immutable */
9315e96a66cSDavid du Colombier return f->dir.qid;
9325e96a66cSDavid du Colombier }
9335e96a66cSDavid du Colombier
9345e96a66cSDavid du Colombier ulong
fileGetMcount(File * f)9355e96a66cSDavid du Colombier fileGetMcount(File *f)
9365e96a66cSDavid du Colombier {
9375e96a66cSDavid du Colombier ulong mcount;
9385e96a66cSDavid du Colombier
9395e96a66cSDavid du Colombier fileMetaLock(f);
9405e96a66cSDavid du Colombier mcount = f->dir.mcount;
9415e96a66cSDavid du Colombier fileMetaUnlock(f);
9425e96a66cSDavid du Colombier return mcount;
9435e96a66cSDavid du Colombier }
9445e96a66cSDavid du Colombier
9455e96a66cSDavid du Colombier ulong
fileGetMode(File * f)9465e96a66cSDavid du Colombier fileGetMode(File *f)
9475e96a66cSDavid du Colombier {
9485e96a66cSDavid du Colombier ulong mode;
9495e96a66cSDavid du Colombier
9505e96a66cSDavid du Colombier fileMetaLock(f);
9515e96a66cSDavid du Colombier mode = f->dir.mode;
9525e96a66cSDavid du Colombier fileMetaUnlock(f);
9535e96a66cSDavid du Colombier return mode;
9545e96a66cSDavid du Colombier }
9555e96a66cSDavid du Colombier
9565e96a66cSDavid du Colombier int
fileIsDir(File * f)9575e96a66cSDavid du Colombier fileIsDir(File *f)
9585e96a66cSDavid du Colombier {
9595e96a66cSDavid du Colombier /* immutable */
9605e96a66cSDavid du Colombier return (f->dir.mode & ModeDir) != 0;
9615e96a66cSDavid du Colombier }
9625e96a66cSDavid du Colombier
9635e96a66cSDavid du Colombier int
fileIsAppend(File * f)964*6bbfed0dSDavid du Colombier fileIsAppend(File *f)
965*6bbfed0dSDavid du Colombier {
966*6bbfed0dSDavid du Colombier return (f->dir.mode & ModeAppend) != 0;
967*6bbfed0dSDavid du Colombier }
968*6bbfed0dSDavid du Colombier
969*6bbfed0dSDavid du Colombier int
fileIsExclusive(File * f)970*6bbfed0dSDavid du Colombier fileIsExclusive(File *f)
971*6bbfed0dSDavid du Colombier {
972*6bbfed0dSDavid du Colombier return (f->dir.mode & ModeExclusive) != 0;
973*6bbfed0dSDavid du Colombier }
974*6bbfed0dSDavid du Colombier
975*6bbfed0dSDavid du Colombier int
fileIsTemporary(File * f)976*6bbfed0dSDavid du Colombier fileIsTemporary(File *f)
977*6bbfed0dSDavid du Colombier {
978*6bbfed0dSDavid du Colombier return (f->dir.mode & ModeTemporary) != 0;
979*6bbfed0dSDavid du Colombier }
980*6bbfed0dSDavid du Colombier
981*6bbfed0dSDavid du Colombier int
fileIsRoot(File * f)9825e96a66cSDavid du Colombier fileIsRoot(File *f)
9835e96a66cSDavid du Colombier {
9845e96a66cSDavid du Colombier return f == f->fs->file;
9855e96a66cSDavid du Colombier }
9865e96a66cSDavid du Colombier
9875e96a66cSDavid du Colombier int
fileIsRoFs(File * f)9885e96a66cSDavid du Colombier fileIsRoFs(File *f)
9895e96a66cSDavid du Colombier {
9905e96a66cSDavid du Colombier return f->fs->mode == OReadOnly;
9915e96a66cSDavid du Colombier }
9925e96a66cSDavid du Colombier
9935e96a66cSDavid du Colombier int
fileGetSize(File * f,uvlong * size)9945e96a66cSDavid du Colombier fileGetSize(File *f, uvlong *size)
9955e96a66cSDavid du Colombier {
9965e96a66cSDavid du Colombier if(!fileRLock(f))
9975e96a66cSDavid du Colombier return 0;
9985e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){
9995e96a66cSDavid du Colombier fileRUnlock(f);
10005e96a66cSDavid du Colombier return 0;
10015e96a66cSDavid du Colombier }
10025e96a66cSDavid du Colombier *size = sourceGetSize(f->source);
10035e96a66cSDavid du Colombier sourceUnlock(f->source);
10045e96a66cSDavid du Colombier fileRUnlock(f);
10055e96a66cSDavid du Colombier
10065e96a66cSDavid du Colombier return 1;
10075e96a66cSDavid du Colombier }
10085e96a66cSDavid du Colombier
10090b9a5132SDavid du Colombier int
fileMetaFlush(File * f,int rec)10105e96a66cSDavid du Colombier fileMetaFlush(File *f, int rec)
10115e96a66cSDavid du Colombier {
10125e96a66cSDavid du Colombier File **kids, *p;
10135e96a66cSDavid du Colombier int nkids;
10140b9a5132SDavid du Colombier int i, rv;
10155e96a66cSDavid du Colombier
10165e96a66cSDavid du Colombier fileMetaLock(f);
10170b9a5132SDavid du Colombier rv = fileMetaFlush2(f, nil);
10185e96a66cSDavid du Colombier fileMetaUnlock(f);
10195e96a66cSDavid du Colombier
10205e96a66cSDavid du Colombier if(!rec || !fileIsDir(f))
10210b9a5132SDavid du Colombier return rv;
10225e96a66cSDavid du Colombier
10235e96a66cSDavid du Colombier if(!fileLock(f))
10240b9a5132SDavid du Colombier return rv;
10255e96a66cSDavid du Colombier nkids = 0;
10265e96a66cSDavid du Colombier for(p=f->down; p; p=p->next)
10275e96a66cSDavid du Colombier nkids++;
10285e96a66cSDavid du Colombier kids = vtMemAlloc(nkids*sizeof(File*));
10295e96a66cSDavid du Colombier i = 0;
10305e96a66cSDavid du Colombier for(p=f->down; p; p=p->next){
10315e96a66cSDavid du Colombier kids[i++] = p;
10325e96a66cSDavid du Colombier p->ref++;
10335e96a66cSDavid du Colombier }
10345e96a66cSDavid du Colombier fileUnlock(f);
10355e96a66cSDavid du Colombier
10365e96a66cSDavid du Colombier for(i=0; i<nkids; i++){
10370b9a5132SDavid du Colombier rv |= fileMetaFlush(kids[i], 1);
10385e96a66cSDavid du Colombier fileDecRef(kids[i]);
10395e96a66cSDavid du Colombier }
10405e96a66cSDavid du Colombier vtMemFree(kids);
10410b9a5132SDavid du Colombier return rv;
10425e96a66cSDavid du Colombier }
10435e96a66cSDavid du Colombier
10445e96a66cSDavid du Colombier /* assumes metaLock is held */
10455e96a66cSDavid du Colombier static int
fileMetaFlush2(File * f,char * oelem)10465e96a66cSDavid du Colombier fileMetaFlush2(File *f, char *oelem)
10475e96a66cSDavid du Colombier {
10485e96a66cSDavid du Colombier File *fp;
10495e96a66cSDavid du Colombier Block *b, *bb;
10505e96a66cSDavid du Colombier MetaBlock mb;
10515e96a66cSDavid du Colombier MetaEntry me, me2;
10525e96a66cSDavid du Colombier int i, n;
10535e96a66cSDavid du Colombier u32int boff;
10545e96a66cSDavid du Colombier
10555e96a66cSDavid du Colombier if(!f->dirty)
10560b9a5132SDavid du Colombier return 0;
10575e96a66cSDavid du Colombier
10585e96a66cSDavid du Colombier if(oelem == nil)
10595e96a66cSDavid du Colombier oelem = f->dir.elem;
10605e96a66cSDavid du Colombier
10615e96a66cSDavid du Colombier //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem);
10625e96a66cSDavid du Colombier
10635e96a66cSDavid du Colombier fp = f->up;
10645e96a66cSDavid du Colombier
10655e96a66cSDavid du Colombier if(!sourceLock(fp->msource, -1))
10660b9a5132SDavid du Colombier return -1;
10676042bf6dSDavid du Colombier /* can happen if source is clri'ed out from under us */
10686042bf6dSDavid du Colombier if(f->boff == NilBlock)
10696042bf6dSDavid du Colombier goto Err1;
10705e96a66cSDavid du Colombier b = sourceBlock(fp->msource, f->boff, OReadWrite);
10715e96a66cSDavid du Colombier if(b == nil)
10725e96a66cSDavid du Colombier goto Err1;
10735e96a66cSDavid du Colombier
10745e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, fp->msource->dsize))
10755e96a66cSDavid du Colombier goto Err;
10765e96a66cSDavid du Colombier if(!mbSearch(&mb, oelem, &i, &me))
10775e96a66cSDavid du Colombier goto Err;
10785e96a66cSDavid du Colombier
10795e96a66cSDavid du Colombier n = deSize(&f->dir);
10805e96a66cSDavid du Colombier if(0)fprint(2, "old size %d new size %d\n", me.size, n);
10815e96a66cSDavid du Colombier
10825e96a66cSDavid du Colombier if(mbResize(&mb, &me, n)){
10835e96a66cSDavid du Colombier /* fits in the block */
10845e96a66cSDavid du Colombier mbDelete(&mb, i);
10855e96a66cSDavid du Colombier if(strcmp(f->dir.elem, oelem) != 0)
10865e96a66cSDavid du Colombier mbSearch(&mb, f->dir.elem, &i, &me2);
10875e96a66cSDavid du Colombier dePack(&f->dir, &me);
10885e96a66cSDavid du Colombier mbInsert(&mb, i, &me);
10895e96a66cSDavid du Colombier mbPack(&mb);
10905e96a66cSDavid du Colombier blockDirty(b);
10915e96a66cSDavid du Colombier blockPut(b);
10925e96a66cSDavid du Colombier sourceUnlock(fp->msource);
10935e96a66cSDavid du Colombier f->dirty = 0;
10945e96a66cSDavid du Colombier
10955e96a66cSDavid du Colombier return 1;
10965e96a66cSDavid du Colombier }
10975e96a66cSDavid du Colombier
10985e96a66cSDavid du Colombier /*
10995e96a66cSDavid du Colombier * moving entry to another block
11005e96a66cSDavid du Colombier * it is feasible for the fs to crash leaving two copies
11015e96a66cSDavid du Colombier * of the directory entry. This is just too much work to
11025e96a66cSDavid du Colombier * fix. Given that entries are only allocated in a block that
11035e96a66cSDavid du Colombier * is less than PercentageFull, most modifications of meta data
11045e96a66cSDavid du Colombier * will fit within the block. i.e. this code should almost
11055e96a66cSDavid du Colombier * never be executed.
11065e96a66cSDavid du Colombier */
11075e96a66cSDavid du Colombier boff = fileMetaAlloc(fp, &f->dir, f->boff+1);
11085e96a66cSDavid du Colombier if(boff == NilBlock){
11095e96a66cSDavid du Colombier /* mbResize might have modified block */
11105e96a66cSDavid du Colombier mbPack(&mb);
11115e96a66cSDavid du Colombier blockDirty(b);
11125e96a66cSDavid du Colombier goto Err;
11135e96a66cSDavid du Colombier }
11145e96a66cSDavid du Colombier fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
11155e96a66cSDavid du Colombier f->boff = boff;
11165e96a66cSDavid du Colombier
11175e96a66cSDavid du Colombier /* make sure deletion goes to disk after new entry */
11185e96a66cSDavid du Colombier bb = sourceBlock(fp->msource, f->boff, OReadWrite);
11195e96a66cSDavid du Colombier mbDelete(&mb, i);
11205e96a66cSDavid du Colombier mbPack(&mb);
112161201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil);
11225e96a66cSDavid du Colombier blockPut(bb);
11235e96a66cSDavid du Colombier blockDirty(b);
11245e96a66cSDavid du Colombier blockPut(b);
11255e96a66cSDavid du Colombier sourceUnlock(fp->msource);
11265e96a66cSDavid du Colombier
11275e96a66cSDavid du Colombier f->dirty = 0;
11285e96a66cSDavid du Colombier
11295e96a66cSDavid du Colombier return 1;
11305e96a66cSDavid du Colombier
11315e96a66cSDavid du Colombier Err:
11325e96a66cSDavid du Colombier blockPut(b);
11335e96a66cSDavid du Colombier Err1:
11345e96a66cSDavid du Colombier sourceUnlock(fp->msource);
11350b9a5132SDavid du Colombier return -1;
11365e96a66cSDavid du Colombier }
11375e96a66cSDavid du Colombier
11385e96a66cSDavid du Colombier static int
fileMetaRemove(File * f,char * uid)11395e96a66cSDavid du Colombier fileMetaRemove(File *f, char *uid)
11405e96a66cSDavid du Colombier {
11415e96a66cSDavid du Colombier Block *b;
11425e96a66cSDavid du Colombier MetaBlock mb;
11435e96a66cSDavid du Colombier MetaEntry me;
11445e96a66cSDavid du Colombier int i;
11455e96a66cSDavid du Colombier File *up;
11465e96a66cSDavid du Colombier
11475e96a66cSDavid du Colombier up = f->up;
11485e96a66cSDavid du Colombier
11495e96a66cSDavid du Colombier fileWAccess(up, uid);
11505e96a66cSDavid du Colombier
11515e96a66cSDavid du Colombier fileMetaLock(f);
11525e96a66cSDavid du Colombier
11535e96a66cSDavid du Colombier sourceLock(up->msource, OReadWrite);
11545e96a66cSDavid du Colombier b = sourceBlock(up->msource, f->boff, OReadWrite);
11555e96a66cSDavid du Colombier if(b == nil)
11565e96a66cSDavid du Colombier goto Err;
11575e96a66cSDavid du Colombier
11585e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, up->msource->dsize))
11595e96a66cSDavid du Colombier {
11605e96a66cSDavid du Colombier fprint(2, "U\n");
11615e96a66cSDavid du Colombier goto Err;
11625e96a66cSDavid du Colombier }
11635e96a66cSDavid du Colombier if(!mbSearch(&mb, f->dir.elem, &i, &me))
11645e96a66cSDavid du Colombier {
11655e96a66cSDavid du Colombier fprint(2, "S\n");
11665e96a66cSDavid du Colombier goto Err;
11675e96a66cSDavid du Colombier }
11685e96a66cSDavid du Colombier mbDelete(&mb, i);
11695e96a66cSDavid du Colombier mbPack(&mb);
11705e96a66cSDavid du Colombier sourceUnlock(up->msource);
11715e96a66cSDavid du Colombier
11725e96a66cSDavid du Colombier blockDirty(b);
11735e96a66cSDavid du Colombier blockPut(b);
11745e96a66cSDavid du Colombier
11755e96a66cSDavid du Colombier f->removed = 1;
11765e96a66cSDavid du Colombier f->boff = NilBlock;
11775e96a66cSDavid du Colombier f->dirty = 0;
11785e96a66cSDavid du Colombier
11795e96a66cSDavid du Colombier fileMetaUnlock(f);
11805e96a66cSDavid du Colombier return 1;
11815e96a66cSDavid du Colombier
11825e96a66cSDavid du Colombier Err:
11835e96a66cSDavid du Colombier sourceUnlock(up->msource);
11845e96a66cSDavid du Colombier blockPut(b);
11855e96a66cSDavid du Colombier fileMetaUnlock(f);
11865e96a66cSDavid du Colombier return 0;
11875e96a66cSDavid du Colombier }
11885e96a66cSDavid du Colombier
11895e96a66cSDavid du Colombier /* assume file is locked, assume f->msource is locked */
11905e96a66cSDavid du Colombier static int
fileCheckEmpty(File * f)11915e96a66cSDavid du Colombier fileCheckEmpty(File *f)
11925e96a66cSDavid du Colombier {
11935e96a66cSDavid du Colombier u32int i, n;
11945e96a66cSDavid du Colombier Block *b;
11955e96a66cSDavid du Colombier MetaBlock mb;
11965e96a66cSDavid du Colombier Source *r;
11975e96a66cSDavid du Colombier
11985e96a66cSDavid du Colombier r = f->msource;
11995e96a66cSDavid du Colombier n = (sourceGetSize(r)+r->dsize-1)/r->dsize;
12005e96a66cSDavid du Colombier for(i=0; i<n; i++){
12015e96a66cSDavid du Colombier b = sourceBlock(r, i, OReadOnly);
12025e96a66cSDavid du Colombier if(b == nil)
12035e96a66cSDavid du Colombier goto Err;
12045e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, r->dsize))
12055e96a66cSDavid du Colombier goto Err;
12065e96a66cSDavid du Colombier if(mb.nindex > 0){
12075e96a66cSDavid du Colombier vtSetError(ENotEmpty);
12085e96a66cSDavid du Colombier goto Err;
12095e96a66cSDavid du Colombier }
12105e96a66cSDavid du Colombier blockPut(b);
12115e96a66cSDavid du Colombier }
12125e96a66cSDavid du Colombier return 1;
12135e96a66cSDavid du Colombier Err:
12145e96a66cSDavid du Colombier blockPut(b);
12155e96a66cSDavid du Colombier return 0;
12165e96a66cSDavid du Colombier }
12175e96a66cSDavid du Colombier
12185e96a66cSDavid du Colombier int
fileRemove(File * f,char * uid)12195e96a66cSDavid du Colombier fileRemove(File *f, char *uid)
12205e96a66cSDavid du Colombier {
12215e96a66cSDavid du Colombier File *ff;
12225e96a66cSDavid du Colombier
12235e96a66cSDavid du Colombier /* can not remove the root */
12245e96a66cSDavid du Colombier if(fileIsRoot(f)){
12255e96a66cSDavid du Colombier vtSetError(ERoot);
12265e96a66cSDavid du Colombier return 0;
12275e96a66cSDavid du Colombier }
12285e96a66cSDavid du Colombier
12295e96a66cSDavid du Colombier if(!fileLock(f))
12305e96a66cSDavid du Colombier return 0;
12315e96a66cSDavid du Colombier
12325e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){
12335e96a66cSDavid du Colombier vtSetError(EReadOnly);
12345e96a66cSDavid du Colombier goto Err1;
12355e96a66cSDavid du Colombier }
12365e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1))
12375e96a66cSDavid du Colombier goto Err1;
12385e96a66cSDavid du Colombier if(fileIsDir(f) && !fileCheckEmpty(f))
12395e96a66cSDavid du Colombier goto Err;
12405e96a66cSDavid du Colombier
12415e96a66cSDavid du Colombier for(ff=f->down; ff; ff=ff->next)
12425e96a66cSDavid du Colombier assert(ff->removed);
12435e96a66cSDavid du Colombier
12445e96a66cSDavid du Colombier sourceRemove(f->source);
12453b86f2f8SDavid du Colombier f->source->file = nil; /* erase back pointer */
12465e96a66cSDavid du Colombier f->source = nil;
12475e96a66cSDavid du Colombier if(f->msource){
12485e96a66cSDavid du Colombier sourceRemove(f->msource);
12495e96a66cSDavid du Colombier f->msource = nil;
12505e96a66cSDavid du Colombier }
12515e96a66cSDavid du Colombier
12525e96a66cSDavid du Colombier fileUnlock(f);
12535e96a66cSDavid du Colombier
12545e96a66cSDavid du Colombier if(!fileMetaRemove(f, uid))
12555e96a66cSDavid du Colombier return 0;
12565e96a66cSDavid du Colombier
12575e96a66cSDavid du Colombier return 1;
12585e96a66cSDavid du Colombier
12595e96a66cSDavid du Colombier Err:
12605e96a66cSDavid du Colombier sourceUnlock(f->source);
12615e96a66cSDavid du Colombier if(f->msource)
12625e96a66cSDavid du Colombier sourceUnlock(f->msource);
12635e96a66cSDavid du Colombier Err1:
12645e96a66cSDavid du Colombier fileUnlock(f);
12655e96a66cSDavid du Colombier return 0;
12665e96a66cSDavid du Colombier }
12675e96a66cSDavid du Colombier
1268dc5a79c1SDavid du Colombier static int
clri(File * f,char * uid)1269dc5a79c1SDavid du Colombier clri(File *f, char *uid)
12705e96a66cSDavid du Colombier {
12715e96a66cSDavid du Colombier int r;
12725e96a66cSDavid du Colombier
12735e96a66cSDavid du Colombier if(f == nil)
12745e96a66cSDavid du Colombier return 0;
12755e96a66cSDavid du Colombier if(f->up->source->mode != OReadWrite){
12765e96a66cSDavid du Colombier vtSetError(EReadOnly);
12775e96a66cSDavid du Colombier fileDecRef(f);
12785e96a66cSDavid du Colombier return 0;
12795e96a66cSDavid du Colombier }
12805e96a66cSDavid du Colombier r = fileMetaRemove(f, uid);
12815e96a66cSDavid du Colombier fileDecRef(f);
12825e96a66cSDavid du Colombier return r;
12835e96a66cSDavid du Colombier }
12845e96a66cSDavid du Colombier
1285dc5a79c1SDavid du Colombier int
fileClriPath(Fs * fs,char * path,char * uid)1286dc5a79c1SDavid du Colombier fileClriPath(Fs *fs, char *path, char *uid)
1287dc5a79c1SDavid du Colombier {
1288dc5a79c1SDavid du Colombier return clri(_fileOpen(fs, path, 1), uid);
1289dc5a79c1SDavid du Colombier }
1290dc5a79c1SDavid du Colombier
1291dc5a79c1SDavid du Colombier int
fileClri(File * dir,char * elem,char * uid)1292dc5a79c1SDavid du Colombier fileClri(File *dir, char *elem, char *uid)
1293dc5a79c1SDavid du Colombier {
1294dc5a79c1SDavid du Colombier return clri(_fileWalk(dir, elem, 1), uid);
1295dc5a79c1SDavid du Colombier }
1296dc5a79c1SDavid du Colombier
12975e96a66cSDavid du Colombier File *
fileIncRef(File * vf)12985e96a66cSDavid du Colombier fileIncRef(File *vf)
12995e96a66cSDavid du Colombier {
13005e96a66cSDavid du Colombier fileMetaLock(vf);
13015e96a66cSDavid du Colombier assert(vf->ref > 0);
13025e96a66cSDavid du Colombier vf->ref++;
13035e96a66cSDavid du Colombier fileMetaUnlock(vf);
13045e96a66cSDavid du Colombier return vf;
13055e96a66cSDavid du Colombier }
13065e96a66cSDavid du Colombier
13075e96a66cSDavid du Colombier int
fileDecRef(File * f)13085e96a66cSDavid du Colombier fileDecRef(File *f)
13095e96a66cSDavid du Colombier {
13105e96a66cSDavid du Colombier File *p, *q, **qq;
13115e96a66cSDavid du Colombier
13125e96a66cSDavid du Colombier if(f->up == nil){
13135e96a66cSDavid du Colombier /* never linked in */
13145e96a66cSDavid du Colombier assert(f->ref == 1);
13155e96a66cSDavid du Colombier fileFree(f);
13165e96a66cSDavid du Colombier return 1;
13175e96a66cSDavid du Colombier }
13185e96a66cSDavid du Colombier
13195e96a66cSDavid du Colombier fileMetaLock(f);
13205e96a66cSDavid du Colombier f->ref--;
13215e96a66cSDavid du Colombier if(f->ref > 0){
13225e96a66cSDavid du Colombier fileMetaUnlock(f);
13235e96a66cSDavid du Colombier return 0;
13245e96a66cSDavid du Colombier }
13255e96a66cSDavid du Colombier assert(f->ref == 0);
13265e96a66cSDavid du Colombier assert(f->down == nil);
13275e96a66cSDavid du Colombier
13285e96a66cSDavid du Colombier fileMetaFlush2(f, nil);
13295e96a66cSDavid du Colombier
13305e96a66cSDavid du Colombier p = f->up;
13315e96a66cSDavid du Colombier qq = &p->down;
13325e96a66cSDavid du Colombier for(q = *qq; q; q = *qq){
13335e96a66cSDavid du Colombier if(q == f)
13345e96a66cSDavid du Colombier break;
13355e96a66cSDavid du Colombier qq = &q->next;
13365e96a66cSDavid du Colombier }
13375e96a66cSDavid du Colombier assert(q != nil);
13385e96a66cSDavid du Colombier *qq = f->next;
13395e96a66cSDavid du Colombier
13405e96a66cSDavid du Colombier fileMetaUnlock(f);
13415e96a66cSDavid du Colombier fileFree(f);
13425e96a66cSDavid du Colombier
13435e96a66cSDavid du Colombier fileDecRef(p);
13445e96a66cSDavid du Colombier return 1;
13455e96a66cSDavid du Colombier }
13465e96a66cSDavid du Colombier
13475e96a66cSDavid du Colombier File *
fileGetParent(File * f)13485e96a66cSDavid du Colombier fileGetParent(File *f)
13495e96a66cSDavid du Colombier {
13505e96a66cSDavid du Colombier if(fileIsRoot(f))
13515e96a66cSDavid du Colombier return fileIncRef(f);
13525e96a66cSDavid du Colombier return fileIncRef(f->up);
13535e96a66cSDavid du Colombier }
13545e96a66cSDavid du Colombier
13555e96a66cSDavid du Colombier DirEntryEnum *
deeOpen(File * f)13565e96a66cSDavid du Colombier deeOpen(File *f)
13575e96a66cSDavid du Colombier {
13585e96a66cSDavid du Colombier DirEntryEnum *dee;
13595e96a66cSDavid du Colombier File *p;
13605e96a66cSDavid du Colombier
13615e96a66cSDavid du Colombier if(!fileIsDir(f)){
13625e96a66cSDavid du Colombier vtSetError(ENotDir);
13635e96a66cSDavid du Colombier fileDecRef(f);
13645e96a66cSDavid du Colombier return nil;
13655e96a66cSDavid du Colombier }
13665e96a66cSDavid du Colombier
13675e96a66cSDavid du Colombier /* flush out meta data */
13685e96a66cSDavid du Colombier if(!fileLock(f))
13695e96a66cSDavid du Colombier return nil;
13705e96a66cSDavid du Colombier for(p=f->down; p; p=p->next)
13715e96a66cSDavid du Colombier fileMetaFlush2(p, nil);
13725e96a66cSDavid du Colombier fileUnlock(f);
13735e96a66cSDavid du Colombier
13745e96a66cSDavid du Colombier dee = vtMemAllocZ(sizeof(DirEntryEnum));
13755e96a66cSDavid du Colombier dee->file = fileIncRef(f);
13765e96a66cSDavid du Colombier
13775e96a66cSDavid du Colombier return dee;
13785e96a66cSDavid du Colombier }
13795e96a66cSDavid du Colombier
13805e96a66cSDavid du Colombier static int
dirEntrySize(Source * s,ulong elem,ulong gen,uvlong * size)13815e96a66cSDavid du Colombier dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size)
13825e96a66cSDavid du Colombier {
13835e96a66cSDavid du Colombier Block *b;
13845e96a66cSDavid du Colombier ulong bn;
13855e96a66cSDavid du Colombier Entry e;
13865e96a66cSDavid du Colombier int epb;
13875e96a66cSDavid du Colombier
13885e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize;
13895e96a66cSDavid du Colombier bn = elem/epb;
13905e96a66cSDavid du Colombier elem -= bn*epb;
13915e96a66cSDavid du Colombier
13925e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly);
13935e96a66cSDavid du Colombier if(b == nil)
13945e96a66cSDavid du Colombier goto Err;
13955e96a66cSDavid du Colombier if(!entryUnpack(&e, b->data, elem))
13965e96a66cSDavid du Colombier goto Err;
13975e96a66cSDavid du Colombier
13985e96a66cSDavid du Colombier /* hanging entries are returned as zero size */
13995e96a66cSDavid du Colombier if(!(e.flags & VtEntryActive) || e.gen != gen)
14005e96a66cSDavid du Colombier *size = 0;
14015e96a66cSDavid du Colombier else
14025e96a66cSDavid du Colombier *size = e.size;
14035e96a66cSDavid du Colombier blockPut(b);
14045e96a66cSDavid du Colombier return 1;
14055e96a66cSDavid du Colombier
14065e96a66cSDavid du Colombier Err:
14075e96a66cSDavid du Colombier blockPut(b);
14085e96a66cSDavid du Colombier return 0;
14095e96a66cSDavid du Colombier }
14105e96a66cSDavid du Colombier
14115e96a66cSDavid du Colombier static int
deeFill(DirEntryEnum * dee)14125e96a66cSDavid du Colombier deeFill(DirEntryEnum *dee)
14135e96a66cSDavid du Colombier {
14145e96a66cSDavid du Colombier int i, n;
14155e96a66cSDavid du Colombier Source *meta, *source;
14165e96a66cSDavid du Colombier MetaBlock mb;
14175e96a66cSDavid du Colombier MetaEntry me;
14185e96a66cSDavid du Colombier File *f;
14195e96a66cSDavid du Colombier Block *b;
14205e96a66cSDavid du Colombier DirEntry *de;
14215e96a66cSDavid du Colombier
14225e96a66cSDavid du Colombier /* clean up first */
14235e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++)
14245e96a66cSDavid du Colombier deCleanup(dee->buf+i);
14255e96a66cSDavid du Colombier vtMemFree(dee->buf);
14265e96a66cSDavid du Colombier dee->buf = nil;
14275e96a66cSDavid du Colombier dee->i = 0;
14285e96a66cSDavid du Colombier dee->n = 0;
14295e96a66cSDavid du Colombier
14305e96a66cSDavid du Colombier f = dee->file;
14315e96a66cSDavid du Colombier
14325e96a66cSDavid du Colombier source = f->source;
14335e96a66cSDavid du Colombier meta = f->msource;
14345e96a66cSDavid du Colombier
14355e96a66cSDavid du Colombier b = sourceBlock(meta, dee->boff, OReadOnly);
14365e96a66cSDavid du Colombier if(b == nil)
14375e96a66cSDavid du Colombier goto Err;
14385e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize))
14395e96a66cSDavid du Colombier goto Err;
14405e96a66cSDavid du Colombier
14415e96a66cSDavid du Colombier n = mb.nindex;
14425e96a66cSDavid du Colombier dee->buf = vtMemAlloc(n * sizeof(DirEntry));
14435e96a66cSDavid du Colombier
14445e96a66cSDavid du Colombier for(i=0; i<n; i++){
14455e96a66cSDavid du Colombier de = dee->buf + i;
14465e96a66cSDavid du Colombier meUnpack(&me, &mb, i);
14475e96a66cSDavid du Colombier if(!deUnpack(de, &me))
14485e96a66cSDavid du Colombier goto Err;
14495e96a66cSDavid du Colombier dee->n++;
14505e96a66cSDavid du Colombier if(!(de->mode & ModeDir))
14515e96a66cSDavid du Colombier if(!dirEntrySize(source, de->entry, de->gen, &de->size))
14525e96a66cSDavid du Colombier goto Err;
14535e96a66cSDavid du Colombier }
14545e96a66cSDavid du Colombier dee->boff++;
14555e96a66cSDavid du Colombier blockPut(b);
14565e96a66cSDavid du Colombier return 1;
14575e96a66cSDavid du Colombier Err:
14585e96a66cSDavid du Colombier blockPut(b);
14595e96a66cSDavid du Colombier return 0;
14605e96a66cSDavid du Colombier }
14615e96a66cSDavid du Colombier
14625e96a66cSDavid du Colombier int
deeRead(DirEntryEnum * dee,DirEntry * de)14635e96a66cSDavid du Colombier deeRead(DirEntryEnum *dee, DirEntry *de)
14645e96a66cSDavid du Colombier {
14655e96a66cSDavid du Colombier int ret, didread;
14665e96a66cSDavid du Colombier File *f;
14675e96a66cSDavid du Colombier u32int nb;
14685e96a66cSDavid du Colombier
1469418f3c22SDavid du Colombier if(dee == nil){
1470418f3c22SDavid du Colombier vtSetError("cannot happen in deeRead");
1471418f3c22SDavid du Colombier return -1;
1472418f3c22SDavid du Colombier }
1473418f3c22SDavid du Colombier
14745e96a66cSDavid du Colombier f = dee->file;
14755e96a66cSDavid du Colombier if(!fileRLock(f))
14765e96a66cSDavid du Colombier return -1;
14775e96a66cSDavid du Colombier
14785e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadOnly)){
14795e96a66cSDavid du Colombier fileRUnlock(f);
14805e96a66cSDavid du Colombier return -1;
14815e96a66cSDavid du Colombier }
14825e96a66cSDavid du Colombier
14835e96a66cSDavid du Colombier nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize;
14845e96a66cSDavid du Colombier
14855e96a66cSDavid du Colombier didread = 0;
14865e96a66cSDavid du Colombier while(dee->i >= dee->n){
14875e96a66cSDavid du Colombier if(dee->boff >= nb){
14885e96a66cSDavid du Colombier ret = 0;
14895e96a66cSDavid du Colombier goto Return;
14905e96a66cSDavid du Colombier }
14915e96a66cSDavid du Colombier didread = 1;
14925e96a66cSDavid du Colombier if(!deeFill(dee)){
14935e96a66cSDavid du Colombier ret = -1;
14945e96a66cSDavid du Colombier goto Return;
14955e96a66cSDavid du Colombier }
14965e96a66cSDavid du Colombier }
14975e96a66cSDavid du Colombier
14985e96a66cSDavid du Colombier memmove(de, dee->buf + dee->i, sizeof(DirEntry));
14995e96a66cSDavid du Colombier dee->i++;
15005e96a66cSDavid du Colombier ret = 1;
15015e96a66cSDavid du Colombier
15025e96a66cSDavid du Colombier Return:
15035e96a66cSDavid du Colombier sourceUnlock(f->source);
15045e96a66cSDavid du Colombier sourceUnlock(f->msource);
15055e96a66cSDavid du Colombier fileRUnlock(f);
15065e96a66cSDavid du Colombier
15075e96a66cSDavid du Colombier if(didread)
15085e96a66cSDavid du Colombier fileRAccess(f);
15095e96a66cSDavid du Colombier return ret;
15105e96a66cSDavid du Colombier }
15115e96a66cSDavid du Colombier
15125e96a66cSDavid du Colombier void
deeClose(DirEntryEnum * dee)15135e96a66cSDavid du Colombier deeClose(DirEntryEnum *dee)
15145e96a66cSDavid du Colombier {
15155e96a66cSDavid du Colombier int i;
15165e96a66cSDavid du Colombier if(dee == nil)
15175e96a66cSDavid du Colombier return;
15185e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++)
15195e96a66cSDavid du Colombier deCleanup(dee->buf+i);
15205e96a66cSDavid du Colombier vtMemFree(dee->buf);
15215e96a66cSDavid du Colombier fileDecRef(dee->file);
15225e96a66cSDavid du Colombier vtMemFree(dee);
15235e96a66cSDavid du Colombier }
15245e96a66cSDavid du Colombier
15255e96a66cSDavid du Colombier /*
15265e96a66cSDavid du Colombier * caller must lock f->source and f->msource
15275e96a66cSDavid du Colombier * caller must NOT lock the source and msource
15285e96a66cSDavid du Colombier * referenced by dir.
15295e96a66cSDavid du Colombier */
15305e96a66cSDavid du Colombier static u32int
fileMetaAlloc(File * f,DirEntry * dir,u32int start)15315e96a66cSDavid du Colombier fileMetaAlloc(File *f, DirEntry *dir, u32int start)
15325e96a66cSDavid du Colombier {
15335e96a66cSDavid du Colombier u32int nb, bo;
15345e96a66cSDavid du Colombier Block *b, *bb;
15355e96a66cSDavid du Colombier MetaBlock mb;
15365e96a66cSDavid du Colombier int nn;
15375e96a66cSDavid du Colombier uchar *p;
15385e96a66cSDavid du Colombier int i, n, epb;
15395e96a66cSDavid du Colombier MetaEntry me;
15405e96a66cSDavid du Colombier Source *s, *ms;
15415e96a66cSDavid du Colombier
15425e96a66cSDavid du Colombier s = f->source;
15435e96a66cSDavid du Colombier ms = f->msource;
15445e96a66cSDavid du Colombier
15455e96a66cSDavid du Colombier n = deSize(dir);
15465e96a66cSDavid du Colombier nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize;
15475e96a66cSDavid du Colombier b = nil;
15485e96a66cSDavid du Colombier if(start > nb)
15495e96a66cSDavid du Colombier start = nb;
15505e96a66cSDavid du Colombier for(bo=start; bo<nb; bo++){
15515e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite);
15525e96a66cSDavid du Colombier if(b == nil)
15535e96a66cSDavid du Colombier goto Err;
15545e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, ms->dsize))
15555e96a66cSDavid du Colombier goto Err;
15565e96a66cSDavid du Colombier nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
15575e96a66cSDavid du Colombier if(n <= nn && mb.nindex < mb.maxindex)
15585e96a66cSDavid du Colombier break;
15595e96a66cSDavid du Colombier blockPut(b);
15605e96a66cSDavid du Colombier b = nil;
15615e96a66cSDavid du Colombier }
15625e96a66cSDavid du Colombier
15635e96a66cSDavid du Colombier /* add block to meta file */
15645e96a66cSDavid du Colombier if(b == nil){
15655e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite);
15665e96a66cSDavid du Colombier if(b == nil)
15675e96a66cSDavid du Colombier goto Err;
15685e96a66cSDavid du Colombier sourceSetSize(ms, (nb+1)*ms->dsize);
15695e96a66cSDavid du Colombier mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
15705e96a66cSDavid du Colombier }
15715e96a66cSDavid du Colombier
15725e96a66cSDavid du Colombier p = mbAlloc(&mb, n);
15735e96a66cSDavid du Colombier if(p == nil){
15745e96a66cSDavid du Colombier /* mbAlloc might have changed block */
15755e96a66cSDavid du Colombier mbPack(&mb);
15765e96a66cSDavid du Colombier blockDirty(b);
15775e96a66cSDavid du Colombier vtSetError(EBadMeta);
15785e96a66cSDavid du Colombier goto Err;
15795e96a66cSDavid du Colombier }
15805e96a66cSDavid du Colombier
15815e96a66cSDavid du Colombier mbSearch(&mb, dir->elem, &i, &me);
15825e96a66cSDavid du Colombier assert(me.p == nil);
15835e96a66cSDavid du Colombier me.p = p;
15845e96a66cSDavid du Colombier me.size = n;
15855e96a66cSDavid du Colombier dePack(dir, &me);
15865e96a66cSDavid du Colombier mbInsert(&mb, i, &me);
15875e96a66cSDavid du Colombier mbPack(&mb);
15885e96a66cSDavid du Colombier
15895e96a66cSDavid du Colombier /* meta block depends on super block for qid ... */
15905e96a66cSDavid du Colombier bb = cacheLocal(b->c, PartSuper, 0, OReadOnly);
159161201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil);
15925e96a66cSDavid du Colombier blockPut(bb);
15935e96a66cSDavid du Colombier
15945e96a66cSDavid du Colombier /* ... and one or two dir entries */
15955e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize;
15965e96a66cSDavid du Colombier bb = sourceBlock(s, dir->entry/epb, OReadOnly);
159761201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil);
15985e96a66cSDavid du Colombier blockPut(bb);
15995e96a66cSDavid du Colombier if(dir->mode & ModeDir){
16005e96a66cSDavid du Colombier bb = sourceBlock(s, dir->mentry/epb, OReadOnly);
160161201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil);
16025e96a66cSDavid du Colombier blockPut(bb);
16035e96a66cSDavid du Colombier }
16045e96a66cSDavid du Colombier
16055e96a66cSDavid du Colombier blockDirty(b);
16065e96a66cSDavid du Colombier blockPut(b);
16075e96a66cSDavid du Colombier return bo;
16085e96a66cSDavid du Colombier Err:
16095e96a66cSDavid du Colombier blockPut(b);
16105e96a66cSDavid du Colombier return NilBlock;
16115e96a66cSDavid du Colombier }
16125e96a66cSDavid du Colombier
16135e96a66cSDavid du Colombier static int
chkSource(File * f)16145e96a66cSDavid du Colombier chkSource(File *f)
16155e96a66cSDavid du Colombier {
16165e96a66cSDavid du Colombier if(f->partial)
16175e96a66cSDavid du Colombier return 1;
16185e96a66cSDavid du Colombier
16195e96a66cSDavid du Colombier if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){
16205e96a66cSDavid du Colombier vtSetError(ERemoved);
16215e96a66cSDavid du Colombier return 0;
16225e96a66cSDavid du Colombier }
16235e96a66cSDavid du Colombier return 1;
16245e96a66cSDavid du Colombier }
16255e96a66cSDavid du Colombier
16265e96a66cSDavid du Colombier static int
fileRLock(File * f)16275e96a66cSDavid du Colombier fileRLock(File *f)
16285e96a66cSDavid du Colombier {
16295e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk));
16305e96a66cSDavid du Colombier vtRLock(f->lk);
16315e96a66cSDavid du Colombier if(!chkSource(f)){
16325e96a66cSDavid du Colombier fileRUnlock(f);
16335e96a66cSDavid du Colombier return 0;
16345e96a66cSDavid du Colombier }
16355e96a66cSDavid du Colombier return 1;
16365e96a66cSDavid du Colombier }
16375e96a66cSDavid du Colombier
16385e96a66cSDavid du Colombier static void
fileRUnlock(File * f)16395e96a66cSDavid du Colombier fileRUnlock(File *f)
16405e96a66cSDavid du Colombier {
16415e96a66cSDavid du Colombier vtRUnlock(f->lk);
16425e96a66cSDavid du Colombier }
16435e96a66cSDavid du Colombier
16445e96a66cSDavid du Colombier static int
fileLock(File * f)16455e96a66cSDavid du Colombier fileLock(File *f)
16465e96a66cSDavid du Colombier {
16475e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk));
16485e96a66cSDavid du Colombier vtLock(f->lk);
16495e96a66cSDavid du Colombier if(!chkSource(f)){
16505e96a66cSDavid du Colombier fileUnlock(f);
16515e96a66cSDavid du Colombier return 0;
16525e96a66cSDavid du Colombier }
16535e96a66cSDavid du Colombier return 1;
16545e96a66cSDavid du Colombier }
16555e96a66cSDavid du Colombier
16565e96a66cSDavid du Colombier static void
fileUnlock(File * f)16575e96a66cSDavid du Colombier fileUnlock(File *f)
16585e96a66cSDavid du Colombier {
16595e96a66cSDavid du Colombier vtUnlock(f->lk);
16605e96a66cSDavid du Colombier }
16615e96a66cSDavid du Colombier
16625e96a66cSDavid du Colombier /*
16635e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked.
16645e96a66cSDavid du Colombier * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2).
16655e96a66cSDavid du Colombier * We have to respect that ordering.
16665e96a66cSDavid du Colombier */
16675e96a66cSDavid du Colombier static void
fileMetaLock(File * f)16685e96a66cSDavid du Colombier fileMetaLock(File *f)
16695e96a66cSDavid du Colombier {
16705e96a66cSDavid du Colombier if(f->up == nil)
16715e96a66cSDavid du Colombier fprint(2, "f->elem = %s\n", f->dir.elem);
16725e96a66cSDavid du Colombier assert(f->up != nil);
16735e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk));
16745e96a66cSDavid du Colombier vtLock(f->up->lk);
16755e96a66cSDavid du Colombier }
16765e96a66cSDavid du Colombier
16775e96a66cSDavid du Colombier static void
fileMetaUnlock(File * f)16785e96a66cSDavid du Colombier fileMetaUnlock(File *f)
16795e96a66cSDavid du Colombier {
16805e96a66cSDavid du Colombier vtUnlock(f->up->lk);
16815e96a66cSDavid du Colombier }
16825e96a66cSDavid du Colombier
16835e96a66cSDavid du Colombier /*
16845e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked.
16855e96a66cSDavid du Colombier * see fileMetaLock.
16865e96a66cSDavid du Colombier */
16875e96a66cSDavid du Colombier static void
fileRAccess(File * f)16885e96a66cSDavid du Colombier fileRAccess(File* f)
16895e96a66cSDavid du Colombier {
1690f4051287SDavid du Colombier if(f->mode == OReadOnly || f->fs->noatimeupd)
16915e96a66cSDavid du Colombier return;
16925e96a66cSDavid du Colombier
16935e96a66cSDavid du Colombier fileMetaLock(f);
16945e96a66cSDavid du Colombier f->dir.atime = time(0L);
16955e96a66cSDavid du Colombier f->dirty = 1;
16965e96a66cSDavid du Colombier fileMetaUnlock(f);
16975e96a66cSDavid du Colombier }
16985e96a66cSDavid du Colombier
16995e96a66cSDavid du Colombier /*
17005e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked.
17015e96a66cSDavid du Colombier * see fileMetaLock.
17025e96a66cSDavid du Colombier */
17035e96a66cSDavid du Colombier static void
fileWAccess(File * f,char * mid)17045e96a66cSDavid du Colombier fileWAccess(File* f, char *mid)
17055e96a66cSDavid du Colombier {
17065e96a66cSDavid du Colombier if(f->mode == OReadOnly)
17075e96a66cSDavid du Colombier return;
17085e96a66cSDavid du Colombier
17095e96a66cSDavid du Colombier fileMetaLock(f);
17105e96a66cSDavid du Colombier f->dir.atime = f->dir.mtime = time(0L);
17115e96a66cSDavid du Colombier if(strcmp(f->dir.mid, mid) != 0){
17125e96a66cSDavid du Colombier vtMemFree(f->dir.mid);
17135e96a66cSDavid du Colombier f->dir.mid = vtStrDup(mid);
17145e96a66cSDavid du Colombier }
17155e96a66cSDavid du Colombier f->dir.mcount++;
17165e96a66cSDavid du Colombier f->dirty = 1;
17175e96a66cSDavid du Colombier fileMetaUnlock(f);
1718d58da526SDavid du Colombier
1719d58da526SDavid du Colombier /*RSC: let's try this */
1720d58da526SDavid du Colombier /*presotto - lets not
1721d58da526SDavid du Colombier if(f->up)
1722d58da526SDavid du Colombier fileWAccess(f->up, mid);
1723d58da526SDavid du Colombier */
17245e96a66cSDavid du Colombier }
17255e96a66cSDavid du Colombier
17265e96a66cSDavid du Colombier static int
getEntry(Source * r,Entry * e,int checkepoch)1727e569ccb5SDavid du Colombier getEntry(Source *r, Entry *e, int checkepoch)
17285e96a66cSDavid du Colombier {
1729e569ccb5SDavid du Colombier u32int epoch;
17305e96a66cSDavid du Colombier Block *b;
17315e96a66cSDavid du Colombier
17325e96a66cSDavid du Colombier if(r == nil){
17335e96a66cSDavid du Colombier memset(&e, 0, sizeof e);
17345e96a66cSDavid du Colombier return 1;
17355e96a66cSDavid du Colombier }
17365e96a66cSDavid du Colombier
17375e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly);
17385e96a66cSDavid du Colombier if(b == nil)
17395e96a66cSDavid du Colombier return 0;
17405e96a66cSDavid du Colombier if(!entryUnpack(e, b->data, r->offset % r->epb)){
17415e96a66cSDavid du Colombier blockPut(b);
17425e96a66cSDavid du Colombier return 0;
17435e96a66cSDavid du Colombier }
1744e569ccb5SDavid du Colombier epoch = b->l.epoch;
17455e96a66cSDavid du Colombier blockPut(b);
1746e569ccb5SDavid du Colombier
1747e569ccb5SDavid du Colombier if(checkepoch){
1748e569ccb5SDavid du Colombier b = cacheGlobal(r->fs->cache, e->score, entryType(e), e->tag, OReadOnly);
1749e569ccb5SDavid du Colombier if(b){
1750e569ccb5SDavid du Colombier if(b->l.epoch >= epoch)
1751e569ccb5SDavid du Colombier fprint(2, "warning: entry %p epoch not older %#.8ux/%d %V/%d in getEntry\n",
1752e569ccb5SDavid du Colombier r, b->addr, b->l.epoch, r->score, epoch);
1753e569ccb5SDavid du Colombier blockPut(b);
1754e569ccb5SDavid du Colombier }
1755e569ccb5SDavid du Colombier }
1756e569ccb5SDavid du Colombier
17575e96a66cSDavid du Colombier return 1;
17585e96a66cSDavid du Colombier }
17595e96a66cSDavid du Colombier
17605e96a66cSDavid du Colombier static int
setEntry(Source * r,Entry * e)17615e96a66cSDavid du Colombier setEntry(Source *r, Entry *e)
17625e96a66cSDavid du Colombier {
17635e96a66cSDavid du Colombier Block *b;
17645e96a66cSDavid du Colombier Entry oe;
17655e96a66cSDavid du Colombier
17665e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
17675e96a66cSDavid du Colombier if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
17685e96a66cSDavid du Colombier if(b == nil)
17695e96a66cSDavid du Colombier return 0;
17705e96a66cSDavid du Colombier if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
17715e96a66cSDavid du Colombier blockPut(b);
17725e96a66cSDavid du Colombier return 0;
17735e96a66cSDavid du Colombier }
17745e96a66cSDavid du Colombier e->gen = oe.gen;
17755e96a66cSDavid du Colombier entryPack(e, b->data, r->offset % r->epb);
17765e96a66cSDavid du Colombier
17775e96a66cSDavid du Colombier /* BUG b should depend on the entry pointer */
17785e96a66cSDavid du Colombier
17795e96a66cSDavid du Colombier blockDirty(b);
17805e96a66cSDavid du Colombier blockPut(b);
17815e96a66cSDavid du Colombier return 1;
17825e96a66cSDavid du Colombier }
17835e96a66cSDavid du Colombier
17845e96a66cSDavid du Colombier /* assumes hold elk */
17855e96a66cSDavid du Colombier int
fileSnapshot(File * dst,File * src,u32int epoch,int doarchive)17865e96a66cSDavid du Colombier fileSnapshot(File *dst, File *src, u32int epoch, int doarchive)
17875e96a66cSDavid du Colombier {
17885e96a66cSDavid du Colombier Entry e, ee;
17895e96a66cSDavid du Colombier
17905e96a66cSDavid du Colombier /* add link to snapshot */
17915e96a66cSDavid du Colombier if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1))
17925e96a66cSDavid du Colombier return 0;
17935e96a66cSDavid du Colombier
17945e96a66cSDavid du Colombier e.snap = epoch;
17955e96a66cSDavid du Colombier e.archive = doarchive;
17965e96a66cSDavid du Colombier ee.snap = epoch;
17975e96a66cSDavid du Colombier ee.archive = doarchive;
17985e96a66cSDavid du Colombier
17995e96a66cSDavid du Colombier if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee))
18005e96a66cSDavid du Colombier return 0;
18015e96a66cSDavid du Colombier return 1;
18025e96a66cSDavid du Colombier }
18035e96a66cSDavid du Colombier
18045e96a66cSDavid du Colombier int
fileGetSources(File * f,Entry * e,Entry * ee)1805e569ccb5SDavid du Colombier fileGetSources(File *f, Entry *e, Entry *ee)
18065e96a66cSDavid du Colombier {
1807e569ccb5SDavid du Colombier if(!getEntry(f->source, e, 0)
1808e569ccb5SDavid du Colombier || !getEntry(f->msource, ee, 0))
18095e96a66cSDavid du Colombier return 0;
18105e96a66cSDavid du Colombier return 1;
18115e96a66cSDavid du Colombier }
18125e96a66cSDavid du Colombier
1813e569ccb5SDavid du Colombier /*
1814e569ccb5SDavid du Colombier * Walk down to the block(s) containing the Entries
1815e569ccb5SDavid du Colombier * for f->source and f->msource, copying as we go.
1816e569ccb5SDavid du Colombier */
18175e96a66cSDavid du Colombier int
fileWalkSources(File * f)18185e96a66cSDavid du Colombier fileWalkSources(File *f)
18195e96a66cSDavid du Colombier {
1820e569ccb5SDavid du Colombier if(f->mode == OReadOnly){
1821e569ccb5SDavid du Colombier fprint(2, "readonly in fileWalkSources\n");
18225e96a66cSDavid du Colombier return 1;
1823e569ccb5SDavid du Colombier }
1824e569ccb5SDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadWrite)){
1825e569ccb5SDavid du Colombier fprint(2, "sourceLock2 failed in fileWalkSources\n");
18265e96a66cSDavid du Colombier return 0;
1827e569ccb5SDavid du Colombier }
18285e96a66cSDavid du Colombier sourceUnlock(f->source);
18295e96a66cSDavid du Colombier sourceUnlock(f->msource);
18305e96a66cSDavid du Colombier return 1;
18315e96a66cSDavid du Colombier }
18323b86f2f8SDavid du Colombier
18333b86f2f8SDavid du Colombier /*
18343b86f2f8SDavid du Colombier * convert File* to full path name in malloced string.
18353b86f2f8SDavid du Colombier * this hasn't been as useful as we hoped it would be.
18363b86f2f8SDavid du Colombier */
18373b86f2f8SDavid du Colombier char *
fileName(File * f)18383b86f2f8SDavid du Colombier fileName(File *f)
18393b86f2f8SDavid du Colombier {
18403b86f2f8SDavid du Colombier char *name, *pname;
18413b86f2f8SDavid du Colombier File *p;
18423b86f2f8SDavid du Colombier static char root[] = "/";
18433b86f2f8SDavid du Colombier
18443b86f2f8SDavid du Colombier if (f == nil)
18451bdadbfaSDavid du Colombier return vtStrDup("/**GOK**");
18463b86f2f8SDavid du Colombier
18473b86f2f8SDavid du Colombier p = fileGetParent(f);
18483b86f2f8SDavid du Colombier if (p == f)
18491bdadbfaSDavid du Colombier name = vtStrDup(root);
18503b86f2f8SDavid du Colombier else {
18513b86f2f8SDavid du Colombier pname = fileName(p);
18523b86f2f8SDavid du Colombier if (strcmp(pname, root) == 0)
18533b86f2f8SDavid du Colombier name = smprint("/%s", f->dir.elem);
18543b86f2f8SDavid du Colombier else
18553b86f2f8SDavid du Colombier name = smprint("%s/%s", pname, f->dir.elem);
18563b86f2f8SDavid du Colombier free(pname);
18573b86f2f8SDavid du Colombier }
18583b86f2f8SDavid du Colombier fileDecRef(p);
18593b86f2f8SDavid du Colombier return name;
18603b86f2f8SDavid du Colombier }
1861