int fileMetaFlush(File *f, int rec) { File **kids, *p; int nkids; int i, rv; fileMetaLock(f); rv = fileMetaFlush2(f, nil); fileMetaUnlock(f); if(!rec || !fileIsDir(f)) return rv; if(!fileLock(f)) return rv; nkids = 0; for(p=f->down; p; p=p->next) nkids++; kids = vtMemAlloc(nkids*sizeof(File*)); i = 0; for(p=f->down; p; p=p->next){ kids[i++] = p; p->ref++; } fileUnlock(f); for(i=0; i<nkids; i++){ rv |= fileMetaFlush(kids[i], 1); fileDecRef(kids[i]); } vtMemFree(kids); return rv; }
File * fileIncRef(File *vf) { fileMetaLock(vf); assert(vf->ref > 0); vf->ref++; fileMetaUnlock(vf); return vf; }
ulong fileGetMode(File *f) { ulong mode; fileMetaLock(f); mode = f->dir.mode; fileMetaUnlock(f); return mode; }
ulong fileGetMcount(File *f) { ulong mcount; fileMetaLock(f); mcount = f->dir.mcount; fileMetaUnlock(f); return mcount; }
uint32_t fileGetMode(File *f) { uint32_t mode; fileMetaLock(f); mode = f->dir.mode; fileMetaUnlock(f); return mode; }
uint32_t fileGetMcount(File *f) { uint32_t mcount; fileMetaLock(f); mcount = f->dir.mcount; fileMetaUnlock(f); return mcount; }
/* * f->source and f->msource must NOT be locked. * see fileMetaLock. */ static void fileRAccess(File* f) { if(f->mode == OReadOnly || f->fs->noatimeupd) return; fileMetaLock(f); f->dir.atime = time(0L); f->dirty = 1; fileMetaUnlock(f); }
static int fileMetaRemove(File *f, char *uid) { Block *b; MetaBlock mb; MetaEntry me; int i; File *up; up = f->up; fileWAccess(up, uid); fileMetaLock(f); sourceLock(up->msource, OReadWrite); b = sourceBlock(up->msource, f->boff, OReadWrite); if(b == nil) goto Err; if(!mbUnpack(&mb, b->data, up->msource->dsize)) { fprint(2, "U\n"); goto Err; } if(!mbSearch(&mb, f->dir.elem, &i, &me)) { fprint(2, "S\n"); goto Err; } mbDelete(&mb, i); mbPack(&mb); sourceUnlock(up->msource); blockDirty(b); blockPut(b); f->removed = 1; f->boff = NilBlock; f->dirty = 0; fileMetaUnlock(f); return 1; Err: sourceUnlock(up->msource); blockPut(b); fileMetaUnlock(f); return 0; }
int fileSetQidSpace(File *f, u64int offset, u64int max) { int ret; if(!fileLock(f)) return 0; fileMetaLock(f); f->dir.qidSpace = 1; f->dir.qidOffset = offset; f->dir.qidMax = max; ret = fileMetaFlush2(f, nil)>=0; fileMetaUnlock(f); fileUnlock(f); return ret; }
int fileGetDir(File *f, DirEntry *dir) { if(!fileRLock(f)) return 0; fileMetaLock(f); deCopy(dir, &f->dir); fileMetaUnlock(f); if(!fileIsDir(f)){ if(!sourceLock(f->source, OReadOnly)){ fileRUnlock(f); return 0; } dir->size = sourceGetSize(f->source); sourceUnlock(f->source); } fileRUnlock(f); return 1; }
/* * f->source and f->msource must NOT be locked. * see fileMetaLock. */ static void fileWAccess(File* f, char *mid) { if(f->mode == OReadOnly) return; fileMetaLock(f); f->dir.atime = f->dir.mtime = time(0L); if(strcmp(f->dir.mid, mid) != 0){ vtMemFree(f->dir.mid); f->dir.mid = vtStrDup(mid); } f->dir.mcount++; f->dirty = 1; fileMetaUnlock(f); /*RSC: let's try this */ /*presotto - lets not if(f->up) fileWAccess(f->up, mid); */ }
int fileDecRef(File *f) { File *p, *q, **qq; if(f->up == nil){ /* never linked in */ assert(f->ref == 1); fileFree(f); return 1; } fileMetaLock(f); f->ref--; if(f->ref > 0){ fileMetaUnlock(f); return 0; } assert(f->ref == 0); assert(f->down == nil); fileMetaFlush2(f, nil); p = f->up; qq = &p->down; for(q = *qq; q; q = *qq){ if(q == f) break; qq = &q->next; } assert(q != nil); *qq = f->next; fileMetaUnlock(f); fileFree(f); fileDecRef(p); return 1; }
int fileSetDir(File *f, DirEntry *dir, char *uid) { File *ff; char *oelem; u32int mask; u64int size; /* can not set permissions for the root */ if(fileIsRoot(f)){ vtSetError(ERoot); return 0; } if(!fileLock(f)) return 0; if(f->source->mode != OReadWrite){ vtSetError(EReadOnly); fileUnlock(f); return 0; } fileMetaLock(f); /* check new name does not already exist */ if(strcmp(f->dir.elem, dir->elem) != 0){ for(ff = f->up->down; ff; ff=ff->next){ if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ vtSetError(EExists); goto Err; } } ff = dirLookup(f->up, dir->elem); if(ff != nil){ fileDecRef(ff); vtSetError(EExists); goto Err; } } if(!sourceLock2(f->source, f->msource, -1)) goto Err; if(!fileIsDir(f)){ size = sourceGetSize(f->source); if(size != dir->size){ if(!sourceSetSize(f->source, dir->size)){ sourceUnlock(f->source); if(f->msource) sourceUnlock(f->msource); goto Err; } /* commited to changing it now */ } } /* commited to changing it now */ if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary)) fileSetTmp(f, dir->mode&ModeTemporary); sourceUnlock(f->source); if(f->msource) sourceUnlock(f->msource); oelem = nil; if(strcmp(f->dir.elem, dir->elem) != 0){ oelem = f->dir.elem; f->dir.elem = vtStrDup(dir->elem); } if(strcmp(f->dir.uid, dir->uid) != 0){ vtMemFree(f->dir.uid); f->dir.uid = vtStrDup(dir->uid); } if(strcmp(f->dir.gid, dir->gid) != 0){ vtMemFree(f->dir.gid); f->dir.gid = vtStrDup(dir->gid); } f->dir.mtime = dir->mtime; f->dir.atime = dir->atime; //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); mask = ~(ModeDir|ModeSnapshot); f->dir.mode &= ~mask; f->dir.mode |= mask & dir->mode; f->dirty = 1; //fprint(2, "->%x\n", f->dir.mode); fileMetaFlush2(f, oelem); vtMemFree(oelem); fileMetaUnlock(f); fileUnlock(f); fileWAccess(f->up, uid); return 1; Err: fileMetaUnlock(f); fileUnlock(f); return 0; }