int fileTruncate(File *f, char *uid) { if(fileIsDir(f)){ vtSetError(ENotFile); return 0; } if(!fileLock(f)) return 0; if(f->source->mode != OReadWrite){ vtSetError(EReadOnly); fileUnlock(f); return 0; } if(!sourceLock(f->source, -1)){ fileUnlock(f); return 0; } if(!sourceTruncate(f->source)){ sourceUnlock(f->source); fileUnlock(f); return 0; } sourceUnlock(f->source); fileUnlock(f); fileWAccess(f, uid); return 1; }
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; }
uint64_t Directory::fileSize(void) const { if(!mDirent) throw Exception("No more files in directory"); if(fileIsDir()) return 0; stat_t st; if(pla::stat(filePath().pathEncode().c_str(), &st)) return 0; return uint64_t(st.st_size); }
void Directory::getFileInfo(StringMap &map) const { // Note: fileInfo must not contain path map.clear(); map["name"] = fileName(); map["time"] << fileTime(); if(fileIsDir()) map["type"] = "directory"; else { map["type"] = "file"; map["size"] << fileSize(); } }
int fileRemove(File *f, char *uid) { File *ff; /* can not remove the root */ if(fileIsRoot(f)){ vtSetError(ERoot); return 0; } if(!fileLock(f)) return 0; if(f->source->mode != OReadWrite){ vtSetError(EReadOnly); goto Err1; } if(!sourceLock2(f->source, f->msource, -1)) goto Err1; if(fileIsDir(f) && !fileCheckEmpty(f)) goto Err; for(ff=f->down; ff; ff=ff->next) assert(ff->removed); sourceRemove(f->source); f->source->file = nil; /* erase back pointer */ f->source = nil; if(f->msource){ sourceRemove(f->msource); f->msource = nil; } fileUnlock(f); if(!fileMetaRemove(f, uid)) return 0; return 1; Err: sourceUnlock(f->source); if(f->msource) sourceUnlock(f->msource); Err1: fileUnlock(f); return 0; }
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; }
DirEntryEnum * deeOpen(File *f) { DirEntryEnum *dee; File *p; if(!fileIsDir(f)){ vtSetError(ENotDir); fileDecRef(f); return nil; } /* flush out meta data */ if(!fileLock(f)) return nil; for(p=f->down; p; p=p->next) fileMetaFlush2(p, nil); fileUnlock(f); dee = vtMemAllocZ(sizeof(DirEntryEnum)); dee->file = fileIncRef(f); return dee; }
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; }
File * _fileWalk(File *f, char *elem, int partial) { File *ff; fileRAccess(f); if(elem[0] == 0){ vtSetError(EBadPath); return nil; } if(!fileIsDir(f)){ vtSetError(ENotDir); return nil; } if(strcmp(elem, ".") == 0){ return fileIncRef(f); } if(strcmp(elem, "..") == 0){ if(fileIsRoot(f)) return fileIncRef(f); return fileIncRef(f->up); } if(!fileLock(f)) return nil; for(ff = f->down; ff; ff=ff->next){ if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){ ff->ref++; goto Exit; } } ff = dirLookup(f, elem); if(ff == nil) goto Err; if(ff->dir.mode & ModeSnapshot){ ff->mode = OReadOnly; ff->issnapshot = 1; } if(partial){ /* * Do nothing. We're opening this file only so we can clri it. * Usually the sources can't be opened, hence we won't even bother. * Be VERY careful with the returned file. If you hand it to a routine * expecting ff->source and/or ff->msource to be non-nil, we're * likely to dereference nil. FileClri should be the only routine * setting partial. */ ff->partial = 1; }else if(ff->dir.mode & ModeDir){ ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 1, ff->mode, ff->issnapshot); ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen, 0, ff->mode, ff->issnapshot); if(ff->source == nil || ff->msource == nil) goto Err; }else{ ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen, 0, ff->mode, ff->issnapshot); if(ff->source == nil) goto Err; } /* link in and up parent ref count */ if (ff->source) ff->source->file = ff; /* point back */ ff->next = f->down; f->down = ff; ff->up = f; fileIncRef(f); Exit: fileUnlock(f); return ff; Err: fileUnlock(f); if(ff != nil) fileDecRef(ff); return nil; }