📄 check.c
字号:
r = nil; if(getBit(bm, offset)){ warn(chk, "multiple references to source: %s -> %d", name, offset); goto Err; } setBit(bm, offset); r = sourceOpen(s, offset, OReadOnly); if(r == nil){ warn(chk, "could not open source: %s -> %d: %R", name, offset); goto Err; } if(r->gen != gen){ warn(chk, "source has been removed: %s -> %d", name, offset); goto Err; } if(r->dir != dir){ warn(chk, "dir mismatch: %s -> %d", name, offset); goto Err; } return r;Err: chk->clri(chk, name, mb, i, b); chk->nclri++; if(r) sourceClose(r); return nil;}typedef struct MetaChunk MetaChunk;struct MetaChunk { ushort offset; ushort size; ushort index;};static intoffsetCmp(void *s0, void *s1){ MetaChunk *mc0, *mc1; mc0 = s0; mc1 = s1; if(mc0->offset < mc1->offset) return -1; if(mc0->offset > mc1->offset) return 1; return 0;}/* * Fsck that MetaBlock has reasonable header, sorted entries, */static intchkMetaBlock(MetaBlock *mb){ MetaChunk *mc; int oo, o, n, i; uchar *p; mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk)); p = mb->buf + MetaHeaderSize; for(i = 0; i<mb->nindex; i++){ mc[i].offset = (p[0]<<8) | p[1]; mc[i].size = (p[2]<<8) | p[3]; mc[i].index = i; p += MetaIndexSize; } qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp); /* check block looks ok */ oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; o = oo; n = 0; for(i=0; i<mb->nindex; i++){ o = mc[i].offset; n = mc[i].size; if(o < oo) goto Err; oo += n; } if(o+n > mb->size) goto Err; if(mb->size - oo != mb->free) goto Err; vtMemFree(mc); return 1;Err:if(0){ fprint(2, "metaChunks failed!\n"); oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; for(i=0; i<mb->nindex; i++){ fprint(2, "\t%d: %d %d\n", i, mc[i].offset, mc[i].offset + mc[i].size); oo += mc[i].size; } fprint(2, "\tused=%d size=%d free=%d free2=%d\n", oo, mb->size, mb->free, mb->size - oo);} vtMemFree(mc); return 0;}static voidscanSource(Fsck *chk, char *name, Source *r){ u32int nb, o; Block *b; Entry e; u32int a; if(!chk->useventi && globalToLocal(r->score)==NilBlock) return; if(!sourceGetEntry(r, &e)){ error(chk, "could not get entry for %s", name); return; } a = globalToLocal(e.score); if(!chk->useventi && a==NilBlock) return; if(getBit(chk->smap, a)) return; setBit(chk->smap, a); nb = (sourceGetSize(r) + r->dsize-1) / r->dsize; for(o=0; o<nb; o++){ b = sourceBlock(r, o, OReadOnly); if(b == nil){ error(chk, "could not read block in data file %s", name); continue; } if(b->addr != NilBlock && getBit(chk->errmap, b->addr)){ warn(chk, "previously reported error in block %ux is in file %s", b->addr, name); } blockPut(b); }}/* * Walk the source tree making sure that the BtData * sources containing directory entries are okay. */static voidchkDir(Fsck *chk, char *name, Source *source, Source *meta){ uchar *bm; Block *b, *bb; u32int nb, o; MetaBlock mb; DirEntry de; Entry e1, e2; MetaEntry me; int i; char *s, *nn; Source *r, *mr; u32int a1, a2; if(!chk->useventi && globalToLocal(source->score)==NilBlock && globalToLocal(meta->score)==NilBlock) return; if(!sourceLock2(source, meta, OReadOnly)){ warn(chk, "could not lock sources for %s: %R", name); return; } if(!sourceGetEntry(source, &e1) || !sourceGetEntry(meta, &e2)){ warn(chk, "could not load entries for %s: %R", name); return; } a1 = globalToLocal(e1.score); a2 = globalToLocal(e2.score); if((!chk->useventi && a1==NilBlock && a2==NilBlock) || (getBit(chk->smap, a1) && getBit(chk->smap, a2))){ sourceUnlock(source); sourceUnlock(meta); return; } setBit(chk->smap, a1); setBit(chk->smap, a2); bm = vtMemAllocZ(sourceGetDirSize(source)/8 + 1); nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize; for(o=0; o<nb; o++){ b = sourceBlock(meta, o, OReadOnly); if(b == nil){ error(chk, "could not read block in meta file: %s[%ud]: %R", name, o); continue; }if(0)fprint(2, "source %V:%d block %d addr %d\n", source->score, source->offset, o, b->addr); if(b->addr != NilBlock && getBit(chk->errmap, b->addr)) warn(chk, "previously reported error in block %ux is in %s", b->addr, name); if(!mbUnpack(&mb, b->data, meta->dsize)){ error(chk, "could not unpack meta block: %s[%ud]: %R", name, o); blockPut(b); continue; } if(!chkMetaBlock(&mb)){ error(chk, "bad meta block: %s[%ud]: %R", name, o); blockPut(b); continue; } s = nil; for(i=mb.nindex-1; i>=0; i--){ meUnpack(&me, &mb, i); if(!deUnpack(&de, &me)){ error(chk, "cound not unpack dir entry: %s[%ud][%d]: %R", name, o, i); continue; } if(s && strcmp(s, de.elem) <= 0) error(chk, "dir entry out of order: %s[%ud][%d] = %s last = %s", name, o, i, de.elem, s); vtMemFree(s); s = vtStrDup(de.elem); nn = smprint("%s/%s", name, de.elem); if(nn == nil){ error(chk, "out of memory"); continue; } if(chk->printdirs){ if(de.mode&ModeDir) chk->print("%s/\n", nn); } if(chk->printfiles){ if(!(de.mode&ModeDir)) chk->print("%s\n", nn); } if(!(de.mode & ModeDir)){ r = openSource(chk, source, nn, bm, de.entry, de.gen, 0, &mb, i, b); if(r != nil){ if(sourceLock(r, OReadOnly)){ scanSource(chk, nn, r); sourceUnlock(r); } sourceClose(r); } deCleanup(&de); free(nn); continue; } r = openSource(chk, source, nn, bm, de.entry, de.gen, 1, &mb, i, b); if(r == nil){ deCleanup(&de); free(nn); continue; } mr = openSource(chk, source, nn, bm, de.mentry, de.mgen, 0, &mb, i, b); if(mr == nil){ sourceClose(r); deCleanup(&de); free(nn); continue; } if(!(de.mode&ModeSnapshot) || chk->walksnapshots) chkDir(chk, nn, r, mr); sourceClose(mr); sourceClose(r); deCleanup(&de); free(nn); deCleanup(&de); } vtMemFree(s); blockPut(b); } nb = sourceGetDirSize(source); for(o=0; o<nb; o++){ if(getBit(bm, o)) continue; r = sourceOpen(source, o, OReadOnly); if(r == nil) continue; warn(chk, "non referenced entry in source %s[%d]", name, o); if((bb = sourceBlock(source, o/(source->dsize/VtEntrySize), OReadOnly)) != nil){ if(bb->addr != NilBlock){ setBit(chk->errmap, bb->addr); chk->clre(chk, bb, o%(source->dsize/VtEntrySize)); chk->nclre++; } blockPut(bb); } sourceClose(r); } sourceUnlock(source); sourceUnlock(meta); vtMemFree(bm);}static voidcheckDirs(Fsck *chk){ Source *r, *mr; sourceLock(chk->fs->source, OReadOnly); r = sourceOpen(chk->fs->source, 0, OReadOnly); mr = sourceOpen(chk->fs->source, 1, OReadOnly); sourceUnlock(chk->fs->source); chkDir(chk, "", r, mr); sourceClose(r); sourceClose(mr);}static voidsetBit(uchar *bmap, u32int addr){ if(addr == NilBlock) return; bmap[addr>>3] |= 1 << (addr & 7);}static intgetBit(uchar *bmap, u32int addr){ if(addr == NilBlock) return 0; return (bmap[addr>>3] >> (addr & 7)) & 1;}static voiderror(Fsck *chk, char *fmt, ...){ static nerr; va_list arg; char buf[128]; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); chk->print("error: %s\n", buf);// if(nerr++ > 20)// vtFatal("too many errors");}static voidwarn(Fsck *chk, char *fmt, ...){ static nerr; va_list arg; char buf[128]; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); chk->print("error: %s\n", buf);}static voidclrenop(Fsck*, Block*, int){}static voidclosenop(Fsck*, Block*, u32int){}static voidclrinop(Fsck*, char*, MetaBlock*, int, Block*){}static intprintnop(char*, ...){ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -