📄 file.c
字号:
/* link in and up parent ref count */ nvf->next = vf->down; vf->down = nvf; nvf->up = vf; vfIncRef(vf); vfWAccess(vf, user); vfUnlock(vf); return nvf;Err: lumpDecRef(u, 1); if(r) sourceRemove(r); if(mr) sourceRemove(mr); if(nvf) vfFree(nvf); vfUnlock(vf); return 0;}intvfRead(VacFile *vf, void *buf, int cnt, vlong offset){ Source *s; uvlong size; ulong bn; int off, dsize, n, nn; Lump *u; uchar *b;if(0)fprint(2, "vfRead: %s %d, %lld\n", vf->dir.elem, cnt, offset); if(!vfRLock(vf)) return -1; s = vf->source; dsize = s->dsize; size = sourceGetSize(s); if(offset < 0) { vtSetError(EBadOffset); goto Err; } vfRAccess(vf); if(offset >= size) offset = size; if(cnt > size-offset) cnt = size-offset; bn = offset/dsize; off = offset%dsize; b = buf; while(cnt > 0) { u = sourceGetLump(s, bn, 1, 0); if(u == nil) goto Err; if(u->asize <= off) { lumpDecRef(u, 0); goto Err; } n = cnt; if(n > dsize-off) n = dsize-off; nn = u->asize-off; if(nn > n) nn = n; memmove(b, u->data+off, nn); memset(b+nn, 0, n-nn); off = 0; bn++; cnt -= n; b += n; lumpDecRef(u, 0); } vfRUnlock(vf); return b-(uchar*)buf;Err: vfRUnlock(vf); return -1;}intvfWrite(VacFile *vf, void *buf, int cnt, vlong offset, char *user){ Source *s; ulong bn; int off, dsize, n; Lump *u; uchar *b; USED(user); if(!vfLock(vf)) return -1; if(vf->fs->readOnly) { vtSetError(EReadOnly); goto Err; } if(vf->dir.mode & ModeDir) { vtSetError(ENotFile); goto Err; }if(0)fprint(2, "vfWrite: %s %d, %lld\n", vf->dir.elem, cnt, offset); s = vf->source; dsize = s->dsize; if(offset < 0) { vtSetError(EBadOffset); goto Err; } vfWAccess(vf, user); bn = offset/dsize; off = offset%dsize; b = buf; while(cnt > 0) { n = cnt; if(n > dsize-off) n = dsize-off; if(!sourceSetDepth(s, offset+n)) goto Err; u = sourceGetLump(s, bn, 0, 0); if(u == nil) goto Err; if(u->asize < dsize) { vtSetError("runt block"); lumpDecRef(u, 0); goto Err; } memmove(u->data+off, b, n); off = 0; cnt -= n; b += n; offset += n; bn++; lumpDecRef(u, 0); if(!sourceSetSize(s, offset)) goto Err; } vfLock(vf); return b-(uchar*)buf;Err: vfLock(vf); return -1;}intvfGetDir(VacFile *vf, VacDir *dir){ if(!vfRLock(vf)) return 0; vfMetaLock(vf); vdCopy(dir, &vf->dir); vfMetaUnlock(vf); if(!vfIsDir(vf)) dir->size = sourceGetSize(vf->source); vfRUnlock(vf); return 1;}uvlongvfGetId(VacFile *vf){ /* immutable */ return vf->dir.qid;}ulongvfGetMcount(VacFile *vf){ ulong mcount; vfMetaLock(vf); mcount = vf->dir.mcount; vfMetaUnlock(vf); return mcount;}intvfIsDir(VacFile *vf){ /* immutable */ return (vf->dir.mode & ModeDir) != 0;}intvfIsRoot(VacFile *vf){ return vf == vf->fs->root;}intvfGetSize(VacFile *vf, uvlong *size){ if(!vfRLock(vf)) return 0; *size = sourceGetSize(vf->source); vfRUnlock(vf); return 1;}static intvfMetaRemove(VacFile *vf, char *user){ Lump *u; MetaBlock mb; MetaEntry me; int i; VacFile *vfp; vfp = vf->up; vfWAccess(vfp, user); vfMetaLock(vf); u = sourceGetLump(vfp->msource, vf->block, 0, 1); if(u == nil) goto Err; if(!mbUnpack(&mb, u->data, u->asize)) goto Err; if(!mbSearch(&mb, vf->dir.elem, &i, &me) || me.p == nil) goto Err;print("deleting %d entry\n", i); mbDelete(&mb, i, &me); memset(me.p, 0, me.size); mbPack(&mb); lumpDecRef(u, 1); vf->removed = 1; vf->block = NilBlock; vfMetaUnlock(vf); return 1;Err: lumpDecRef(u, 1); vfMetaUnlock(vf); return 0;}static intvfCheckEmpty(VacFile *vf){ int i, n; Lump *u; MetaBlock mb; Source *r; r = vf->msource; n = sourceGetNumBlocks(r); for(i=0; i<n; i++) { u = sourceGetLump(r, i, 1, 1); if(u == nil) goto Err; if(!mbUnpack(&mb, u->data, u->asize)) goto Err; if(mb.nindex > 0) { vtSetError(ENotEmpty); goto Err; } lumpDecRef(u, 1); } return 1;Err: lumpDecRef(u, 1); return 0;}intvfRemove(VacFile *vf, char *user){ /* can not remove the root */ if(vfIsRoot(vf)) { vtSetError(ERoot); return 0; } if(!vfLock(vf)) return 0; if(vfIsDir(vf) && !vfCheckEmpty(vf)) goto Err; assert(vf->down == nil); sourceRemove(vf->source); vf->source = nil; if(vf->msource) { sourceRemove(vf->msource); vf->msource = nil; } vfUnlock(vf); if(!vfMetaRemove(vf, user)) return 0; return 1;Err: vfUnlock(vf); return 0;}VacFile *vfIncRef(VacFile *vf){ vfMetaLock(vf); assert(vf->ref > 0); vf->ref++; vfMetaUnlock(vf); return vf;}voidvfDecRef(VacFile *vf){ VacFile *p, *q, **qq; if(vf->up == nil) { vfFree(vf); return; } vfMetaLock(vf); vf->ref--; if(vf->ref > 0) { vfMetaUnlock(vf); return; } assert(vf->ref == 0); assert(vf->down == nil); p = vf->up; qq = &p->down; for(q = *qq; q; qq=&q->next,q=*qq) if(q == vf) break; assert(q != nil); *qq = vf->next; vfMetaUnlock(vf); vfFree(vf); vfDecRef(p);}intvfGetVtEntry(VacFile *vf, VtEntry *e){ int res; if(!vfRLock(vf)) return 0; res = sourceGetVtEntry(vf->source, e); vfRUnlock(vf); return res;}#ifdef notdefintvfGetBlockScore(VacFile *vf, ulong bn, uchar score[VtScoreSize]){ Lump *u; int ret, off; Source *r; if(!vfRLock(vf)) return 0; r = vf->source; u = sourceWalk(r, bn, 1, &off); if(u == nil){ vfRUnlock(vf); return 0; } ret = lumpGetScore(u, off, score); lumpDecRef(u, 0); vfRUnlock(vf); return ret;}#endifVacFile *vfGetParent(VacFile *vf){ if(vfIsRoot(vf)) return vfIncRef(vf); return vfIncRef(vf->up);}static VacDirEnum *vdeAlloc(VacFile *vf){ VacDirEnum *ds; if(!(vf->dir.mode & ModeDir)) { vtSetError(ENotDir); vfDecRef(vf); return nil; } ds = vtMemAllocZ(sizeof(VacDirEnum)); ds->file = vf; return ds;}VacDirEnum *vdeOpen(VacFS *fs, char *path){ VacFile *vf; vf = vfOpen(fs, path); if(vf == nil) return nil; return vdeAlloc(vf);}VacDirEnum *vfDirEnum(VacFile *vf){ return vdeAlloc(vfIncRef(vf));}static intdirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size){ Lump *u; ulong bn; VtEntry e; bn = elem/s->epb; elem -= bn*s->epb; u = sourceGetLump(s, bn, 1, 1); if(u == nil) goto Err; if(u->asize < (elem+1)*VtEntrySize) { vtSetError(ENoDir); goto Err; } vtEntryUnpack(&e, u->data, elem); if(!(e.flags & VtEntryActive) || e.gen != gen) {fprint(2, "gen mismatch\n"); vtSetError(ENoDir); goto Err; } *size = e.size; lumpDecRef(u, 1); return 1;Err: lumpDecRef(u, 1); return 0;}intvdeRead(VacDirEnum *ds, VacDir *dir, int n){ ulong nb; int i; Source *meta, *source; MetaBlock mb; MetaEntry me; Lump *u; vfRAccess(ds->file); if(!vfRLock(ds->file)) return -1; i = 0; u = nil; source = ds->file->source; meta = ds->file->msource; nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize; if(ds->block >= nb) goto Exit; u = sourceGetLump(meta, ds->block, 1, 1); if(u == nil) goto Err; if(!mbUnpack(&mb, u->data, u->asize)) goto Err; for(i=0; i<n; i++) { while(ds->index >= mb.nindex) { lumpDecRef(u, 1); u = nil; ds->index = 0; ds->block++; if(ds->block >= nb) goto Exit; u = sourceGetLump(meta, ds->block, 1, 1); if(u == nil) goto Err; if(!mbUnpack(&mb, u->data, u->asize)) goto Err; } if(!meUnpack(&me, &mb, ds->index)) goto Err; if(dir != nil) { if(!vdUnpack(&dir[i], &me)) goto Err; if(!(dir[i].mode & ModeDir)) if(!dirEntrySize(source, dir[i].entry, dir[i].gen, &dir[i].size)) goto Err; } ds->index++; }Exit: lumpDecRef(u, 1); vfRUnlock(ds->file); return i;Err: lumpDecRef(u, 1); vfRUnlock(ds->file); n = i; for(i=0; i<n ; i++) vdCleanup(&dir[i]); return -1;}voidvdeFree(VacDirEnum *ds){ if(ds == nil) return; vfDecRef(ds->file); vtMemFree(ds);}static ulongmsAlloc(Source *ms, ulong start, int n){ ulong nb, i; Lump *u; MetaBlock mb; nb = sourceGetNumBlocks(ms); u = nil; if(start > nb) start = nb; for(i=start; i<nb; i++) { u = sourceGetLump(ms, i, 1, 1); if(u == nil) goto Err; if(!mbUnpack(&mb, u->data, ms->dsize)) goto Err; if(mb.maxsize - mb.size + mb.free >= n && mb.nindex < mb.maxindex) break; lumpDecRef(u, 1); u = nil; } /* add block to meta file */ if(i == nb) { if(!sourceSetDepth(ms, (i+1)*ms->dsize)) goto Err; u = sourceGetLump(ms, i, 0, 1); if(u == nil) goto Err; sourceSetSize(ms, (nb+1)*ms->dsize); mbInit(&mb, u->data, u->asize); mbPack(&mb); } lumpDecRef(u, 1); return i;Err: lumpDecRef(u, 1); return NilBlock;}VacFS *vacfs(VacFile *vf){ if (vf == nil) return nil; return vf->fs;}/* * path may be nil; it's the right-hand part of the path so far. * result is malloced, path must be malloced or nil. */char *vfName(VacFile *vf, char *path){ char *nname, *rname, *elem; if (vf == nil || vf == vf->up) { /* at the root? */ if (path == nil) return strdup("/"); return path; } elem = vf->dir.elem; if (elem != nil && path != nil) rname = smprint("%s/%s", elem, path); else if (elem != nil) rname = strdup(elem); else return vfName(vf->up, path); nname = vfName(vf->up, rname); if (nname != rname) free(rname); return nname;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -