int sourceSetDirSize(Source *r, uint32_t ds) { uint64_t size; int epb; assert(sourceIsLocked(r)); epb = r->dsize/VtEntrySize; size = (uint64_t)r->dsize*(ds/epb); size += VtEntrySize*(ds%epb); return sourceSetSize(r, size); }
int fileSetSize(File *f, uvlong size) { int r; if(!fileLock(f)) return 0; r = 0; if(f->dir.mode & ModeDir){ vtSetError(ENotFile); goto Err; } if(f->source->mode != OReadWrite){ vtSetError(EReadOnly); goto Err; } if(!sourceLock(f->source, -1)) goto Err; r = sourceSetSize(f->source, size); sourceUnlock(f->source); Err: fileUnlock(f); return r; }
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; }
int fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid) { Source *s; ulong bn; int off, dsize, n; Block *b; uchar *p; vlong eof; if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset); if(!fileLock(f)) return -1; s = nil; if(f->dir.mode & ModeDir){ vtSetError(ENotFile); goto Err; } if(f->source->mode != OReadWrite){ vtSetError(EReadOnly); goto Err; } if(offset < 0){ vtSetError(EBadOffset); goto Err; } fileWAccess(f, uid); if(!sourceLock(f->source, -1)) goto Err; s = f->source; dsize = s->dsize; eof = sourceGetSize(s); if(f->dir.mode & ModeAppend) offset = eof; bn = offset/dsize; off = offset%dsize; p = buf; while(cnt > 0){ n = cnt; if(n > dsize-off) n = dsize-off; b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite); if(b == nil){ if(offset > eof) sourceSetSize(s, offset); goto Err; } memmove(b->data+off, p, n); off = 0; cnt -= n; p += n; offset += n; bn++; blockDirty(b); blockPut(b); } if(offset > eof && !sourceSetSize(s, offset)) goto Err; sourceUnlock(s); fileUnlock(f); return p-(uchar*)buf; Err: if(s) sourceUnlock(s); fileUnlock(f); return -1; }
/* * caller must lock f->source and f->msource * caller must NOT lock the source and msource * referenced by dir. */ static u32int fileMetaAlloc(File *f, DirEntry *dir, u32int start) { u32int nb, bo; Block *b, *bb; MetaBlock mb; int nn; uchar *p; int i, n, epb; MetaEntry me; Source *s, *ms; s = f->source; ms = f->msource; n = deSize(dir); nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize; b = nil; if(start > nb) start = nb; for(bo=start; bo<nb; bo++){ b = sourceBlock(ms, bo, OReadWrite); if(b == nil) goto Err; if(!mbUnpack(&mb, b->data, ms->dsize)) goto Err; nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free; if(n <= nn && mb.nindex < mb.maxindex) break; blockPut(b); b = nil; } /* add block to meta file */ if(b == nil){ b = sourceBlock(ms, bo, OReadWrite); if(b == nil) goto Err; sourceSetSize(ms, (nb+1)*ms->dsize); mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry); } p = mbAlloc(&mb, n); if(p == nil){ /* mbAlloc might have changed block */ mbPack(&mb); blockDirty(b); vtSetError(EBadMeta); goto Err; } mbSearch(&mb, dir->elem, &i, &me); assert(me.p == nil); me.p = p; me.size = n; dePack(dir, &me); mbInsert(&mb, i, &me); mbPack(&mb); /* meta block depends on super block for qid ... */ bb = cacheLocal(b->c, PartSuper, 0, OReadOnly); blockDependency(b, bb, -1, nil, nil); blockPut(bb); /* ... and one or two dir entries */ epb = s->dsize/VtEntrySize; bb = sourceBlock(s, dir->entry/epb, OReadOnly); blockDependency(b, bb, -1, nil, nil); blockPut(bb); if(dir->mode & ModeDir){ bb = sourceBlock(s, dir->mentry/epb, OReadOnly); blockDependency(b, bb, -1, nil, nil); blockPut(bb); } blockDirty(b); blockPut(b); return bo; Err: blockPut(b); return NilBlock; }