15e96a66cSDavid du Colombier #include "stdinc.h" 25e96a66cSDavid du Colombier #include "dat.h" 35e96a66cSDavid du Colombier #include "fns.h" 45e96a66cSDavid du Colombier #include "error.h" 55e96a66cSDavid du Colombier 65e96a66cSDavid du Colombier /* 75e96a66cSDavid du Colombier * locking order is upwards. A thread can hold the lock for a File 85e96a66cSDavid du Colombier * and then acquire the lock of its parent 95e96a66cSDavid du Colombier */ 105e96a66cSDavid du Colombier 115e96a66cSDavid du Colombier struct File { 125e96a66cSDavid du Colombier Fs *fs; /* immutable */ 135e96a66cSDavid du Colombier 145e96a66cSDavid du Colombier /* meta data for file: protected by the lk in the parent */ 155e96a66cSDavid du Colombier int ref; /* holds this data structure up */ 165e96a66cSDavid du Colombier 175e96a66cSDavid du Colombier int partial; /* file was never really open */ 185e96a66cSDavid du Colombier int removed; /* file has been removed */ 195e96a66cSDavid du Colombier int dirty; /* dir is dirty with respect to meta data in block */ 205e96a66cSDavid du Colombier u32int boff; /* block offset within msource for this file's meta data */ 215e96a66cSDavid du Colombier 225e96a66cSDavid du Colombier DirEntry dir; /* meta data for this file */ 235e96a66cSDavid du Colombier 245e96a66cSDavid du Colombier File *up; /* parent file */ 255e96a66cSDavid du Colombier File *next; /* sibling */ 265e96a66cSDavid du Colombier 275e96a66cSDavid du Colombier /* data for file */ 285e96a66cSDavid du Colombier VtLock *lk; /* lock for the following */ 295e96a66cSDavid du Colombier Source *source; 305e96a66cSDavid du Colombier Source *msource; /* for directories: meta data for children */ 315e96a66cSDavid du Colombier File *down; /* children */ 325e96a66cSDavid du Colombier 335e96a66cSDavid du Colombier int mode; 345e96a66cSDavid du Colombier }; 355e96a66cSDavid du Colombier 365e96a66cSDavid du Colombier static int fileMetaFlush2(File*, char*); 375e96a66cSDavid du Colombier static u32int fileMetaAlloc(File*, DirEntry*, u32int); 385e96a66cSDavid du Colombier static int fileRLock(File*); 395e96a66cSDavid du Colombier static void fileRUnlock(File*); 405e96a66cSDavid du Colombier static int fileLock(File*); 415e96a66cSDavid du Colombier static void fileUnlock(File*); 425e96a66cSDavid du Colombier static void fileMetaLock(File*); 435e96a66cSDavid du Colombier static void fileMetaUnlock(File*); 445e96a66cSDavid du Colombier static void fileRAccess(File*); 455e96a66cSDavid du Colombier static void fileWAccess(File*, char*); 465e96a66cSDavid du Colombier 475e96a66cSDavid du Colombier static File * 485e96a66cSDavid du Colombier fileAlloc(Fs *fs) 495e96a66cSDavid du Colombier { 505e96a66cSDavid du Colombier File *f; 515e96a66cSDavid du Colombier 525e96a66cSDavid du Colombier f = vtMemAllocZ(sizeof(File)); 535e96a66cSDavid du Colombier f->lk = vtLockAlloc(); 545e96a66cSDavid du Colombier f->ref = 1; 555e96a66cSDavid du Colombier f->fs = fs; 565e96a66cSDavid du Colombier f->boff = NilBlock; 575e96a66cSDavid du Colombier f->mode = fs->mode; 585e96a66cSDavid du Colombier return f; 595e96a66cSDavid du Colombier } 605e96a66cSDavid du Colombier 615e96a66cSDavid du Colombier static void 625e96a66cSDavid du Colombier fileFree(File *f) 635e96a66cSDavid du Colombier { 645e96a66cSDavid du Colombier sourceClose(f->source); 655e96a66cSDavid du Colombier vtLockFree(f->lk); 665e96a66cSDavid du Colombier sourceClose(f->msource); 675e96a66cSDavid du Colombier deCleanup(&f->dir); 685e96a66cSDavid du Colombier 695e96a66cSDavid du Colombier memset(f, ~0, sizeof(File)); 705e96a66cSDavid du Colombier vtMemFree(f); 715e96a66cSDavid du Colombier } 725e96a66cSDavid du Colombier 735e96a66cSDavid du Colombier /* 745e96a66cSDavid du Colombier * the file is locked already 755e96a66cSDavid du Colombier * f->msource is unlocked 765e96a66cSDavid du Colombier */ 775e96a66cSDavid du Colombier static File * 785e96a66cSDavid du Colombier dirLookup(File *f, char *elem) 795e96a66cSDavid du Colombier { 805e96a66cSDavid du Colombier int i; 815e96a66cSDavid du Colombier MetaBlock mb; 825e96a66cSDavid du Colombier MetaEntry me; 835e96a66cSDavid du Colombier Block *b; 845e96a66cSDavid du Colombier Source *meta; 855e96a66cSDavid du Colombier File *ff; 865e96a66cSDavid du Colombier u32int bo, nb; 875e96a66cSDavid du Colombier 885e96a66cSDavid du Colombier meta = f->msource; 895e96a66cSDavid du Colombier b = nil; 905e96a66cSDavid du Colombier if(!sourceLock(meta, -1)) 915e96a66cSDavid du Colombier return nil; 925e96a66cSDavid du Colombier nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize; 935e96a66cSDavid du Colombier for(bo=0; bo<nb; bo++){ 945e96a66cSDavid du Colombier b = sourceBlock(meta, bo, OReadOnly); 955e96a66cSDavid du Colombier if(b == nil) 965e96a66cSDavid du Colombier goto Err; 975e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 985e96a66cSDavid du Colombier goto Err; 995e96a66cSDavid du Colombier if(mbSearch(&mb, elem, &i, &me)){ 1005e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 1015e96a66cSDavid du Colombier if(!deUnpack(&ff->dir, &me)){ 1025e96a66cSDavid du Colombier fileFree(ff); 1035e96a66cSDavid du Colombier goto Err; 1045e96a66cSDavid du Colombier } 1055e96a66cSDavid du Colombier sourceUnlock(meta); 1065e96a66cSDavid du Colombier blockPut(b); 1075e96a66cSDavid du Colombier ff->boff = bo; 1085e96a66cSDavid du Colombier ff->mode = f->mode; 1095e96a66cSDavid du Colombier return ff; 1105e96a66cSDavid du Colombier } 1115e96a66cSDavid du Colombier 1125e96a66cSDavid du Colombier blockPut(b); 1135e96a66cSDavid du Colombier b = nil; 1145e96a66cSDavid du Colombier } 1155e96a66cSDavid du Colombier vtSetError(ENoFile); 1165e96a66cSDavid du Colombier /* fall through */ 1175e96a66cSDavid du Colombier Err: 1185e96a66cSDavid du Colombier sourceUnlock(meta); 1195e96a66cSDavid du Colombier blockPut(b); 1205e96a66cSDavid du Colombier return nil; 1215e96a66cSDavid du Colombier } 1225e96a66cSDavid du Colombier 1235e96a66cSDavid du Colombier File * 1245e96a66cSDavid du Colombier fileRoot(Source *r) 1255e96a66cSDavid du Colombier { 1265e96a66cSDavid du Colombier Block *b; 1275e96a66cSDavid du Colombier Source *r0, *r1, *r2; 1285e96a66cSDavid du Colombier MetaBlock mb; 1295e96a66cSDavid du Colombier MetaEntry me; 1305e96a66cSDavid du Colombier File *root, *mr; 1315e96a66cSDavid du Colombier Fs *fs; 1325e96a66cSDavid du Colombier 1335e96a66cSDavid du Colombier b = nil; 1345e96a66cSDavid du Colombier root = nil; 1355e96a66cSDavid du Colombier mr = nil; 1365e96a66cSDavid du Colombier r1 = nil; 1375e96a66cSDavid du Colombier r2 = nil; 1385e96a66cSDavid du Colombier 1395e96a66cSDavid du Colombier fs = r->fs; 1405e96a66cSDavid du Colombier if(!sourceLock(r, -1)) 1415e96a66cSDavid du Colombier return nil; 1425e96a66cSDavid du Colombier r0 = sourceOpen(r, 0, fs->mode); 1435e96a66cSDavid du Colombier if(r0 == nil) 1445e96a66cSDavid du Colombier goto Err; 1455e96a66cSDavid du Colombier r1 = sourceOpen(r, 1, fs->mode); 1465e96a66cSDavid du Colombier if(r1 == nil) 1475e96a66cSDavid du Colombier goto Err; 1485e96a66cSDavid du Colombier r2 = sourceOpen(r, 2, fs->mode); 1495e96a66cSDavid du Colombier if(r2 == nil) 1505e96a66cSDavid du Colombier goto Err; 1515e96a66cSDavid du Colombier 1525e96a66cSDavid du Colombier mr = fileAlloc(fs); 1535e96a66cSDavid du Colombier mr->msource = r2; 1545e96a66cSDavid du Colombier r2 = nil; 1555e96a66cSDavid du Colombier 1565e96a66cSDavid du Colombier root = fileAlloc(fs); 1575e96a66cSDavid du Colombier root->boff = 0; 1585e96a66cSDavid du Colombier root->up = mr; 1595e96a66cSDavid du Colombier root->source = r0; 1605e96a66cSDavid du Colombier r0 = nil; 1615e96a66cSDavid du Colombier root->msource = r1; 1625e96a66cSDavid du Colombier r1 = nil; 1635e96a66cSDavid du Colombier 1645e96a66cSDavid du Colombier mr->down = root; 1655e96a66cSDavid du Colombier 1665e96a66cSDavid du Colombier if(!sourceLock(mr->msource, -1)) 1675e96a66cSDavid du Colombier goto Err; 1685e96a66cSDavid du Colombier b = sourceBlock(mr->msource, 0, OReadOnly); 1695e96a66cSDavid du Colombier sourceUnlock(mr->msource); 1705e96a66cSDavid du Colombier if(b == nil) 1715e96a66cSDavid du Colombier goto Err; 1725e96a66cSDavid du Colombier 1735e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, mr->msource->dsize)) 1745e96a66cSDavid du Colombier goto Err; 1755e96a66cSDavid du Colombier 1765e96a66cSDavid du Colombier meUnpack(&me, &mb, 0); 1775e96a66cSDavid du Colombier if(!deUnpack(&root->dir, &me)) 1785e96a66cSDavid du Colombier goto Err; 1795e96a66cSDavid du Colombier blockPut(b); 1805e96a66cSDavid du Colombier sourceUnlock(r); 1815e96a66cSDavid du Colombier fileRAccess(root); 1825e96a66cSDavid du Colombier 1835e96a66cSDavid du Colombier return root; 1845e96a66cSDavid du Colombier Err: 1855e96a66cSDavid du Colombier blockPut(b); 1865e96a66cSDavid du Colombier if(r0) 1875e96a66cSDavid du Colombier sourceClose(r0); 1885e96a66cSDavid du Colombier if(r1) 1895e96a66cSDavid du Colombier sourceClose(r1); 1905e96a66cSDavid du Colombier if(r2) 1915e96a66cSDavid du Colombier sourceClose(r2); 1925e96a66cSDavid du Colombier if(mr) 1935e96a66cSDavid du Colombier fileFree(mr); 1945e96a66cSDavid du Colombier if(root) 1955e96a66cSDavid du Colombier fileFree(root); 1965e96a66cSDavid du Colombier sourceUnlock(r); 1975e96a66cSDavid du Colombier 1985e96a66cSDavid du Colombier return nil; 1995e96a66cSDavid du Colombier } 2005e96a66cSDavid du Colombier 2015e96a66cSDavid du Colombier static Source * 2025e96a66cSDavid du Colombier fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode) 2035e96a66cSDavid du Colombier { 2045e96a66cSDavid du Colombier Source *r; 2055e96a66cSDavid du Colombier 2065e96a66cSDavid du Colombier if(!sourceLock(f->source, mode)) 2075e96a66cSDavid du Colombier return nil; 2085e96a66cSDavid du Colombier r = sourceOpen(f->source, offset, mode); 2095e96a66cSDavid du Colombier sourceUnlock(f->source); 2105e96a66cSDavid du Colombier if(r == nil) 2115e96a66cSDavid du Colombier return nil; 2125e96a66cSDavid du Colombier if(r->gen != gen){ 2135e96a66cSDavid du Colombier vtSetError(ERemoved); 2145e96a66cSDavid du Colombier goto Err; 2155e96a66cSDavid du Colombier } 2165e96a66cSDavid du Colombier if(r->dir != dir && r->mode != -1){ 2175e96a66cSDavid du Colombier fprint(2, "fileOpenSource: dir mismatch %d %d\n", r->dir, dir); 2185e96a66cSDavid du Colombier vtSetError(EBadMeta); 2195e96a66cSDavid du Colombier goto Err; 2205e96a66cSDavid du Colombier } 2215e96a66cSDavid du Colombier return r; 2225e96a66cSDavid du Colombier Err: 2235e96a66cSDavid du Colombier sourceClose(r); 2245e96a66cSDavid du Colombier return nil; 2255e96a66cSDavid du Colombier } 2265e96a66cSDavid du Colombier 2275e96a66cSDavid du Colombier File * 2285e96a66cSDavid du Colombier _fileWalk(File *f, char *elem, int partial) 2295e96a66cSDavid du Colombier { 2305e96a66cSDavid du Colombier File *ff; 2315e96a66cSDavid du Colombier 2325e96a66cSDavid du Colombier fileRAccess(f); 2335e96a66cSDavid du Colombier 2345e96a66cSDavid du Colombier if(elem[0] == 0){ 2355e96a66cSDavid du Colombier vtSetError(EBadPath); 2365e96a66cSDavid du Colombier return nil; 2375e96a66cSDavid du Colombier } 2385e96a66cSDavid du Colombier 2395e96a66cSDavid du Colombier if(!fileIsDir(f)){ 2405e96a66cSDavid du Colombier vtSetError(ENotDir); 2415e96a66cSDavid du Colombier return nil; 2425e96a66cSDavid du Colombier } 2435e96a66cSDavid du Colombier 2445e96a66cSDavid du Colombier if(strcmp(elem, ".") == 0){ 2455e96a66cSDavid du Colombier return fileIncRef(f); 2465e96a66cSDavid du Colombier } 2475e96a66cSDavid du Colombier 2485e96a66cSDavid du Colombier if(strcmp(elem, "..") == 0){ 2495e96a66cSDavid du Colombier if(fileIsRoot(f)) 2505e96a66cSDavid du Colombier return fileIncRef(f); 2515e96a66cSDavid du Colombier return fileIncRef(f->up); 2525e96a66cSDavid du Colombier } 2535e96a66cSDavid du Colombier 2545e96a66cSDavid du Colombier if(!fileLock(f)) 2555e96a66cSDavid du Colombier return nil; 2565e96a66cSDavid du Colombier 2575e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 2585e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 2595e96a66cSDavid du Colombier ff->ref++; 2605e96a66cSDavid du Colombier goto Exit; 2615e96a66cSDavid du Colombier } 2625e96a66cSDavid du Colombier } 2635e96a66cSDavid du Colombier 2645e96a66cSDavid du Colombier ff = dirLookup(f, elem); 2655e96a66cSDavid du Colombier if(ff == nil) 2665e96a66cSDavid du Colombier goto Err; 2675e96a66cSDavid du Colombier 2685e96a66cSDavid du Colombier if(ff->dir.mode & ModeSnapshot) 2695e96a66cSDavid du Colombier ff->mode = OReadOnly; 2705e96a66cSDavid du Colombier 2715e96a66cSDavid du Colombier if(partial){ 2725e96a66cSDavid du Colombier /* 2735e96a66cSDavid du Colombier * Do nothing. We're opening this file only so we can clri it. 2745e96a66cSDavid du Colombier * Usually the sources can't be opened, hence we won't even bother. 2755e96a66cSDavid du Colombier * Be VERY careful with the returned file. If you hand it to a routine 2765e96a66cSDavid du Colombier * expecting ff->source and/or ff->msource to be non-nil, we're 2775e96a66cSDavid du Colombier * likely to dereference nil. FileClri should be the only routine 2785e96a66cSDavid du Colombier * setting partial. 2795e96a66cSDavid du Colombier */ 2805e96a66cSDavid du Colombier ff->partial = 1; 2815e96a66cSDavid du Colombier }else if(ff->dir.mode & ModeDir){ 2825e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode); 2835e96a66cSDavid du Colombier ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode); 2845e96a66cSDavid du Colombier if(ff->source == nil || ff->msource == nil) 2855e96a66cSDavid du Colombier goto Err; 2865e96a66cSDavid du Colombier }else{ 2875e96a66cSDavid du Colombier ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode); 2885e96a66cSDavid du Colombier if(ff->source == nil) 2895e96a66cSDavid du Colombier goto Err; 2905e96a66cSDavid du Colombier } 2915e96a66cSDavid du Colombier 2925e96a66cSDavid du Colombier /* link in and up parent ref count */ 2935e96a66cSDavid du Colombier ff->next = f->down; 2945e96a66cSDavid du Colombier f->down = ff; 2955e96a66cSDavid du Colombier ff->up = f; 2965e96a66cSDavid du Colombier fileIncRef(f); 2975e96a66cSDavid du Colombier Exit: 2985e96a66cSDavid du Colombier fileUnlock(f); 2995e96a66cSDavid du Colombier return ff; 3005e96a66cSDavid du Colombier Err: 3015e96a66cSDavid du Colombier fileUnlock(f); 3025e96a66cSDavid du Colombier if(ff != nil) 3035e96a66cSDavid du Colombier fileDecRef(ff); 3045e96a66cSDavid du Colombier return nil; 3055e96a66cSDavid du Colombier } 3065e96a66cSDavid du Colombier 3075e96a66cSDavid du Colombier File * 3085e96a66cSDavid du Colombier fileWalk(File *f, char *elem) 3095e96a66cSDavid du Colombier { 3105e96a66cSDavid du Colombier return _fileWalk(f, elem, 0); 3115e96a66cSDavid du Colombier } 3125e96a66cSDavid du Colombier 3135e96a66cSDavid du Colombier File * 3145e96a66cSDavid du Colombier _fileOpen(Fs *fs, char *path, int partial) 3155e96a66cSDavid du Colombier { 3165e96a66cSDavid du Colombier File *f, *ff; 317f8e525acSDavid du Colombier char *p, elem[VtMaxStringSize], *opath; 3185e96a66cSDavid du Colombier int n; 3195e96a66cSDavid du Colombier 3205e96a66cSDavid du Colombier f = fs->file; 3215e96a66cSDavid du Colombier fileIncRef(f); 322f8e525acSDavid du Colombier opath = path; 3235e96a66cSDavid du Colombier while(*path != 0){ 3245e96a66cSDavid du Colombier for(p = path; *p && *p != '/'; p++) 3255e96a66cSDavid du Colombier ; 3265e96a66cSDavid du Colombier n = p - path; 3275e96a66cSDavid du Colombier if(n > 0){ 3285e96a66cSDavid du Colombier if(n > VtMaxStringSize){ 329f8e525acSDavid du Colombier vtSetError("%s: element too long", EBadPath); 3305e96a66cSDavid du Colombier goto Err; 3315e96a66cSDavid du Colombier } 3325e96a66cSDavid du Colombier memmove(elem, path, n); 3335e96a66cSDavid du Colombier elem[n] = 0; 3345e96a66cSDavid du Colombier ff = _fileWalk(f, elem, partial && *p=='\0'); 335f8e525acSDavid du Colombier if(ff == nil){ 336f8e525acSDavid du Colombier vtSetError("%.*s: %R", utfnlen(opath, p-opath), opath); 3375e96a66cSDavid du Colombier goto Err; 338f8e525acSDavid du Colombier } 3395e96a66cSDavid du Colombier fileDecRef(f); 3405e96a66cSDavid du Colombier f = ff; 3415e96a66cSDavid du Colombier } 3425e96a66cSDavid du Colombier if(*p == '/') 3435e96a66cSDavid du Colombier p++; 3445e96a66cSDavid du Colombier path = p; 3455e96a66cSDavid du Colombier } 3465e96a66cSDavid du Colombier return f; 3475e96a66cSDavid du Colombier Err: 3485e96a66cSDavid du Colombier fileDecRef(f); 3495e96a66cSDavid du Colombier return nil; 3505e96a66cSDavid du Colombier } 3515e96a66cSDavid du Colombier 3525e96a66cSDavid du Colombier File* 3535e96a66cSDavid du Colombier fileOpen(Fs *fs, char *path) 3545e96a66cSDavid du Colombier { 3555e96a66cSDavid du Colombier return _fileOpen(fs, path, 0); 3565e96a66cSDavid du Colombier } 3575e96a66cSDavid du Colombier 3585e96a66cSDavid du Colombier File * 3595e96a66cSDavid du Colombier fileCreate(File *f, char *elem, ulong mode, char *uid) 3605e96a66cSDavid du Colombier { 3615e96a66cSDavid du Colombier File *ff; 3625e96a66cSDavid du Colombier DirEntry *dir; 3635e96a66cSDavid du Colombier Source *pr, *r, *mr; 3645e96a66cSDavid du Colombier int isdir; 3655e96a66cSDavid du Colombier 3665e96a66cSDavid du Colombier if(!fileLock(f)) 3675e96a66cSDavid du Colombier return nil; 3685e96a66cSDavid du Colombier 3695e96a66cSDavid du Colombier r = nil; 3705e96a66cSDavid du Colombier mr = nil; 3715e96a66cSDavid du Colombier for(ff = f->down; ff; ff=ff->next){ 3725e96a66cSDavid du Colombier if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ 3735e96a66cSDavid du Colombier ff = nil; 3745e96a66cSDavid du Colombier vtSetError(EExists); 3755e96a66cSDavid du Colombier goto Err1; 3765e96a66cSDavid du Colombier } 3775e96a66cSDavid du Colombier } 3785e96a66cSDavid du Colombier 3795e96a66cSDavid du Colombier ff = dirLookup(f, elem); 3805e96a66cSDavid du Colombier if(ff != nil){ 3815e96a66cSDavid du Colombier vtSetError(EExists); 3825e96a66cSDavid du Colombier goto Err1; 3835e96a66cSDavid du Colombier } 3845e96a66cSDavid du Colombier 3855e96a66cSDavid du Colombier pr = f->source; 3865e96a66cSDavid du Colombier if(pr->mode != OReadWrite){ 3875e96a66cSDavid du Colombier vtSetError(EReadOnly); 3885e96a66cSDavid du Colombier goto Err1; 3895e96a66cSDavid du Colombier } 3905e96a66cSDavid du Colombier 3915e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 3925e96a66cSDavid du Colombier goto Err1; 3935e96a66cSDavid du Colombier 3945e96a66cSDavid du Colombier ff = fileAlloc(f->fs); 3955e96a66cSDavid du Colombier isdir = mode & ModeDir; 3965e96a66cSDavid du Colombier 3975e96a66cSDavid du Colombier r = sourceCreate(pr, pr->dsize, isdir, 0); 3985e96a66cSDavid du Colombier if(r == nil) 3995e96a66cSDavid du Colombier goto Err; 4005e96a66cSDavid du Colombier if(isdir){ 4015e96a66cSDavid du Colombier mr = sourceCreate(pr, pr->dsize, 0, r->offset); 4025e96a66cSDavid du Colombier if(mr == nil) 4035e96a66cSDavid du Colombier goto Err; 4045e96a66cSDavid du Colombier } 4055e96a66cSDavid du Colombier 4065e96a66cSDavid du Colombier dir = &ff->dir; 4075e96a66cSDavid du Colombier dir->elem = vtStrDup(elem); 4085e96a66cSDavid du Colombier dir->entry = r->offset; 4095e96a66cSDavid du Colombier dir->gen = r->gen; 4105e96a66cSDavid du Colombier if(isdir){ 4115e96a66cSDavid du Colombier dir->mentry = mr->offset; 4125e96a66cSDavid du Colombier dir->mgen = mr->gen; 4135e96a66cSDavid du Colombier } 4145e96a66cSDavid du Colombier dir->size = 0; 4155e96a66cSDavid du Colombier if(!fsNextQid(f->fs, &dir->qid)) 4165e96a66cSDavid du Colombier goto Err; 4175e96a66cSDavid du Colombier dir->uid = vtStrDup(uid); 4185e96a66cSDavid du Colombier dir->gid = vtStrDup(f->dir.gid); 4195e96a66cSDavid du Colombier dir->mid = vtStrDup(uid); 4205e96a66cSDavid du Colombier dir->mtime = time(0L); 4215e96a66cSDavid du Colombier dir->mcount = 0; 4225e96a66cSDavid du Colombier dir->ctime = dir->mtime; 4235e96a66cSDavid du Colombier dir->atime = dir->mtime; 4245e96a66cSDavid du Colombier dir->mode = mode; 4255e96a66cSDavid du Colombier 4265e96a66cSDavid du Colombier ff->boff = fileMetaAlloc(f, dir, 0); 4275e96a66cSDavid du Colombier if(ff->boff == NilBlock) 4285e96a66cSDavid du Colombier goto Err; 4295e96a66cSDavid du Colombier 430dc5a79c1SDavid du Colombier /* committed */ 4315e96a66cSDavid du Colombier sourceUnlock(f->source); 4325e96a66cSDavid du Colombier sourceUnlock(f->msource); 4335e96a66cSDavid du Colombier 4345e96a66cSDavid du Colombier ff->source = r; 4355e96a66cSDavid du Colombier ff->msource = mr; 4365e96a66cSDavid du Colombier 4375e96a66cSDavid du Colombier /* link in and up parent ref count */ 4385e96a66cSDavid du Colombier ff->next = f->down; 4395e96a66cSDavid du Colombier f->down = ff; 4405e96a66cSDavid du Colombier ff->up = f; 4415e96a66cSDavid du Colombier fileIncRef(f); 4425e96a66cSDavid du Colombier 4435e96a66cSDavid du Colombier fileWAccess(f, uid); 4445e96a66cSDavid du Colombier 4455e96a66cSDavid du Colombier fileUnlock(f); 4465e96a66cSDavid du Colombier return ff; 4475e96a66cSDavid du Colombier 4485e96a66cSDavid du Colombier Err: 4495e96a66cSDavid du Colombier sourceUnlock(f->source); 4505e96a66cSDavid du Colombier sourceUnlock(f->msource); 4515e96a66cSDavid du Colombier Err1: 452dc5a79c1SDavid du Colombier if(r){ 453dc5a79c1SDavid du Colombier sourceLock(r, -1); 4545e96a66cSDavid du Colombier sourceRemove(r); 455dc5a79c1SDavid du Colombier } 456dc5a79c1SDavid du Colombier if(mr){ 457dc5a79c1SDavid du Colombier sourceLock(mr, -1); 4585e96a66cSDavid du Colombier sourceRemove(mr); 459dc5a79c1SDavid du Colombier } 4605e96a66cSDavid du Colombier if(ff) 4615e96a66cSDavid du Colombier fileDecRef(ff); 4625e96a66cSDavid du Colombier fileUnlock(f); 4635e96a66cSDavid du Colombier return 0; 4645e96a66cSDavid du Colombier } 4655e96a66cSDavid du Colombier 4665e96a66cSDavid du Colombier int 4675e96a66cSDavid du Colombier fileRead(File *f, void *buf, int cnt, vlong offset) 4685e96a66cSDavid du Colombier { 4695e96a66cSDavid du Colombier Source *s; 4705e96a66cSDavid du Colombier uvlong size; 4715e96a66cSDavid du Colombier u32int bn; 4725e96a66cSDavid du Colombier int off, dsize, n, nn; 4735e96a66cSDavid du Colombier Block *b; 4745e96a66cSDavid du Colombier uchar *p; 4755e96a66cSDavid du Colombier 4765e96a66cSDavid du Colombier if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset); 4775e96a66cSDavid du Colombier 4785e96a66cSDavid du Colombier if(!fileRLock(f)) 4795e96a66cSDavid du Colombier return -1; 4805e96a66cSDavid du Colombier 4815e96a66cSDavid du Colombier if(offset < 0){ 4825e96a66cSDavid du Colombier vtSetError(EBadOffset); 4835e96a66cSDavid du Colombier goto Err1; 4845e96a66cSDavid du Colombier } 4855e96a66cSDavid du Colombier 4865e96a66cSDavid du Colombier fileRAccess(f); 4875e96a66cSDavid du Colombier 4885e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)) 4895e96a66cSDavid du Colombier goto Err1; 4905e96a66cSDavid du Colombier 4915e96a66cSDavid du Colombier s = f->source; 4925e96a66cSDavid du Colombier dsize = s->dsize; 4935e96a66cSDavid du Colombier size = sourceGetSize(s); 4945e96a66cSDavid du Colombier 4955e96a66cSDavid du Colombier if(offset >= size) 4965e96a66cSDavid du Colombier offset = size; 4975e96a66cSDavid du Colombier 4985e96a66cSDavid du Colombier if(cnt > size-offset) 4995e96a66cSDavid du Colombier cnt = size-offset; 5005e96a66cSDavid du Colombier bn = offset/dsize; 5015e96a66cSDavid du Colombier off = offset%dsize; 5025e96a66cSDavid du Colombier p = buf; 5035e96a66cSDavid du Colombier while(cnt > 0){ 5045e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 5055e96a66cSDavid du Colombier if(b == nil) 5065e96a66cSDavid du Colombier goto Err; 5075e96a66cSDavid du Colombier n = cnt; 5085e96a66cSDavid du Colombier if(n > dsize-off) 5095e96a66cSDavid du Colombier n = dsize-off; 5105e96a66cSDavid du Colombier nn = dsize-off; 5115e96a66cSDavid du Colombier if(nn > n) 5125e96a66cSDavid du Colombier nn = n; 5135e96a66cSDavid du Colombier memmove(p, b->data+off, nn); 5145e96a66cSDavid du Colombier memset(p+nn, 0, nn-n); 5155e96a66cSDavid du Colombier off = 0; 5165e96a66cSDavid du Colombier bn++; 5175e96a66cSDavid du Colombier cnt -= n; 5185e96a66cSDavid du Colombier p += n; 5195e96a66cSDavid du Colombier blockPut(b); 5205e96a66cSDavid du Colombier } 5215e96a66cSDavid du Colombier sourceUnlock(s); 5225e96a66cSDavid du Colombier fileRUnlock(f); 5235e96a66cSDavid du Colombier return p-(uchar*)buf; 5245e96a66cSDavid du Colombier 5255e96a66cSDavid du Colombier Err: 5265e96a66cSDavid du Colombier sourceUnlock(s); 5275e96a66cSDavid du Colombier Err1: 5285e96a66cSDavid du Colombier fileRUnlock(f); 5295e96a66cSDavid du Colombier return -1; 5305e96a66cSDavid du Colombier } 5315e96a66cSDavid du Colombier 5325e96a66cSDavid du Colombier int 5335e96a66cSDavid du Colombier fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid) 5345e96a66cSDavid du Colombier { 5355e96a66cSDavid du Colombier Source *s; 5365e96a66cSDavid du Colombier ulong bn; 5375e96a66cSDavid du Colombier int off, dsize, n; 5385e96a66cSDavid du Colombier Block *b; 5395e96a66cSDavid du Colombier uchar *p; 5405e96a66cSDavid du Colombier vlong eof; 5415e96a66cSDavid du Colombier 5425e96a66cSDavid du Colombier if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); 5435e96a66cSDavid du Colombier 5445e96a66cSDavid du Colombier if(!fileLock(f)) 5455e96a66cSDavid du Colombier return -1; 5465e96a66cSDavid du Colombier 5475e96a66cSDavid du Colombier s = nil; 5485e96a66cSDavid du Colombier if(f->dir.mode & ModeDir){ 5495e96a66cSDavid du Colombier vtSetError(ENotFile); 5505e96a66cSDavid du Colombier goto Err; 5515e96a66cSDavid du Colombier } 5525e96a66cSDavid du Colombier 5535e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 5545e96a66cSDavid du Colombier vtSetError(EReadOnly); 5555e96a66cSDavid du Colombier goto Err; 5565e96a66cSDavid du Colombier } 5575e96a66cSDavid du Colombier if(offset < 0){ 5585e96a66cSDavid du Colombier vtSetError(EBadOffset); 5595e96a66cSDavid du Colombier goto Err; 5605e96a66cSDavid du Colombier } 5615e96a66cSDavid du Colombier 5625e96a66cSDavid du Colombier fileWAccess(f, uid); 5635e96a66cSDavid du Colombier 5645e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 5655e96a66cSDavid du Colombier goto Err; 5665e96a66cSDavid du Colombier s = f->source; 5675e96a66cSDavid du Colombier dsize = s->dsize; 5685e96a66cSDavid du Colombier 5695e96a66cSDavid du Colombier eof = sourceGetSize(s); 5705e96a66cSDavid du Colombier if(f->dir.mode & ModeAppend) 5715e96a66cSDavid du Colombier offset = eof; 5725e96a66cSDavid du Colombier bn = offset/dsize; 5735e96a66cSDavid du Colombier off = offset%dsize; 5745e96a66cSDavid du Colombier p = buf; 5755e96a66cSDavid du Colombier while(cnt > 0){ 5765e96a66cSDavid du Colombier n = cnt; 5775e96a66cSDavid du Colombier if(n > dsize-off) 5785e96a66cSDavid du Colombier n = dsize-off; 5795e96a66cSDavid du Colombier b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite); 5805e96a66cSDavid du Colombier if(b == nil){ 5815e96a66cSDavid du Colombier if(offset > eof) 5825e96a66cSDavid du Colombier sourceSetSize(s, offset); 5835e96a66cSDavid du Colombier goto Err; 5845e96a66cSDavid du Colombier } 5855e96a66cSDavid du Colombier memmove(b->data+off, p, n); 5865e96a66cSDavid du Colombier off = 0; 5875e96a66cSDavid du Colombier cnt -= n; 5885e96a66cSDavid du Colombier p += n; 5895e96a66cSDavid du Colombier offset += n; 5905e96a66cSDavid du Colombier bn++; 5915e96a66cSDavid du Colombier blockDirty(b); 5925e96a66cSDavid du Colombier blockPut(b); 5935e96a66cSDavid du Colombier } 5945e96a66cSDavid du Colombier if(offset > eof && !sourceSetSize(s, offset)) 5955e96a66cSDavid du Colombier goto Err; 5965e96a66cSDavid du Colombier sourceUnlock(s); 5975e96a66cSDavid du Colombier fileUnlock(f); 5985e96a66cSDavid du Colombier return p-(uchar*)buf; 5995e96a66cSDavid du Colombier Err: 6005e96a66cSDavid du Colombier if(s) 6015e96a66cSDavid du Colombier sourceUnlock(s); 6025e96a66cSDavid du Colombier fileUnlock(f); 6035e96a66cSDavid du Colombier return -1; 6045e96a66cSDavid du Colombier } 6055e96a66cSDavid du Colombier 6065e96a66cSDavid du Colombier int 6075e96a66cSDavid du Colombier fileGetDir(File *f, DirEntry *dir) 6085e96a66cSDavid du Colombier { 6095e96a66cSDavid du Colombier if(!fileRLock(f)) 6105e96a66cSDavid du Colombier return 0; 6115e96a66cSDavid du Colombier 6125e96a66cSDavid du Colombier fileMetaLock(f); 6135e96a66cSDavid du Colombier deCopy(dir, &f->dir); 6145e96a66cSDavid du Colombier fileMetaUnlock(f); 6155e96a66cSDavid du Colombier 6165e96a66cSDavid du Colombier if(!fileIsDir(f)){ 6175e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 6185e96a66cSDavid du Colombier fileRUnlock(f); 6195e96a66cSDavid du Colombier return 0; 6205e96a66cSDavid du Colombier } 6215e96a66cSDavid du Colombier dir->size = sourceGetSize(f->source); 6225e96a66cSDavid du Colombier sourceUnlock(f->source); 6235e96a66cSDavid du Colombier } 6245e96a66cSDavid du Colombier fileRUnlock(f); 6255e96a66cSDavid du Colombier 6265e96a66cSDavid du Colombier return 1; 6275e96a66cSDavid du Colombier } 6285e96a66cSDavid du Colombier 6295e96a66cSDavid du Colombier int 6305e96a66cSDavid du Colombier fileTruncate(File *f, char *uid) 6315e96a66cSDavid du Colombier { 6325e96a66cSDavid du Colombier if(fileIsDir(f)){ 6335e96a66cSDavid du Colombier vtSetError(ENotFile); 6345e96a66cSDavid du Colombier return 0; 6355e96a66cSDavid du Colombier } 6365e96a66cSDavid du Colombier 6375e96a66cSDavid du Colombier if(!fileLock(f)) 6385e96a66cSDavid du Colombier return 0; 6395e96a66cSDavid du Colombier 6405e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 6415e96a66cSDavid du Colombier vtSetError(EReadOnly); 6425e96a66cSDavid du Colombier fileUnlock(f); 6435e96a66cSDavid du Colombier return 0; 6445e96a66cSDavid du Colombier } 6455e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)){ 6465e96a66cSDavid du Colombier fileUnlock(f); 6475e96a66cSDavid du Colombier return 0; 6485e96a66cSDavid du Colombier } 6495e96a66cSDavid du Colombier if(!sourceTruncate(f->source)){ 6505e96a66cSDavid du Colombier sourceUnlock(f->source); 6515e96a66cSDavid du Colombier fileUnlock(f); 6525e96a66cSDavid du Colombier return 0; 6535e96a66cSDavid du Colombier } 6545e96a66cSDavid du Colombier sourceUnlock(f->source); 6555e96a66cSDavid du Colombier fileUnlock(f); 6565e96a66cSDavid du Colombier 6575e96a66cSDavid du Colombier fileWAccess(f->up, uid); 6585e96a66cSDavid du Colombier 6595e96a66cSDavid du Colombier return 1; 6605e96a66cSDavid du Colombier } 6615e96a66cSDavid du Colombier 6625e96a66cSDavid du Colombier int 6635e96a66cSDavid du Colombier fileSetDir(File *f, DirEntry *dir, char *uid) 6645e96a66cSDavid du Colombier { 6655e96a66cSDavid du Colombier File *ff; 6665e96a66cSDavid du Colombier char *oelem; 6675e96a66cSDavid du Colombier u32int mask; 6685e96a66cSDavid du Colombier u64int size; 6695e96a66cSDavid du Colombier 6705e96a66cSDavid du Colombier /* can not set permissions for the root */ 6715e96a66cSDavid du Colombier if(fileIsRoot(f)){ 6725e96a66cSDavid du Colombier vtSetError(ERoot); 6735e96a66cSDavid du Colombier return 0; 6745e96a66cSDavid du Colombier } 6755e96a66cSDavid du Colombier 6765e96a66cSDavid du Colombier if(!fileLock(f)) 6775e96a66cSDavid du Colombier return 0; 6785e96a66cSDavid du Colombier 6795e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 6805e96a66cSDavid du Colombier vtSetError(EReadOnly); 6815e96a66cSDavid du Colombier fileUnlock(f); 6825e96a66cSDavid du Colombier return 0; 6835e96a66cSDavid du Colombier } 6845e96a66cSDavid du Colombier 6855e96a66cSDavid du Colombier fileMetaLock(f); 6865e96a66cSDavid du Colombier 6875e96a66cSDavid du Colombier /* check new name does not already exist */ 6885e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 6895e96a66cSDavid du Colombier for(ff = f->up->down; ff; ff=ff->next){ 6905e96a66cSDavid du Colombier if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ 6915e96a66cSDavid du Colombier vtSetError(EExists); 6925e96a66cSDavid du Colombier goto Err; 6935e96a66cSDavid du Colombier } 6945e96a66cSDavid du Colombier } 6955e96a66cSDavid du Colombier 6965e96a66cSDavid du Colombier ff = dirLookup(f->up, dir->elem); 6975e96a66cSDavid du Colombier if(ff != nil){ 6985e96a66cSDavid du Colombier fileDecRef(ff); 6995e96a66cSDavid du Colombier vtSetError(EExists); 7005e96a66cSDavid du Colombier goto Err; 7015e96a66cSDavid du Colombier } 7025e96a66cSDavid du Colombier } 7035e96a66cSDavid du Colombier 7045e96a66cSDavid du Colombier if(!fileIsDir(f)){ 7055e96a66cSDavid du Colombier if(!sourceLock(f->source, -1)) 7065e96a66cSDavid du Colombier goto Err; 7075e96a66cSDavid du Colombier size = sourceGetSize(f->source); 7085e96a66cSDavid du Colombier if(size != dir->size){ 7095e96a66cSDavid du Colombier if(!sourceSetSize(f->source, dir->size)){ 7105e96a66cSDavid du Colombier sourceUnlock(f->source); 7115e96a66cSDavid du Colombier goto Err; 7125e96a66cSDavid du Colombier } 7135e96a66cSDavid du Colombier /* commited to changing it now */ 7145e96a66cSDavid du Colombier } 7155e96a66cSDavid du Colombier sourceUnlock(f->source); 7165e96a66cSDavid du Colombier } 7175e96a66cSDavid du Colombier 7185e96a66cSDavid du Colombier /* commited to changing it now */ 7195e96a66cSDavid du Colombier oelem = nil; 7205e96a66cSDavid du Colombier if(strcmp(f->dir.elem, dir->elem) != 0){ 7215e96a66cSDavid du Colombier oelem = f->dir.elem; 7225e96a66cSDavid du Colombier f->dir.elem = vtStrDup(dir->elem); 7235e96a66cSDavid du Colombier } 7245e96a66cSDavid du Colombier 7255e96a66cSDavid du Colombier if(strcmp(f->dir.uid, dir->uid) != 0){ 7265e96a66cSDavid du Colombier vtMemFree(f->dir.uid); 7275e96a66cSDavid du Colombier f->dir.uid = vtStrDup(dir->uid); 7285e96a66cSDavid du Colombier } 7295e96a66cSDavid du Colombier 7305e96a66cSDavid du Colombier if(strcmp(f->dir.gid, dir->gid) != 0){ 7315e96a66cSDavid du Colombier vtMemFree(f->dir.gid); 7325e96a66cSDavid du Colombier f->dir.gid = vtStrDup(dir->gid); 7335e96a66cSDavid du Colombier } 7345e96a66cSDavid du Colombier 7355e96a66cSDavid du Colombier f->dir.mtime = dir->mtime; 7365e96a66cSDavid du Colombier f->dir.atime = dir->atime; 7375e96a66cSDavid du Colombier 7385e96a66cSDavid du Colombier //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); 7395e96a66cSDavid du Colombier mask = ~(ModeDir|ModeSnapshot); 7405e96a66cSDavid du Colombier f->dir.mode &= ~mask; 7415e96a66cSDavid du Colombier f->dir.mode |= mask & dir->mode; 7425e96a66cSDavid du Colombier f->dirty = 1; 7435e96a66cSDavid du Colombier //fprint(2, "->%x\n", f->dir.mode); 7445e96a66cSDavid du Colombier 7455e96a66cSDavid du Colombier fileMetaFlush2(f, oelem); 7465e96a66cSDavid du Colombier vtMemFree(oelem); 7475e96a66cSDavid du Colombier 7485e96a66cSDavid du Colombier fileMetaUnlock(f); 7495e96a66cSDavid du Colombier fileUnlock(f); 7505e96a66cSDavid du Colombier 7515e96a66cSDavid du Colombier fileWAccess(f->up, uid); 7525e96a66cSDavid du Colombier 7535e96a66cSDavid du Colombier return 1; 7545e96a66cSDavid du Colombier Err: 7555e96a66cSDavid du Colombier fileMetaUnlock(f); 7565e96a66cSDavid du Colombier fileUnlock(f); 7575e96a66cSDavid du Colombier return 0; 7585e96a66cSDavid du Colombier } 7595e96a66cSDavid du Colombier 7605e96a66cSDavid du Colombier int 7615e96a66cSDavid du Colombier fileSetQidSpace(File *f, u64int offset, u64int max) 7625e96a66cSDavid du Colombier { 7635e96a66cSDavid du Colombier int ret; 7645e96a66cSDavid du Colombier 7655e96a66cSDavid du Colombier if(!fileLock(f)) 7665e96a66cSDavid du Colombier return 0; 7675e96a66cSDavid du Colombier fileMetaLock(f); 7685e96a66cSDavid du Colombier f->dir.qidSpace = 1; 7695e96a66cSDavid du Colombier f->dir.qidOffset = offset; 7705e96a66cSDavid du Colombier f->dir.qidMax = max; 7715e96a66cSDavid du Colombier ret = fileMetaFlush2(f, nil); 7725e96a66cSDavid du Colombier fileMetaUnlock(f); 7735e96a66cSDavid du Colombier fileUnlock(f); 7745e96a66cSDavid du Colombier return ret; 7755e96a66cSDavid du Colombier } 7765e96a66cSDavid du Colombier 7775e96a66cSDavid du Colombier 7785e96a66cSDavid du Colombier uvlong 7795e96a66cSDavid du Colombier fileGetId(File *f) 7805e96a66cSDavid du Colombier { 7815e96a66cSDavid du Colombier /* immutable */ 7825e96a66cSDavid du Colombier return f->dir.qid; 7835e96a66cSDavid du Colombier } 7845e96a66cSDavid du Colombier 7855e96a66cSDavid du Colombier ulong 7865e96a66cSDavid du Colombier fileGetMcount(File *f) 7875e96a66cSDavid du Colombier { 7885e96a66cSDavid du Colombier ulong mcount; 7895e96a66cSDavid du Colombier 7905e96a66cSDavid du Colombier fileMetaLock(f); 7915e96a66cSDavid du Colombier mcount = f->dir.mcount; 7925e96a66cSDavid du Colombier fileMetaUnlock(f); 7935e96a66cSDavid du Colombier return mcount; 7945e96a66cSDavid du Colombier } 7955e96a66cSDavid du Colombier 7965e96a66cSDavid du Colombier ulong 7975e96a66cSDavid du Colombier fileGetMode(File *f) 7985e96a66cSDavid du Colombier { 7995e96a66cSDavid du Colombier ulong mode; 8005e96a66cSDavid du Colombier 8015e96a66cSDavid du Colombier fileMetaLock(f); 8025e96a66cSDavid du Colombier mode = f->dir.mode; 8035e96a66cSDavid du Colombier fileMetaUnlock(f); 8045e96a66cSDavid du Colombier return mode; 8055e96a66cSDavid du Colombier } 8065e96a66cSDavid du Colombier 8075e96a66cSDavid du Colombier int 8085e96a66cSDavid du Colombier fileIsDir(File *f) 8095e96a66cSDavid du Colombier { 8105e96a66cSDavid du Colombier /* immutable */ 8115e96a66cSDavid du Colombier return (f->dir.mode & ModeDir) != 0; 8125e96a66cSDavid du Colombier } 8135e96a66cSDavid du Colombier 8145e96a66cSDavid du Colombier int 8155e96a66cSDavid du Colombier fileIsRoot(File *f) 8165e96a66cSDavid du Colombier { 8175e96a66cSDavid du Colombier return f == f->fs->file; 8185e96a66cSDavid du Colombier } 8195e96a66cSDavid du Colombier 8205e96a66cSDavid du Colombier int 8215e96a66cSDavid du Colombier fileIsRoFs(File *f) 8225e96a66cSDavid du Colombier { 8235e96a66cSDavid du Colombier return f->fs->mode == OReadOnly; 8245e96a66cSDavid du Colombier } 8255e96a66cSDavid du Colombier 8265e96a66cSDavid du Colombier int 8275e96a66cSDavid du Colombier fileGetSize(File *f, uvlong *size) 8285e96a66cSDavid du Colombier { 8295e96a66cSDavid du Colombier if(!fileRLock(f)) 8305e96a66cSDavid du Colombier return 0; 8315e96a66cSDavid du Colombier if(!sourceLock(f->source, OReadOnly)){ 8325e96a66cSDavid du Colombier fileRUnlock(f); 8335e96a66cSDavid du Colombier return 0; 8345e96a66cSDavid du Colombier } 8355e96a66cSDavid du Colombier *size = sourceGetSize(f->source); 8365e96a66cSDavid du Colombier sourceUnlock(f->source); 8375e96a66cSDavid du Colombier fileRUnlock(f); 8385e96a66cSDavid du Colombier 8395e96a66cSDavid du Colombier return 1; 8405e96a66cSDavid du Colombier } 8415e96a66cSDavid du Colombier 8425e96a66cSDavid du Colombier void 8435e96a66cSDavid du Colombier fileMetaFlush(File *f, int rec) 8445e96a66cSDavid du Colombier { 8455e96a66cSDavid du Colombier File **kids, *p; 8465e96a66cSDavid du Colombier int nkids; 8475e96a66cSDavid du Colombier int i; 8485e96a66cSDavid du Colombier 8495e96a66cSDavid du Colombier fileMetaLock(f); 8505e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 8515e96a66cSDavid du Colombier fileMetaUnlock(f); 8525e96a66cSDavid du Colombier 8535e96a66cSDavid du Colombier if(!rec || !fileIsDir(f)) 8545e96a66cSDavid du Colombier return; 8555e96a66cSDavid du Colombier 8565e96a66cSDavid du Colombier if(!fileLock(f)) 8575e96a66cSDavid du Colombier return; 8585e96a66cSDavid du Colombier nkids = 0; 8595e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 8605e96a66cSDavid du Colombier nkids++; 8615e96a66cSDavid du Colombier kids = vtMemAlloc(nkids*sizeof(File*)); 8625e96a66cSDavid du Colombier i = 0; 8635e96a66cSDavid du Colombier for(p=f->down; p; p=p->next){ 8645e96a66cSDavid du Colombier kids[i++] = p; 8655e96a66cSDavid du Colombier p->ref++; 8665e96a66cSDavid du Colombier } 8675e96a66cSDavid du Colombier fileUnlock(f); 8685e96a66cSDavid du Colombier 8695e96a66cSDavid du Colombier for(i=0; i<nkids; i++){ 8705e96a66cSDavid du Colombier fileMetaFlush(kids[i], 1); 8715e96a66cSDavid du Colombier fileDecRef(kids[i]); 8725e96a66cSDavid du Colombier } 8735e96a66cSDavid du Colombier vtMemFree(kids); 8745e96a66cSDavid du Colombier } 8755e96a66cSDavid du Colombier 8765e96a66cSDavid du Colombier /* assumes metaLock is held */ 8775e96a66cSDavid du Colombier static int 8785e96a66cSDavid du Colombier fileMetaFlush2(File *f, char *oelem) 8795e96a66cSDavid du Colombier { 8805e96a66cSDavid du Colombier File *fp; 8815e96a66cSDavid du Colombier Block *b, *bb; 8825e96a66cSDavid du Colombier MetaBlock mb; 8835e96a66cSDavid du Colombier MetaEntry me, me2; 8845e96a66cSDavid du Colombier int i, n; 8855e96a66cSDavid du Colombier u32int boff; 8865e96a66cSDavid du Colombier 8875e96a66cSDavid du Colombier if(!f->dirty) 8885e96a66cSDavid du Colombier return 1; 8895e96a66cSDavid du Colombier 8905e96a66cSDavid du Colombier if(oelem == nil) 8915e96a66cSDavid du Colombier oelem = f->dir.elem; 8925e96a66cSDavid du Colombier 8935e96a66cSDavid du Colombier //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem); 8945e96a66cSDavid du Colombier 8955e96a66cSDavid du Colombier fp = f->up; 8965e96a66cSDavid du Colombier 8975e96a66cSDavid du Colombier if(!sourceLock(fp->msource, -1)) 8985e96a66cSDavid du Colombier return 0; 8996042bf6dSDavid du Colombier /* can happen if source is clri'ed out from under us */ 9006042bf6dSDavid du Colombier if(f->boff == NilBlock) 9016042bf6dSDavid du Colombier goto Err1; 9025e96a66cSDavid du Colombier b = sourceBlock(fp->msource, f->boff, OReadWrite); 9035e96a66cSDavid du Colombier if(b == nil) 9045e96a66cSDavid du Colombier goto Err1; 9055e96a66cSDavid du Colombier 9065e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, fp->msource->dsize)) 9075e96a66cSDavid du Colombier goto Err; 9085e96a66cSDavid du Colombier if(!mbSearch(&mb, oelem, &i, &me)) 9095e96a66cSDavid du Colombier goto Err; 9105e96a66cSDavid du Colombier 9115e96a66cSDavid du Colombier n = deSize(&f->dir); 9125e96a66cSDavid du Colombier if(0)fprint(2, "old size %d new size %d\n", me.size, n); 9135e96a66cSDavid du Colombier 9145e96a66cSDavid du Colombier if(mbResize(&mb, &me, n)){ 9155e96a66cSDavid du Colombier /* fits in the block */ 9165e96a66cSDavid du Colombier mbDelete(&mb, i); 9175e96a66cSDavid du Colombier if(strcmp(f->dir.elem, oelem) != 0) 9185e96a66cSDavid du Colombier mbSearch(&mb, f->dir.elem, &i, &me2); 9195e96a66cSDavid du Colombier dePack(&f->dir, &me); 9205e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 9215e96a66cSDavid du Colombier mbPack(&mb); 9225e96a66cSDavid du Colombier blockDirty(b); 9235e96a66cSDavid du Colombier blockPut(b); 9245e96a66cSDavid du Colombier sourceUnlock(fp->msource); 9255e96a66cSDavid du Colombier f->dirty = 0; 9265e96a66cSDavid du Colombier 9275e96a66cSDavid du Colombier return 1; 9285e96a66cSDavid du Colombier } 9295e96a66cSDavid du Colombier 9305e96a66cSDavid du Colombier /* 9315e96a66cSDavid du Colombier * moving entry to another block 9325e96a66cSDavid du Colombier * it is feasible for the fs to crash leaving two copies 9335e96a66cSDavid du Colombier * of the directory entry. This is just too much work to 9345e96a66cSDavid du Colombier * fix. Given that entries are only allocated in a block that 9355e96a66cSDavid du Colombier * is less than PercentageFull, most modifications of meta data 9365e96a66cSDavid du Colombier * will fit within the block. i.e. this code should almost 9375e96a66cSDavid du Colombier * never be executed. 9385e96a66cSDavid du Colombier */ 9395e96a66cSDavid du Colombier boff = fileMetaAlloc(fp, &f->dir, f->boff+1); 9405e96a66cSDavid du Colombier if(boff == NilBlock){ 9415e96a66cSDavid du Colombier /* mbResize might have modified block */ 9425e96a66cSDavid du Colombier mbPack(&mb); 9435e96a66cSDavid du Colombier blockDirty(b); 9445e96a66cSDavid du Colombier goto Err; 9455e96a66cSDavid du Colombier } 9465e96a66cSDavid du Colombier fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff); 9475e96a66cSDavid du Colombier f->boff = boff; 9485e96a66cSDavid du Colombier 9495e96a66cSDavid du Colombier /* make sure deletion goes to disk after new entry */ 9505e96a66cSDavid du Colombier bb = sourceBlock(fp->msource, f->boff, OReadWrite); 9515e96a66cSDavid du Colombier mbDelete(&mb, i); 9525e96a66cSDavid du Colombier mbPack(&mb); 95361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 9545e96a66cSDavid du Colombier blockPut(bb); 9555e96a66cSDavid du Colombier blockDirty(b); 9565e96a66cSDavid du Colombier blockPut(b); 9575e96a66cSDavid du Colombier sourceUnlock(fp->msource); 9585e96a66cSDavid du Colombier 9595e96a66cSDavid du Colombier f->dirty = 0; 9605e96a66cSDavid du Colombier 9615e96a66cSDavid du Colombier return 1; 9625e96a66cSDavid du Colombier 9635e96a66cSDavid du Colombier Err: 9645e96a66cSDavid du Colombier blockPut(b); 9655e96a66cSDavid du Colombier Err1: 9665e96a66cSDavid du Colombier sourceUnlock(fp->msource); 9675e96a66cSDavid du Colombier return 0; 9685e96a66cSDavid du Colombier } 9695e96a66cSDavid du Colombier 9705e96a66cSDavid du Colombier static int 9715e96a66cSDavid du Colombier fileMetaRemove(File *f, char *uid) 9725e96a66cSDavid du Colombier { 9735e96a66cSDavid du Colombier Block *b; 9745e96a66cSDavid du Colombier MetaBlock mb; 9755e96a66cSDavid du Colombier MetaEntry me; 9765e96a66cSDavid du Colombier int i; 9775e96a66cSDavid du Colombier File *up; 9785e96a66cSDavid du Colombier 9795e96a66cSDavid du Colombier up = f->up; 9805e96a66cSDavid du Colombier 9815e96a66cSDavid du Colombier fileWAccess(up, uid); 9825e96a66cSDavid du Colombier 9835e96a66cSDavid du Colombier fileMetaLock(f); 9845e96a66cSDavid du Colombier 9855e96a66cSDavid du Colombier sourceLock(up->msource, OReadWrite); 9865e96a66cSDavid du Colombier b = sourceBlock(up->msource, f->boff, OReadWrite); 9875e96a66cSDavid du Colombier if(b == nil) 9885e96a66cSDavid du Colombier goto Err; 9895e96a66cSDavid du Colombier 9905e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, up->msource->dsize)) 9915e96a66cSDavid du Colombier { 9925e96a66cSDavid du Colombier fprint(2, "U\n"); 9935e96a66cSDavid du Colombier goto Err; 9945e96a66cSDavid du Colombier } 9955e96a66cSDavid du Colombier if(!mbSearch(&mb, f->dir.elem, &i, &me)) 9965e96a66cSDavid du Colombier { 9975e96a66cSDavid du Colombier fprint(2, "S\n"); 9985e96a66cSDavid du Colombier goto Err; 9995e96a66cSDavid du Colombier } 10005e96a66cSDavid du Colombier mbDelete(&mb, i); 10015e96a66cSDavid du Colombier mbPack(&mb); 10025e96a66cSDavid du Colombier sourceUnlock(up->msource); 10035e96a66cSDavid du Colombier 10045e96a66cSDavid du Colombier blockDirty(b); 10055e96a66cSDavid du Colombier blockPut(b); 10065e96a66cSDavid du Colombier 10075e96a66cSDavid du Colombier f->removed = 1; 10085e96a66cSDavid du Colombier f->boff = NilBlock; 10095e96a66cSDavid du Colombier f->dirty = 0; 10105e96a66cSDavid du Colombier 10115e96a66cSDavid du Colombier fileMetaUnlock(f); 10125e96a66cSDavid du Colombier return 1; 10135e96a66cSDavid du Colombier 10145e96a66cSDavid du Colombier Err: 10155e96a66cSDavid du Colombier sourceUnlock(up->msource); 10165e96a66cSDavid du Colombier blockPut(b); 10175e96a66cSDavid du Colombier fileMetaUnlock(f); 10185e96a66cSDavid du Colombier return 0; 10195e96a66cSDavid du Colombier } 10205e96a66cSDavid du Colombier 10215e96a66cSDavid du Colombier /* assume file is locked, assume f->msource is locked */ 10225e96a66cSDavid du Colombier static int 10235e96a66cSDavid du Colombier fileCheckEmpty(File *f) 10245e96a66cSDavid du Colombier { 10255e96a66cSDavid du Colombier u32int i, n; 10265e96a66cSDavid du Colombier Block *b; 10275e96a66cSDavid du Colombier MetaBlock mb; 10285e96a66cSDavid du Colombier Source *r; 10295e96a66cSDavid du Colombier 10305e96a66cSDavid du Colombier r = f->msource; 10315e96a66cSDavid du Colombier n = (sourceGetSize(r)+r->dsize-1)/r->dsize; 10325e96a66cSDavid du Colombier for(i=0; i<n; i++){ 10335e96a66cSDavid du Colombier b = sourceBlock(r, i, OReadOnly); 10345e96a66cSDavid du Colombier if(b == nil) 10355e96a66cSDavid du Colombier goto Err; 10365e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, r->dsize)) 10375e96a66cSDavid du Colombier goto Err; 10385e96a66cSDavid du Colombier if(mb.nindex > 0){ 10395e96a66cSDavid du Colombier vtSetError(ENotEmpty); 10405e96a66cSDavid du Colombier goto Err; 10415e96a66cSDavid du Colombier } 10425e96a66cSDavid du Colombier blockPut(b); 10435e96a66cSDavid du Colombier } 10445e96a66cSDavid du Colombier return 1; 10455e96a66cSDavid du Colombier Err: 10465e96a66cSDavid du Colombier blockPut(b); 10475e96a66cSDavid du Colombier return 0; 10485e96a66cSDavid du Colombier } 10495e96a66cSDavid du Colombier 10505e96a66cSDavid du Colombier int 10515e96a66cSDavid du Colombier fileRemove(File *f, char *uid) 10525e96a66cSDavid du Colombier { 10535e96a66cSDavid du Colombier File *ff; 10545e96a66cSDavid du Colombier 10555e96a66cSDavid du Colombier /* can not remove the root */ 10565e96a66cSDavid du Colombier if(fileIsRoot(f)){ 10575e96a66cSDavid du Colombier vtSetError(ERoot); 10585e96a66cSDavid du Colombier return 0; 10595e96a66cSDavid du Colombier } 10605e96a66cSDavid du Colombier 10615e96a66cSDavid du Colombier if(!fileLock(f)) 10625e96a66cSDavid du Colombier return 0; 10635e96a66cSDavid du Colombier 10645e96a66cSDavid du Colombier if(f->source->mode != OReadWrite){ 10655e96a66cSDavid du Colombier vtSetError(EReadOnly); 10665e96a66cSDavid du Colombier goto Err1; 10675e96a66cSDavid du Colombier } 10685e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, -1)) 10695e96a66cSDavid du Colombier goto Err1; 10705e96a66cSDavid du Colombier if(fileIsDir(f) && !fileCheckEmpty(f)) 10715e96a66cSDavid du Colombier goto Err; 10725e96a66cSDavid du Colombier 10735e96a66cSDavid du Colombier for(ff=f->down; ff; ff=ff->next) 10745e96a66cSDavid du Colombier assert(ff->removed); 10755e96a66cSDavid du Colombier 10765e96a66cSDavid du Colombier sourceRemove(f->source); 10775e96a66cSDavid du Colombier f->source = nil; 10785e96a66cSDavid du Colombier if(f->msource){ 10795e96a66cSDavid du Colombier sourceRemove(f->msource); 10805e96a66cSDavid du Colombier f->msource = nil; 10815e96a66cSDavid du Colombier } 10825e96a66cSDavid du Colombier 10835e96a66cSDavid du Colombier fileUnlock(f); 10845e96a66cSDavid du Colombier 10855e96a66cSDavid du Colombier if(!fileMetaRemove(f, uid)) 10865e96a66cSDavid du Colombier return 0; 10875e96a66cSDavid du Colombier 10885e96a66cSDavid du Colombier return 1; 10895e96a66cSDavid du Colombier 10905e96a66cSDavid du Colombier Err: 10915e96a66cSDavid du Colombier sourceUnlock(f->source); 10925e96a66cSDavid du Colombier if(f->msource) 10935e96a66cSDavid du Colombier sourceUnlock(f->msource); 10945e96a66cSDavid du Colombier Err1: 10955e96a66cSDavid du Colombier fileUnlock(f); 10965e96a66cSDavid du Colombier return 0; 10975e96a66cSDavid du Colombier } 10985e96a66cSDavid du Colombier 1099dc5a79c1SDavid du Colombier static int 1100dc5a79c1SDavid du Colombier clri(File *f, char *uid) 11015e96a66cSDavid du Colombier { 11025e96a66cSDavid du Colombier int r; 11035e96a66cSDavid du Colombier 11045e96a66cSDavid du Colombier if(f == nil) 11055e96a66cSDavid du Colombier return 0; 11065e96a66cSDavid du Colombier if(f->up->source->mode != OReadWrite){ 11075e96a66cSDavid du Colombier vtSetError(EReadOnly); 11085e96a66cSDavid du Colombier fileDecRef(f); 11095e96a66cSDavid du Colombier return 0; 11105e96a66cSDavid du Colombier } 11115e96a66cSDavid du Colombier r = fileMetaRemove(f, uid); 11125e96a66cSDavid du Colombier fileDecRef(f); 11135e96a66cSDavid du Colombier return r; 11145e96a66cSDavid du Colombier } 11155e96a66cSDavid du Colombier 1116dc5a79c1SDavid du Colombier int 1117dc5a79c1SDavid du Colombier fileClriPath(Fs *fs, char *path, char *uid) 1118dc5a79c1SDavid du Colombier { 1119dc5a79c1SDavid du Colombier return clri(_fileOpen(fs, path, 1), uid); 1120dc5a79c1SDavid du Colombier } 1121dc5a79c1SDavid du Colombier 1122dc5a79c1SDavid du Colombier int 1123dc5a79c1SDavid du Colombier fileClri(File *dir, char *elem, char *uid) 1124dc5a79c1SDavid du Colombier { 1125dc5a79c1SDavid du Colombier return clri(_fileWalk(dir, elem, 1), uid); 1126dc5a79c1SDavid du Colombier } 1127dc5a79c1SDavid du Colombier 11285e96a66cSDavid du Colombier File * 11295e96a66cSDavid du Colombier fileIncRef(File *vf) 11305e96a66cSDavid du Colombier { 11315e96a66cSDavid du Colombier fileMetaLock(vf); 11325e96a66cSDavid du Colombier assert(vf->ref > 0); 11335e96a66cSDavid du Colombier vf->ref++; 11345e96a66cSDavid du Colombier fileMetaUnlock(vf); 11355e96a66cSDavid du Colombier return vf; 11365e96a66cSDavid du Colombier } 11375e96a66cSDavid du Colombier 11385e96a66cSDavid du Colombier int 11395e96a66cSDavid du Colombier fileDecRef(File *f) 11405e96a66cSDavid du Colombier { 11415e96a66cSDavid du Colombier File *p, *q, **qq; 11425e96a66cSDavid du Colombier 11435e96a66cSDavid du Colombier if(f->up == nil){ 11445e96a66cSDavid du Colombier /* never linked in */ 11455e96a66cSDavid du Colombier assert(f->ref == 1); 11465e96a66cSDavid du Colombier fileFree(f); 11475e96a66cSDavid du Colombier return 1; 11485e96a66cSDavid du Colombier } 11495e96a66cSDavid du Colombier 11505e96a66cSDavid du Colombier fileMetaLock(f); 11515e96a66cSDavid du Colombier f->ref--; 11525e96a66cSDavid du Colombier if(f->ref > 0){ 11535e96a66cSDavid du Colombier fileMetaUnlock(f); 11545e96a66cSDavid du Colombier return 0; 11555e96a66cSDavid du Colombier } 11565e96a66cSDavid du Colombier assert(f->ref == 0); 11575e96a66cSDavid du Colombier assert(f->down == nil); 11585e96a66cSDavid du Colombier 11595e96a66cSDavid du Colombier fileMetaFlush2(f, nil); 11605e96a66cSDavid du Colombier 11615e96a66cSDavid du Colombier p = f->up; 11625e96a66cSDavid du Colombier qq = &p->down; 11635e96a66cSDavid du Colombier for(q = *qq; q; q = *qq){ 11645e96a66cSDavid du Colombier if(q == f) 11655e96a66cSDavid du Colombier break; 11665e96a66cSDavid du Colombier qq = &q->next; 11675e96a66cSDavid du Colombier } 11685e96a66cSDavid du Colombier assert(q != nil); 11695e96a66cSDavid du Colombier *qq = f->next; 11705e96a66cSDavid du Colombier 11715e96a66cSDavid du Colombier fileMetaUnlock(f); 11725e96a66cSDavid du Colombier fileFree(f); 11735e96a66cSDavid du Colombier 11745e96a66cSDavid du Colombier fileDecRef(p); 11755e96a66cSDavid du Colombier return 1; 11765e96a66cSDavid du Colombier } 11775e96a66cSDavid du Colombier 11785e96a66cSDavid du Colombier File * 11795e96a66cSDavid du Colombier fileGetParent(File *f) 11805e96a66cSDavid du Colombier { 11815e96a66cSDavid du Colombier if(fileIsRoot(f)) 11825e96a66cSDavid du Colombier return fileIncRef(f); 11835e96a66cSDavid du Colombier return fileIncRef(f->up); 11845e96a66cSDavid du Colombier } 11855e96a66cSDavid du Colombier 11865e96a66cSDavid du Colombier DirEntryEnum * 11875e96a66cSDavid du Colombier deeOpen(File *f) 11885e96a66cSDavid du Colombier { 11895e96a66cSDavid du Colombier DirEntryEnum *dee; 11905e96a66cSDavid du Colombier File *p; 11915e96a66cSDavid du Colombier 11925e96a66cSDavid du Colombier if(!fileIsDir(f)){ 11935e96a66cSDavid du Colombier vtSetError(ENotDir); 11945e96a66cSDavid du Colombier fileDecRef(f); 11955e96a66cSDavid du Colombier return nil; 11965e96a66cSDavid du Colombier } 11975e96a66cSDavid du Colombier 11985e96a66cSDavid du Colombier /* flush out meta data */ 11995e96a66cSDavid du Colombier if(!fileLock(f)) 12005e96a66cSDavid du Colombier return nil; 12015e96a66cSDavid du Colombier for(p=f->down; p; p=p->next) 12025e96a66cSDavid du Colombier fileMetaFlush2(p, nil); 12035e96a66cSDavid du Colombier fileUnlock(f); 12045e96a66cSDavid du Colombier 12055e96a66cSDavid du Colombier dee = vtMemAllocZ(sizeof(DirEntryEnum)); 12065e96a66cSDavid du Colombier dee->file = fileIncRef(f); 12075e96a66cSDavid du Colombier 12085e96a66cSDavid du Colombier return dee; 12095e96a66cSDavid du Colombier } 12105e96a66cSDavid du Colombier 12115e96a66cSDavid du Colombier static int 12125e96a66cSDavid du Colombier dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size) 12135e96a66cSDavid du Colombier { 12145e96a66cSDavid du Colombier Block *b; 12155e96a66cSDavid du Colombier ulong bn; 12165e96a66cSDavid du Colombier Entry e; 12175e96a66cSDavid du Colombier int epb; 12185e96a66cSDavid du Colombier 12195e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 12205e96a66cSDavid du Colombier bn = elem/epb; 12215e96a66cSDavid du Colombier elem -= bn*epb; 12225e96a66cSDavid du Colombier 12235e96a66cSDavid du Colombier b = sourceBlock(s, bn, OReadOnly); 12245e96a66cSDavid du Colombier if(b == nil) 12255e96a66cSDavid du Colombier goto Err; 12265e96a66cSDavid du Colombier if(!entryUnpack(&e, b->data, elem)) 12275e96a66cSDavid du Colombier goto Err; 12285e96a66cSDavid du Colombier 12295e96a66cSDavid du Colombier /* hanging entries are returned as zero size */ 12305e96a66cSDavid du Colombier if(!(e.flags & VtEntryActive) || e.gen != gen) 12315e96a66cSDavid du Colombier *size = 0; 12325e96a66cSDavid du Colombier else 12335e96a66cSDavid du Colombier *size = e.size; 12345e96a66cSDavid du Colombier blockPut(b); 12355e96a66cSDavid du Colombier return 1; 12365e96a66cSDavid du Colombier 12375e96a66cSDavid du Colombier Err: 12385e96a66cSDavid du Colombier blockPut(b); 12395e96a66cSDavid du Colombier return 0; 12405e96a66cSDavid du Colombier } 12415e96a66cSDavid du Colombier 12425e96a66cSDavid du Colombier static int 12435e96a66cSDavid du Colombier deeFill(DirEntryEnum *dee) 12445e96a66cSDavid du Colombier { 12455e96a66cSDavid du Colombier int i, n; 12465e96a66cSDavid du Colombier Source *meta, *source; 12475e96a66cSDavid du Colombier MetaBlock mb; 12485e96a66cSDavid du Colombier MetaEntry me; 12495e96a66cSDavid du Colombier File *f; 12505e96a66cSDavid du Colombier Block *b; 12515e96a66cSDavid du Colombier DirEntry *de; 12525e96a66cSDavid du Colombier 12535e96a66cSDavid du Colombier /* clean up first */ 12545e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 12555e96a66cSDavid du Colombier deCleanup(dee->buf+i); 12565e96a66cSDavid du Colombier vtMemFree(dee->buf); 12575e96a66cSDavid du Colombier dee->buf = nil; 12585e96a66cSDavid du Colombier dee->i = 0; 12595e96a66cSDavid du Colombier dee->n = 0; 12605e96a66cSDavid du Colombier 12615e96a66cSDavid du Colombier f = dee->file; 12625e96a66cSDavid du Colombier 12635e96a66cSDavid du Colombier source = f->source; 12645e96a66cSDavid du Colombier meta = f->msource; 12655e96a66cSDavid du Colombier 12665e96a66cSDavid du Colombier b = sourceBlock(meta, dee->boff, OReadOnly); 12675e96a66cSDavid du Colombier if(b == nil) 12685e96a66cSDavid du Colombier goto Err; 12695e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, meta->dsize)) 12705e96a66cSDavid du Colombier goto Err; 12715e96a66cSDavid du Colombier 12725e96a66cSDavid du Colombier n = mb.nindex; 12735e96a66cSDavid du Colombier dee->buf = vtMemAlloc(n * sizeof(DirEntry)); 12745e96a66cSDavid du Colombier 12755e96a66cSDavid du Colombier for(i=0; i<n; i++){ 12765e96a66cSDavid du Colombier de = dee->buf + i; 12775e96a66cSDavid du Colombier meUnpack(&me, &mb, i); 12785e96a66cSDavid du Colombier if(!deUnpack(de, &me)) 12795e96a66cSDavid du Colombier goto Err; 12805e96a66cSDavid du Colombier dee->n++; 12815e96a66cSDavid du Colombier if(!(de->mode & ModeDir)) 12825e96a66cSDavid du Colombier if(!dirEntrySize(source, de->entry, de->gen, &de->size)) 12835e96a66cSDavid du Colombier goto Err; 12845e96a66cSDavid du Colombier } 12855e96a66cSDavid du Colombier dee->boff++; 12865e96a66cSDavid du Colombier blockPut(b); 12875e96a66cSDavid du Colombier return 1; 12885e96a66cSDavid du Colombier Err: 12895e96a66cSDavid du Colombier blockPut(b); 12905e96a66cSDavid du Colombier return 0; 12915e96a66cSDavid du Colombier } 12925e96a66cSDavid du Colombier 12935e96a66cSDavid du Colombier int 12945e96a66cSDavid du Colombier deeRead(DirEntryEnum *dee, DirEntry *de) 12955e96a66cSDavid du Colombier { 12965e96a66cSDavid du Colombier int ret, didread; 12975e96a66cSDavid du Colombier File *f; 12985e96a66cSDavid du Colombier u32int nb; 12995e96a66cSDavid du Colombier 13005e96a66cSDavid du Colombier f = dee->file; 13015e96a66cSDavid du Colombier if(!fileRLock(f)) 13025e96a66cSDavid du Colombier return -1; 13035e96a66cSDavid du Colombier 13045e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadOnly)){ 13055e96a66cSDavid du Colombier fileRUnlock(f); 13065e96a66cSDavid du Colombier return -1; 13075e96a66cSDavid du Colombier } 13085e96a66cSDavid du Colombier 13095e96a66cSDavid du Colombier nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize; 13105e96a66cSDavid du Colombier 13115e96a66cSDavid du Colombier didread = 0; 13125e96a66cSDavid du Colombier while(dee->i >= dee->n){ 13135e96a66cSDavid du Colombier if(dee->boff >= nb){ 13145e96a66cSDavid du Colombier ret = 0; 13155e96a66cSDavid du Colombier goto Return; 13165e96a66cSDavid du Colombier } 13175e96a66cSDavid du Colombier didread = 1; 13185e96a66cSDavid du Colombier if(!deeFill(dee)){ 13195e96a66cSDavid du Colombier ret = -1; 13205e96a66cSDavid du Colombier goto Return; 13215e96a66cSDavid du Colombier } 13225e96a66cSDavid du Colombier } 13235e96a66cSDavid du Colombier 13245e96a66cSDavid du Colombier memmove(de, dee->buf + dee->i, sizeof(DirEntry)); 13255e96a66cSDavid du Colombier dee->i++; 13265e96a66cSDavid du Colombier ret = 1; 13275e96a66cSDavid du Colombier 13285e96a66cSDavid du Colombier Return: 13295e96a66cSDavid du Colombier sourceUnlock(f->source); 13305e96a66cSDavid du Colombier sourceUnlock(f->msource); 13315e96a66cSDavid du Colombier fileRUnlock(f); 13325e96a66cSDavid du Colombier 13335e96a66cSDavid du Colombier if(didread) 13345e96a66cSDavid du Colombier fileRAccess(f); 13355e96a66cSDavid du Colombier return ret; 13365e96a66cSDavid du Colombier } 13375e96a66cSDavid du Colombier 13385e96a66cSDavid du Colombier void 13395e96a66cSDavid du Colombier deeClose(DirEntryEnum *dee) 13405e96a66cSDavid du Colombier { 13415e96a66cSDavid du Colombier int i; 13425e96a66cSDavid du Colombier if(dee == nil) 13435e96a66cSDavid du Colombier return; 13445e96a66cSDavid du Colombier for(i=dee->i; i<dee->n; i++) 13455e96a66cSDavid du Colombier deCleanup(dee->buf+i); 13465e96a66cSDavid du Colombier vtMemFree(dee->buf); 13475e96a66cSDavid du Colombier fileDecRef(dee->file); 13485e96a66cSDavid du Colombier vtMemFree(dee); 13495e96a66cSDavid du Colombier } 13505e96a66cSDavid du Colombier 13515e96a66cSDavid du Colombier /* 13525e96a66cSDavid du Colombier * caller must lock f->source and f->msource 13535e96a66cSDavid du Colombier * caller must NOT lock the source and msource 13545e96a66cSDavid du Colombier * referenced by dir. 13555e96a66cSDavid du Colombier */ 13565e96a66cSDavid du Colombier static u32int 13575e96a66cSDavid du Colombier fileMetaAlloc(File *f, DirEntry *dir, u32int start) 13585e96a66cSDavid du Colombier { 13595e96a66cSDavid du Colombier u32int nb, bo; 13605e96a66cSDavid du Colombier Block *b, *bb; 13615e96a66cSDavid du Colombier MetaBlock mb; 13625e96a66cSDavid du Colombier int nn; 13635e96a66cSDavid du Colombier uchar *p; 13645e96a66cSDavid du Colombier int i, n, epb; 13655e96a66cSDavid du Colombier MetaEntry me; 13665e96a66cSDavid du Colombier Source *s, *ms; 13675e96a66cSDavid du Colombier 13685e96a66cSDavid du Colombier s = f->source; 13695e96a66cSDavid du Colombier ms = f->msource; 13705e96a66cSDavid du Colombier 13715e96a66cSDavid du Colombier n = deSize(dir); 13725e96a66cSDavid du Colombier nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize; 13735e96a66cSDavid du Colombier b = nil; 13745e96a66cSDavid du Colombier if(start > nb) 13755e96a66cSDavid du Colombier start = nb; 13765e96a66cSDavid du Colombier for(bo=start; bo<nb; bo++){ 13775e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 13785e96a66cSDavid du Colombier if(b == nil) 13795e96a66cSDavid du Colombier goto Err; 13805e96a66cSDavid du Colombier if(!mbUnpack(&mb, b->data, ms->dsize)) 13815e96a66cSDavid du Colombier goto Err; 13825e96a66cSDavid du Colombier nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free; 13835e96a66cSDavid du Colombier if(n <= nn && mb.nindex < mb.maxindex) 13845e96a66cSDavid du Colombier break; 13855e96a66cSDavid du Colombier blockPut(b); 13865e96a66cSDavid du Colombier b = nil; 13875e96a66cSDavid du Colombier } 13885e96a66cSDavid du Colombier 13895e96a66cSDavid du Colombier /* add block to meta file */ 13905e96a66cSDavid du Colombier if(b == nil){ 13915e96a66cSDavid du Colombier b = sourceBlock(ms, bo, OReadWrite); 13925e96a66cSDavid du Colombier if(b == nil) 13935e96a66cSDavid du Colombier goto Err; 13945e96a66cSDavid du Colombier sourceSetSize(ms, (nb+1)*ms->dsize); 13955e96a66cSDavid du Colombier mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry); 13965e96a66cSDavid du Colombier } 13975e96a66cSDavid du Colombier 13985e96a66cSDavid du Colombier p = mbAlloc(&mb, n); 13995e96a66cSDavid du Colombier if(p == nil){ 14005e96a66cSDavid du Colombier /* mbAlloc might have changed block */ 14015e96a66cSDavid du Colombier mbPack(&mb); 14025e96a66cSDavid du Colombier blockDirty(b); 14035e96a66cSDavid du Colombier vtSetError(EBadMeta); 14045e96a66cSDavid du Colombier goto Err; 14055e96a66cSDavid du Colombier } 14065e96a66cSDavid du Colombier 14075e96a66cSDavid du Colombier mbSearch(&mb, dir->elem, &i, &me); 14085e96a66cSDavid du Colombier assert(me.p == nil); 14095e96a66cSDavid du Colombier me.p = p; 14105e96a66cSDavid du Colombier me.size = n; 14115e96a66cSDavid du Colombier dePack(dir, &me); 14125e96a66cSDavid du Colombier mbInsert(&mb, i, &me); 14135e96a66cSDavid du Colombier mbPack(&mb); 14145e96a66cSDavid du Colombier 14155e96a66cSDavid du Colombier /* meta block depends on super block for qid ... */ 14165e96a66cSDavid du Colombier bb = cacheLocal(b->c, PartSuper, 0, OReadOnly); 141761201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 14185e96a66cSDavid du Colombier blockPut(bb); 14195e96a66cSDavid du Colombier 14205e96a66cSDavid du Colombier /* ... and one or two dir entries */ 14215e96a66cSDavid du Colombier epb = s->dsize/VtEntrySize; 14225e96a66cSDavid du Colombier bb = sourceBlock(s, dir->entry/epb, OReadOnly); 142361201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 14245e96a66cSDavid du Colombier blockPut(bb); 14255e96a66cSDavid du Colombier if(dir->mode & ModeDir){ 14265e96a66cSDavid du Colombier bb = sourceBlock(s, dir->mentry/epb, OReadOnly); 142761201b97SDavid du Colombier blockDependency(b, bb, -1, nil, nil); 14285e96a66cSDavid du Colombier blockPut(bb); 14295e96a66cSDavid du Colombier } 14305e96a66cSDavid du Colombier 14315e96a66cSDavid du Colombier blockDirty(b); 14325e96a66cSDavid du Colombier blockPut(b); 14335e96a66cSDavid du Colombier return bo; 14345e96a66cSDavid du Colombier Err: 14355e96a66cSDavid du Colombier blockPut(b); 14365e96a66cSDavid du Colombier return NilBlock; 14375e96a66cSDavid du Colombier } 14385e96a66cSDavid du Colombier 14395e96a66cSDavid du Colombier static int 14405e96a66cSDavid du Colombier chkSource(File *f) 14415e96a66cSDavid du Colombier { 14425e96a66cSDavid du Colombier if(f->partial) 14435e96a66cSDavid du Colombier return 1; 14445e96a66cSDavid du Colombier 14455e96a66cSDavid du Colombier if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){ 14465e96a66cSDavid du Colombier vtSetError(ERemoved); 14475e96a66cSDavid du Colombier return 0; 14485e96a66cSDavid du Colombier } 14495e96a66cSDavid du Colombier return 1; 14505e96a66cSDavid du Colombier } 14515e96a66cSDavid du Colombier 14525e96a66cSDavid du Colombier static int 14535e96a66cSDavid du Colombier fileRLock(File *f) 14545e96a66cSDavid du Colombier { 14555e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 14565e96a66cSDavid du Colombier vtRLock(f->lk); 14575e96a66cSDavid du Colombier if(!chkSource(f)){ 14585e96a66cSDavid du Colombier fileRUnlock(f); 14595e96a66cSDavid du Colombier return 0; 14605e96a66cSDavid du Colombier } 14615e96a66cSDavid du Colombier return 1; 14625e96a66cSDavid du Colombier } 14635e96a66cSDavid du Colombier 14645e96a66cSDavid du Colombier static void 14655e96a66cSDavid du Colombier fileRUnlock(File *f) 14665e96a66cSDavid du Colombier { 14675e96a66cSDavid du Colombier vtRUnlock(f->lk); 14685e96a66cSDavid du Colombier } 14695e96a66cSDavid du Colombier 14705e96a66cSDavid du Colombier static int 14715e96a66cSDavid du Colombier fileLock(File *f) 14725e96a66cSDavid du Colombier { 14735e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 14745e96a66cSDavid du Colombier vtLock(f->lk); 14755e96a66cSDavid du Colombier if(!chkSource(f)){ 14765e96a66cSDavid du Colombier fileUnlock(f); 14775e96a66cSDavid du Colombier return 0; 14785e96a66cSDavid du Colombier } 14795e96a66cSDavid du Colombier return 1; 14805e96a66cSDavid du Colombier } 14815e96a66cSDavid du Colombier 14825e96a66cSDavid du Colombier static void 14835e96a66cSDavid du Colombier fileUnlock(File *f) 14845e96a66cSDavid du Colombier { 14855e96a66cSDavid du Colombier vtUnlock(f->lk); 14865e96a66cSDavid du Colombier } 14875e96a66cSDavid du Colombier 14885e96a66cSDavid du Colombier /* 14895e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 14905e96a66cSDavid du Colombier * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2). 14915e96a66cSDavid du Colombier * We have to respect that ordering. 14925e96a66cSDavid du Colombier */ 14935e96a66cSDavid du Colombier static void 14945e96a66cSDavid du Colombier fileMetaLock(File *f) 14955e96a66cSDavid du Colombier { 14965e96a66cSDavid du Colombier if(f->up == nil) 14975e96a66cSDavid du Colombier fprint(2, "f->elem = %s\n", f->dir.elem); 14985e96a66cSDavid du Colombier assert(f->up != nil); 14995e96a66cSDavid du Colombier assert(!vtCanLock(f->fs->elk)); 15005e96a66cSDavid du Colombier vtLock(f->up->lk); 15015e96a66cSDavid du Colombier } 15025e96a66cSDavid du Colombier 15035e96a66cSDavid du Colombier static void 15045e96a66cSDavid du Colombier fileMetaUnlock(File *f) 15055e96a66cSDavid du Colombier { 15065e96a66cSDavid du Colombier vtUnlock(f->up->lk); 15075e96a66cSDavid du Colombier } 15085e96a66cSDavid du Colombier 15095e96a66cSDavid du Colombier /* 15105e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 15115e96a66cSDavid du Colombier * see fileMetaLock. 15125e96a66cSDavid du Colombier */ 15135e96a66cSDavid du Colombier static void 15145e96a66cSDavid du Colombier fileRAccess(File* f) 15155e96a66cSDavid du Colombier { 15165e96a66cSDavid du Colombier if(f->mode == OReadOnly) 15175e96a66cSDavid du Colombier return; 15185e96a66cSDavid du Colombier 15195e96a66cSDavid du Colombier fileMetaLock(f); 15205e96a66cSDavid du Colombier f->dir.atime = time(0L); 15215e96a66cSDavid du Colombier f->dirty = 1; 15225e96a66cSDavid du Colombier fileMetaUnlock(f); 15235e96a66cSDavid du Colombier } 15245e96a66cSDavid du Colombier 15255e96a66cSDavid du Colombier /* 15265e96a66cSDavid du Colombier * f->source and f->msource must NOT be locked. 15275e96a66cSDavid du Colombier * see fileMetaLock. 15285e96a66cSDavid du Colombier */ 15295e96a66cSDavid du Colombier static void 15305e96a66cSDavid du Colombier fileWAccess(File* f, char *mid) 15315e96a66cSDavid du Colombier { 15325e96a66cSDavid du Colombier if(f->mode == OReadOnly) 15335e96a66cSDavid du Colombier return; 15345e96a66cSDavid du Colombier 15355e96a66cSDavid du Colombier fileMetaLock(f); 15365e96a66cSDavid du Colombier f->dir.atime = f->dir.mtime = time(0L); 15375e96a66cSDavid du Colombier if(strcmp(f->dir.mid, mid) != 0){ 15385e96a66cSDavid du Colombier vtMemFree(f->dir.mid); 15395e96a66cSDavid du Colombier f->dir.mid = vtStrDup(mid); 15405e96a66cSDavid du Colombier } 15415e96a66cSDavid du Colombier f->dir.mcount++; 15425e96a66cSDavid du Colombier f->dirty = 1; 15435e96a66cSDavid du Colombier fileMetaUnlock(f); 1544*d58da526SDavid du Colombier 1545*d58da526SDavid du Colombier /*RSC: let's try this */ 1546*d58da526SDavid du Colombier /*presotto - lets not 1547*d58da526SDavid du Colombier if(f->up) 1548*d58da526SDavid du Colombier fileWAccess(f->up, mid); 1549*d58da526SDavid du Colombier */ 15505e96a66cSDavid du Colombier } 15515e96a66cSDavid du Colombier 15525e96a66cSDavid du Colombier static void 15535e96a66cSDavid du Colombier markCopied(Block *b) 15545e96a66cSDavid du Colombier { 15555e96a66cSDavid du Colombier Block *lb; 15565e96a66cSDavid du Colombier Label l; 15575e96a66cSDavid du Colombier 15585e96a66cSDavid du Colombier if(globalToLocal(b->score) == NilBlock) 15595e96a66cSDavid du Colombier return; 15605e96a66cSDavid du Colombier 15615e96a66cSDavid du Colombier if(!(b->l.state & BsCopied)){ 15625e96a66cSDavid du Colombier /* 15635e96a66cSDavid du Colombier * We need to record that there are now pointers in 15645e96a66cSDavid du Colombier * b that are not unique to b. We do this by marking 15655e96a66cSDavid du Colombier * b as copied. Since we don't return the label block, 15665e96a66cSDavid du Colombier * the caller can't get the dependencies right. So we have 15675e96a66cSDavid du Colombier * to flush the block ourselves. This is a rare occurrence. 15685e96a66cSDavid du Colombier */ 15695e96a66cSDavid du Colombier l = b->l; 15705e96a66cSDavid du Colombier l.state |= BsCopied; 15715e96a66cSDavid du Colombier lb = _blockSetLabel(b, &l); 15725e96a66cSDavid du Colombier WriteAgain: 15735e96a66cSDavid du Colombier while(!blockWrite(lb)){ 15745e96a66cSDavid du Colombier fprint(2, "getEntry: could not write label block\n"); 15755e96a66cSDavid du Colombier sleep(10*1000); 15765e96a66cSDavid du Colombier } 15775e96a66cSDavid du Colombier while(lb->iostate != BioClean && lb->iostate != BioDirty){ 15785e96a66cSDavid du Colombier assert(lb->iostate == BioWriting); 15795e96a66cSDavid du Colombier vtSleep(lb->ioready); 15805e96a66cSDavid du Colombier } 15815e96a66cSDavid du Colombier if(lb->iostate == BioDirty) 15825e96a66cSDavid du Colombier goto WriteAgain; 15835e96a66cSDavid du Colombier blockPut(lb); 15845e96a66cSDavid du Colombier } 15855e96a66cSDavid du Colombier } 15865e96a66cSDavid du Colombier 15875e96a66cSDavid du Colombier static int 15885e96a66cSDavid du Colombier getEntry(Source *r, Entry *e, int mark) 15895e96a66cSDavid du Colombier { 15905e96a66cSDavid du Colombier Block *b; 15915e96a66cSDavid du Colombier 15925e96a66cSDavid du Colombier if(r == nil){ 15935e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 15945e96a66cSDavid du Colombier return 1; 15955e96a66cSDavid du Colombier } 15965e96a66cSDavid du Colombier 15975e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly); 15985e96a66cSDavid du Colombier if(b == nil) 15995e96a66cSDavid du Colombier return 0; 16005e96a66cSDavid du Colombier if(!entryUnpack(e, b->data, r->offset % r->epb)){ 16015e96a66cSDavid du Colombier blockPut(b); 16025e96a66cSDavid du Colombier return 0; 16035e96a66cSDavid du Colombier } 16045e96a66cSDavid du Colombier 16055e96a66cSDavid du Colombier if(mark) 16065e96a66cSDavid du Colombier markCopied(b); 16075e96a66cSDavid du Colombier blockPut(b); 16085e96a66cSDavid du Colombier return 1; 16095e96a66cSDavid du Colombier } 16105e96a66cSDavid du Colombier 16115e96a66cSDavid du Colombier static int 16125e96a66cSDavid du Colombier setEntry(Source *r, Entry *e) 16135e96a66cSDavid du Colombier { 16145e96a66cSDavid du Colombier Block *b; 16155e96a66cSDavid du Colombier Entry oe; 16165e96a66cSDavid du Colombier 16175e96a66cSDavid du Colombier b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite); 16185e96a66cSDavid du Colombier if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score); 16195e96a66cSDavid du Colombier if(b == nil) 16205e96a66cSDavid du Colombier return 0; 16215e96a66cSDavid du Colombier if(!entryUnpack(&oe, b->data, r->offset % r->epb)){ 16225e96a66cSDavid du Colombier blockPut(b); 16235e96a66cSDavid du Colombier return 0; 16245e96a66cSDavid du Colombier } 16255e96a66cSDavid du Colombier e->gen = oe.gen; 16265e96a66cSDavid du Colombier entryPack(e, b->data, r->offset % r->epb); 16275e96a66cSDavid du Colombier 16285e96a66cSDavid du Colombier /* BUG b should depend on the entry pointer */ 16295e96a66cSDavid du Colombier 16305e96a66cSDavid du Colombier markCopied(b); 16315e96a66cSDavid du Colombier blockDirty(b); 16325e96a66cSDavid du Colombier blockPut(b); 16335e96a66cSDavid du Colombier return 1; 16345e96a66cSDavid du Colombier } 16355e96a66cSDavid du Colombier 16365e96a66cSDavid du Colombier /* assumes hold elk */ 16375e96a66cSDavid du Colombier int 16385e96a66cSDavid du Colombier fileSnapshot(File *dst, File *src, u32int epoch, int doarchive) 16395e96a66cSDavid du Colombier { 16405e96a66cSDavid du Colombier Entry e, ee; 16415e96a66cSDavid du Colombier 16425e96a66cSDavid du Colombier /* add link to snapshot */ 16435e96a66cSDavid du Colombier if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1)) 16445e96a66cSDavid du Colombier return 0; 16455e96a66cSDavid du Colombier 16465e96a66cSDavid du Colombier e.snap = epoch; 16475e96a66cSDavid du Colombier e.archive = doarchive; 16485e96a66cSDavid du Colombier ee.snap = epoch; 16495e96a66cSDavid du Colombier ee.archive = doarchive; 16505e96a66cSDavid du Colombier 16515e96a66cSDavid du Colombier if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee)) 16525e96a66cSDavid du Colombier return 0; 16535e96a66cSDavid du Colombier return 1; 16545e96a66cSDavid du Colombier } 16555e96a66cSDavid du Colombier 16565e96a66cSDavid du Colombier int 16575e96a66cSDavid du Colombier fileGetSources(File *f, Entry *e, Entry *ee, int mark) 16585e96a66cSDavid du Colombier { 16595e96a66cSDavid du Colombier if(!getEntry(f->source, e, mark) 16605e96a66cSDavid du Colombier || !getEntry(f->msource, ee, mark)) 16615e96a66cSDavid du Colombier return 0; 16625e96a66cSDavid du Colombier return 1; 16635e96a66cSDavid du Colombier } 16645e96a66cSDavid du Colombier 16655e96a66cSDavid du Colombier int 16665e96a66cSDavid du Colombier fileWalkSources(File *f) 16675e96a66cSDavid du Colombier { 16685e96a66cSDavid du Colombier if(f->mode == OReadOnly) 16695e96a66cSDavid du Colombier return 1; 16705e96a66cSDavid du Colombier if(!sourceLock2(f->source, f->msource, OReadWrite)) 16715e96a66cSDavid du Colombier return 0; 16725e96a66cSDavid du Colombier sourceUnlock(f->source); 16735e96a66cSDavid du Colombier sourceUnlock(f->msource); 16745e96a66cSDavid du Colombier return 1; 16755e96a66cSDavid du Colombier } 1676