/* * read the arena header and trailer blocks from disk */ static int loadarena(Arena *arena) { ArenaHead head; ZBlock *b; b = alloczblock(arena->blocksize, 0, arena->part->blocksize); if(b == nil) return -1; if(readpart(arena->part, arena->base + arena->size, b->data, arena->blocksize) < 0){ freezblock(b); return -1; } if(unpackarena(arena, b->data) < 0){ freezblock(b); return -1; } if(arena->version != ArenaVersion4 && arena->version != ArenaVersion5){ seterr(EAdmin, "unknown arena version %d", arena->version); freezblock(b); return -1; } scorecp(arena->score, &b->data[arena->blocksize - VtScoreSize]); if(readpart(arena->part, arena->base - arena->blocksize, b->data, arena->blocksize) < 0){ logerr(EAdmin, "can't read arena header: %r"); freezblock(b); return 0; } if(unpackarenahead(&head, b->data) < 0) logerr(ECorrupt, "corrupted arena header: %r"); else if(namecmp(arena->name, head.name)!=0 || arena->clumpmagic != head.clumpmagic || arena->version != head.version || arena->blocksize != head.blocksize || arena->size + 2 * arena->blocksize != head.size){ if(namecmp(arena->name, head.name)!=0) logerr(ECorrupt, "arena tail name %s head %s", arena->name, head.name); else if(arena->clumpmagic != head.clumpmagic) logerr(ECorrupt, "arena %d tail clumpmagic 0x%lux head 0x%lux", debugarena, (uint32_t)arena->clumpmagic, (uint32_t)head.clumpmagic); else if(arena->version != head.version) logerr(ECorrupt, "arena tail version %d head version %d", arena->version, head.version); else if(arena->blocksize != head.blocksize) logerr(ECorrupt, "arena tail block size %d head %d", arena->blocksize, head.blocksize); else if(arena->size+2*arena->blocksize != head.size) logerr(ECorrupt, "arena tail size %lud head %lud", (uint32_t)arena->size+2*arena->blocksize, head.size); else logerr(ECorrupt, "arena header inconsistent with arena data"); } freezblock(b); return 0; }
/* * Return the next IEntry (still packed) in the stream. */ static uint8_t* peekientry(IEStream *ies) { uint32_t n, nn; n = ies->epos - ies->pos; if(n < IEntrySize){ memmove(ies->buf, ies->pos, n); ies->epos = &ies->buf[n]; ies->pos = ies->buf; nn = ies->size; if(nn > ies->n * IEntrySize) nn = ies->n * IEntrySize; nn -= n; if(nn == 0) return nil; //fprint(2, "peek %d from %llud into %p\n", nn, ies->off, ies->epos); if(readpart(ies->part, ies->off, ies->epos, nn) < 0){ seterr(EOk, "can't read sorted index entries: %r"); return nil; } ies->epos += nn; ies->off += nn; } return ies->pos; }
/* * read in the chained buffers for bucket b, * and return it's total number of IEntries */ static uint32_t readiebuck(IEBucks *ib, int b) { uint32_t head, m, n; head = ib->bucks[b].head; n = 0; m = ib->bucks[b].used; if(m == 0) m = ib->usable; if(0) if(ib->bucks[b].total) fprint(2, "\tbucket %d: %lld entries\n", b, ib->bucks[b].total/IEntrySize); while(head != TWID32){ if(readpart(ib->part, (uint64_t)head * ib->size, &ib->buf[n], m+U32Size) < 0){ seterr(EOk, "can't read index sort bucket: %r"); return TWID32; } n += m; head = U32GET(&ib->buf[n]); m = ib->usable; } if(n != ib->bucks[b].total) fprint(2, "\tbucket %d: expected %d entries, got %d\n", b, (int)ib->bucks[b].total/IEntrySize, n/IEntrySize); return n / IEntrySize; }
static vlong findintoc(HConnect *c, Arena *arena, uchar *score) { uchar *blk; int i; vlong off; vlong coff; ClumpInfo ci; blk = vtmalloc(arena->blocksize); off = arena->base + arena->size; coff = 0; for(i=0; i<arena->memstats.clumps; i++){ if(i%arena->clumpmax == 0){ off -= arena->blocksize; if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){ if(c) hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n", off); break; } } unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize); if(scorecmp(ci.score, score) == 0){ vtfree(blk); return coff; } coff += ClumpSize + ci.size; } vtfree(blk); return -1; }
Bloom* readbloom(Part *p) { uchar buf[512]; Bloom *b; b = vtmallocz(sizeof *b); if(readpart(p, 0, buf, sizeof buf) < 0) return nil; /* * pass buf as b->data so that bloominit * can parse header. won't be used for * accessing bits (cleared below). */ if(bloominit(b, 0, buf) < 0){ vtfree(b); return nil; }else{ /* * default block size is system page size. * the bloom filter is usually very big. * bump the block size up to speed i/o. */ if(p->blocksize < (1<<20)){ p->blocksize = 1<<20; if(p->blocksize > p->size) p->blocksize = p->size; } } b->part = p; b->data = nil; return b; }
static void rdarena(Arena *arena) { ZBlock *b; uint64_t a, e; uint32_t bs; if (!quiet) { fprint(2, "copying %s to standard output\n", arena->name); printarena(2, arena); } bs = MaxIoSize; if(bs < arena->blocksize) bs = arena->blocksize; b = alloczblock(bs, 0, arena->blocksize); e = arena->base + arena->size + arena->blocksize; for(a = arena->base - arena->blocksize; a + arena->blocksize <= e; a += bs){ if(a + bs > e) bs = arena->blocksize; if(readpart(arena->part, a, b->data, bs) < 0) fprint(2, "can't copy %s, read at %lld failed: %r\n", arena->name, a); if(write(1, b->data, bs) != bs) sysfatal("can't copy %s, write at %lld failed: %r", arena->name, a); } freezblock(b); }
int loadbloom(Bloom *b) { int i, n; uint ones; uchar *data; u32int *a; data = vtmallocz(b->size); if(readpart(b->part, 0, data, b->size) < 0){ vtfree(b); vtfree(data); return -1; } b->data = data; a = (u32int*)b->data; n = b->size/4; ones = 0; for(i=0; i<n; i++) ones += countbits(a[i]); addstat(StatBloomOnes, ones); if(b->size == MaxBloomSize) /* 2^32 overflows ulong */ addstat(StatBloomBits, b->size*8-1); else addstat(StatBloomBits, b->size*8); return 0; }
ISect* initisect(Part *part) { ISect *is; ZBlock *b; int ok; b = alloczblock(HeadSize, 0, 0); if(b == nil || readpart(part, PartBlank, b->data, HeadSize) < 0){ seterr(EAdmin, "can't read index section header: %r"); return nil; } is = MKZ(ISect); if(is == nil){ freezblock(b); return nil; } is->part = part; ok = unpackisect(is, b->data); freezblock(b); if(ok < 0){ seterr(ECorrupt, "corrupted index section header: %r"); freeisect(is); return nil; } if(is->version != ISectVersion1 && is->version != ISectVersion2){ seterr(EAdmin, "unknown index section version %d", is->version); freeisect(is); return nil; } return initisect1(is); }
/* * Read in the len bytes of data at the offset. If can't for whatever reason, * fill it with garbage but print an error. */ static uchar* readdisk(uchar *buf, vlong offset, int len) { int i, j, k, n; if(offset >= partend){ memset(buf, 0xFB, len); return buf; } if(offset+len > partend){ memset(buf, 0xFB, len); len = partend - offset; } if(readpart(part, offset, buf, len) >= 0) return buf; /* * The read failed. Clear the buffer to nonsense, and * then try reading in smaller pieces. If that fails, * read in even smaller pieces. And so on down to sectors. */ memset(buf, 0xFD, len); for(i=0; i<len; i+=64*K){ n = 64*K; if(i+n > len) n = len-i; if(readpart(part, offset+i, buf+i, n) >= 0) continue; for(j=i; j<len && j<i+64*K; j+=4*K){ n = 4*K; if(j+n > len) n = len-j; if(readpart(part, offset+j, buf+j, n) >= 0) continue; for(k=j; k<len && k<j+4*K; k+=512){ if(readpart(part, offset+k, buf+k, 512) >= 0) continue; bad("disk read failed at", k, 512); badreads++; } } } bad(nil, 0, 0); return buf; }
static int diskarenatoc(HConnect *c, Arena *arena) { uchar *blk; int i; vlong off; vlong coff; ClumpInfo ci; char base[512]; int cib; snprint(base, sizeof base, "/disk?disk=%s&type=a&arena=%s", arena->part->name, arena->name); blk = vtmalloc(arena->blocksize); off = arena->base + arena->size; hprint(&c->hout, "<h2>table of contents</h2>\n"); hprint(&c->hout, "<pre>\n"); hprint(&c->hout, "%5s %6s %7s %s\n", "type", "size", "uncsize", "score"); coff = 0; cib = hargint(c, "cib", 0); for(i=0; i<arena->memstats.clumps; i++){ if(i%arena->clumpmax == 0){ off -= arena->blocksize; if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){ hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n", off); i += arena->clumpmax-1; coff = -1; continue; } } unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize); if(i/arena->clumpmax == cib || i%arena->clumpmax == 0){ hprint(&c->hout, "%5d %6d %7d %V", ci.type, ci.size, ci.uncsize, ci.score); if(coff >= 0) hprint(&c->hout, " at <a href=\"%s&clump=%#llx&score=%V\">%#llx</a>", base, coff, ci.score, coff); if(i/arena->clumpmax != cib) hprint(&c->hout, " <font size=-1><a href=\"%s&cib=%d\">more</a></font>", base, i/arena->clumpmax); hprint(&c->hout, "\n"); } if(coff >= 0) coff += ClumpSize + ci.size; } hprint(&c->hout, "</pre>\n"); return 0; }
static char* readap(Part *p, ArenaPart *ap) { uchar *blk; char *table; blk = vtmalloc(8192); if(readpart(p, PartBlank, blk, 8192) != 8192) return nil; if(unpackarenapart(ap, blk) < 0){ werrstr("corrupt arena part header: %r"); return nil; } vtfree(blk); ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1); ap->tabsize = ap->arenabase - ap->tabbase; table = vtmalloc(ap->tabsize+1); if(readpart(p, ap->tabbase, (uchar*)table, ap->tabsize) != ap->tabsize){ werrstr("reading arena part directory: %r"); return nil; } table[ap->tabsize] = 0; return table; }
int partifile(IFile *f, Part *part, u64int start, u32int size) { ZBlock *b; b = alloczblock(size, 0, part->blocksize); if(b == nil) return -1; if(readpart(part, start, b->data, size) < 0){ seterr(EAdmin, "can't read %s: %r", part->name); freezblock(b); return -1; } f->name = part->name; f->b = b; f->pos = 0; return 0; }
void dumpisect(ISect *is) { int j; uchar *buf; u32int i; u64int off; IBucket ib; IEntry ie; buf = emalloc(is->blocksize); for(i=0; i<is->blocks; i++){ off = is->blockbase+(u64int)is->blocksize*i; if(readpart(is->part, off, buf, is->blocksize) < 0) fprint(2, "read %s at 0x%llux: %r\n", is->part->name, off); else{ unpackibucket(&ib, buf, is->bucketmagic); for(j=0; j<ib.n; j++){ unpackientry(&ie, &ib.data[j*IEntrySize]); pie(&ie); } } } }
void load_Files(void){ int i; int errorcode; // show_glui_alert(); for(i=0;i<nplot3dinfo;i++){ plot3ddata *plot3di; plot3di = plot3dinfo + i; if(plot3di->autoload==0&&plot3di->loaded==1){ readplot3d(plot3di->file,i,UNLOAD,&errorcode); } if(plot3di->autoload==1){ ReadPlot3dFile=1; readplot3d(plot3di->file,i,LOAD,&errorcode); } } npartframes_max=get_min_partframes(); for(i=0;i<npartinfo;i++){ partdata *parti; parti = partinfo + i; if(parti->autoload==0&&parti->loaded==1)readpart(parti->file,i,UNLOAD,&errorcode); if(parti->autoload==1)readpart(parti->file,i,UNLOAD,&errorcode); } for(i=0;i<npartinfo;i++){ partdata *parti; parti = partinfo + i; if(parti->autoload==0&&parti->loaded==1)readpart(parti->file,i,UNLOAD,&errorcode); if(parti->autoload==1)readpart(parti->file,i,LOAD,&errorcode); } update_readiso_geom_wrapup == UPDATE_ISO_START_ALL; for(i = 0; i<nisoinfo; i++){ isodata *isoi; isoi = isoinfo + i; if(isoi->autoload==0&&isoi->autoload==1)readiso(isoi->file,i,UNLOAD,&errorcode); if(isoi->autoload == 1){ readiso(isoi->file, i, LOAD, &errorcode); } } if(update_readiso_geom_wrapup == UPDATE_ISO_ALL_NOW)readiso_geom_wrapup(); update_readiso_geom_wrapup = UPDATE_ISO_OFF; for(i = 0; i<nvsliceinfo; i++){ vslicedata *vslicei; vslicei = vsliceinfo + i; if(vslicei->autoload==0&&vslicei->loaded==1)readvslice(i,UNLOAD,&errorcode); if(vslicei->autoload==1){ readvslice(i,LOAD,&errorcode); } } // note: only slices that are NOT a part of a vector slice will be loaded here for(i=0;i<nsliceinfo;i++){ slicedata *slicei; slicei = sliceinfo + i; if(slicei->autoload==0&&slicei->loaded==1)readslice(slicei->file,i,UNLOAD,&errorcode); if(slicei->autoload==1&&slicei->loaded==0){ readslice(slicei->file,i,LOAD,&errorcode); } } for(i=0;i<nterraininfo;i++){ terraindata *terri; terri = terraininfo + i; if(terri->autoload==0&&terri->loaded==1)readterrain(terri->file,i,UNLOAD,&errorcode); if(terri->autoload==1&&terri->loaded==0)readslice(terri->file,i,LOAD,&errorcode); } for(i=0;i<nsmoke3dinfo;i++){ smoke3ddata *smoke3di; smoke3di = smoke3dinfo + i; if(smoke3di->autoload==0&&smoke3di->loaded==1)readsmoke3d(i,UNLOAD,&errorcode); if(smoke3di->autoload==1)readsmoke3d(i,LOAD,&errorcode); } for(i=0;i<npatchinfo;i++){ patchdata *patchi; patchi = patchinfo + i; if(patchi->autoload==0&&patchi->loaded==1)readpatch(i,UNLOAD,&errorcode); if(patchi->autoload==1)readpatch(i,LOAD,&errorcode); } force_redisplay=1; Update_Framenumber(0); updatemenu=1; update_load_Files=0; hide_glui_alert(); TrainerViewMenu(trainerview); }
void sumarena(Arena *arena) { ZBlock *b; DigestState s; uint64_t a, e; uint32_t bs; int t; uint8_t score[VtScoreSize]; bs = MaxIoSize; if(bs < arena->blocksize) bs = arena->blocksize; /* * read & sum all blocks except the last one */ flushdcache(); memset(&s, 0, sizeof s); b = alloczblock(bs, 0, arena->part->blocksize); e = arena->base + arena->size; for(a = arena->base - arena->blocksize; a + arena->blocksize <= e; a += bs){ disksched(); while((t=arenasumsleeptime) == SleepForever){ sleep(1000); disksched(); } sleep(t); if(a + bs > e) bs = arena->blocksize; if(readpart(arena->part, a, b->data, bs) < 0) goto ReadErr; addstat(StatSumRead, 1); addstat(StatSumReadBytes, bs); sha1(b->data, bs, nil, &s); } /* * the last one is special, since it may already have the checksum included */ bs = arena->blocksize; if(readpart(arena->part, e, b->data, bs) < 0){ ReadErr: logerr(EOk, "sumarena can't sum %s, read at %lld failed: %r", arena->name, a); freezblock(b); return; } addstat(StatSumRead, 1); addstat(StatSumReadBytes, bs); sha1(b->data, bs-VtScoreSize, nil, &s); sha1(zeroscore, VtScoreSize, nil, &s); sha1(nil, 0, score, &s); /* * check for no checksum or the same */ if(scorecmp(score, &b->data[bs - VtScoreSize]) != 0 && scorecmp(zeroscore, &b->data[bs - VtScoreSize]) != 0) logerr(EOk, "overwriting mismatched checksums for arena=%s, found=%V calculated=%V", arena->name, &b->data[bs - VtScoreSize], score); freezblock(b); qlock(&arena->lock); scorecp(arena->score, score); wbarena(arena); qunlock(&arena->lock); }
int readifile(IFile *f, char *name) { Part *p; ZBlock *b; u8int *z; p = initpart(name, OREAD); if(p == nil) return -1; b = alloczblock(Maxconfig+1, 1, 0); if(b == nil){ seterr(EOk, "can't alloc for %s: %R", name); return -1; } if(p->size > PartBlank){ /* * this is likely a real venti partition, in which case we're * looking for the config file stored as 8k at end of PartBlank. */ if(readpart(p, PartBlank-Maxconfig, b->data, Maxconfig) < 0){ seterr(EOk, "can't read %s: %r", name); freezblock(b); freepart(p); return -1; } b->data[Maxconfig] = '\0'; if(memcmp(b->data, vcmagic, Maglen) != 0){ seterr(EOk, "bad venti config magic in %s", name); freezblock(b); freepart(p); return -1; } /* * if we change b->data+b->_size, freezblock * will blow an assertion, so don't. */ b->data += Maglen; b->_size -= Maglen; b->len -= Maglen; z = memchr(b->data, '\0', b->len); if(z) b->len = z - b->data; }else if(p->size > Maxconfig){ seterr(EOk, "config file is too large"); freepart(p); freezblock(b); return -1; }else{ freezblock(b); b = readfile(name); if(b == nil){ freepart(p); return -1; } } freepart(p); f->name = name; f->b = b; f->pos = 0; return 0; }
static int icachewritesect(Index *ix, ISect *is, u8int *buf) { int err, i, werr, h, bsize, t; u32int lo, hi; u64int addr, naddr; uint nbuf, off; DBlock *b; IBucket ib; IEntry *ie, *iedirty, **l, *chunk; lo = is->start * ix->div; if(TWID32/ix->div < is->stop) hi = TWID32; else hi = is->stop * ix->div - 1; trace(TraceProc, "icachewritesect enter %ud %ud %llud", lo, hi, iwrite.as.aa); iedirty = icachedirty(lo, hi, iwrite.as.aa); iedirty = iesort(iedirty); bsize = 1 << is->blocklog; err = 0; while(iedirty){ disksched(); while((t = icachesleeptime) == SleepForever){ sleep(1000); disksched(); } if(t < minicachesleeptime) t = minicachesleeptime; if(t > 0) sleep(t); trace(TraceProc, "icachewritesect nextchunk"); chunk = nextchunk(ix, is, &iedirty, &addr, &nbuf); trace(TraceProc, "icachewritesect readpart 0x%llux+0x%ux", addr, nbuf); if(readpart(is->part, addr, buf, nbuf) < 0){ fprint(2, "%s: part %s addr 0x%llux: icachewritesect " "readpart: %r\n", argv0, is->part->name, addr); err = -1; continue; } trace(TraceProc, "icachewritesect updatebuf"); addstat(StatIsectReadBytes, nbuf); addstat(StatIsectRead, 1); for(l=&chunk; (ie=*l)!=nil; l=&ie->nextdirty){ again: naddr = ie2diskaddr(ix, is, ie); off = naddr - addr; if(off+bsize > nbuf){ fprint(2, "%s: whoops! addr=0x%llux nbuf=%ud " "addr+nbuf=0x%llux naddr=0x%llux\n", argv0, addr, nbuf, addr+nbuf, naddr); assert(off+bsize <= nbuf); } unpackibucket(&ib, buf+off, is->bucketmagic); if(okibucket(&ib, is) < 0){ fprint(2, "%s: bad bucket XXX\n", argv0); goto skipit; } trace(TraceProc, "icachewritesect add %V at 0x%llux", ie->score, naddr); h = bucklook(ie->score, ie->ia.type, ib.data, ib.n); if(h & 1){ h ^= 1; packientry(ie, &ib.data[h]); }else if(ib.n < is->buckmax){ memmove(&ib.data[h + IEntrySize], &ib.data[h], ib.n*IEntrySize - h); ib.n++; packientry(ie, &ib.data[h]); }else{ fprint(2, "%s: bucket overflow XXX\n", argv0); skipit: err = -1; *l = ie->nextdirty; ie = *l; if(ie) goto again; else break; } packibucket(&ib, buf+off, is->bucketmagic); } diskaccess(1); trace(TraceProc, "icachewritesect writepart", addr, nbuf); werr = 0; if(writepart(is->part, addr, buf, nbuf) < 0 || flushpart(is->part) < 0) werr = -1; for(i=0; i<nbuf; i+=bsize){ if((b = _getdblock(is->part, addr+i, ORDWR, 0)) != nil){ memmove(b->data, buf+i, bsize); putdblock(b); } } if(werr < 0){ fprint(2, "%s: part %s addr 0x%llux: icachewritesect " "writepart: %r\n", argv0, is->part->name, addr); err = -1; continue; } addstat(StatIsectWriteBytes, nbuf); addstat(StatIsectWrite, 1); icacheclean(chunk); } trace(TraceProc, "icachewritesect done"); return err; }
vol_err_t vol_getfilenames(vol_t handle) { struct volume* vhnd = handle; struct vfile *curfile; log_info("Fetching filenames from array."); guint64 os; os = vhnd->footer.filenames.offset; gint i, j = 0, l = 0; vol_err_t err; gchar* datadir; guint8 bite; log_debug("Scraping array header."); for (i=0; i <=4; i++) { err = vol_getheader(handle, &vhnd->footer.filenames.header, vhnd->footer.filenames.offset + i); if (err) return err; /* Header verification * There might be a memory leak here */ if (memcmp("vols", vhnd->footer.filenames.header.ident, 4)) { log_debug("Retrieved IDstring does not matched needed IDstring."); err = VOL_ERR_BADHEADER; } else { vhnd->footer.filenames.offset += i; err = VOL_ERR_OK; break; } } if (err == VOL_ERR_BADHEADER) { log_critical("Array identity string not recognized."); return VOL_ERR_BROKEN; } if (vhnd->footer.filenames.header.val != 0) { os+=sizeof(struct header); vhnd->footer.filenames.data = g_ptr_array_new_with_free_func(g_free); vhnd->files = g_ptr_array_new_with_free_func(vol_filesarray_free); log_debug("Fetching array data."); for (i = 0; i < vhnd->footer.filenames.header.val; i++) { if (j == 0) log_debug("Seeking to end of string."); j++; readbyte(&vhnd->volio, (guint64)(os+j), &bite); if (bite == 0x00) { j++; log_debug("String at offset 0x%lx indexed. Size is %d. Pulling now.", os, j); gchar *data, *sanitary, *pathcopy1, *pathcopy2; curfile = (struct vfile*)g_malloc(sizeof(struct vfile)); curfile->vol = vhnd; curfile->data.data = NULL; data = readpart(&vhnd->volio, (guint64)os, sizeof(gchar)*j); sanitary = sanitizepath(data); log_debug("Pulled string: %s.", data); i++; os+=j; j=0; log_debug("Adding string to arrays."); pathcopy1 = g_strdup(sanitary); pathcopy2 = g_strdup(sanitary); g_ptr_array_add(vhnd->footer.filenames.data, (gpointer)data); curfile->path = g_strdup(data); curfile->path_canonical = sanitary; curfile->name = g_strdup(basename(pathcopy1)); curfile->dir = g_strdup(dirname(pathcopy2)); g_free(pathcopy1); g_free(pathcopy2); g_ptr_array_add(vhnd->files, (gpointer)curfile); l++; } else if (bite == 0x5C) { log_todo("Warn windows users about invalid characters and forward slashes"); log_warning("An internal path string may contain backslashes."); } } struct counter* k; k = g_malloc0(sizeof(struct counter)); k->count = 0; log_info("File arrays created."); g_ptr_array_foreach(vhnd->files, printfiles, (gpointer)k); g_free(k); } else { log_message("Array is empty. (No files in volume?)"); vhnd->footer.filenames.data = NULL; } vhnd->footer.fileprops.offset = vhnd->footer.filenames.header.val +vhnd->footer.filenames.offset+sizeof(struct header); return err; }
static int diskarenaclump(HConnect *c, Arena *arena, vlong off, char *scorestr) { uchar *blk, *blk2; Clump cl; char err[ERRMAX]; uchar xscore[VtScoreSize], score[VtScoreSize]; Unwhack uw; int n; if(scorestr){ if(vtparsescore(scorestr, nil, score) < 0){ hprint(&c->hout, "bad score %s: %r\n", scorestr); return -1; } if(off < 0){ off = findintoc(c, arena, score); if(off < 0){ hprint(&c->hout, "score %V not found in arena %s\n", score, arena->name); return -1; } hprint(&c->hout, "score %V at %#llx\n", score, off); } }else memset(score, 0, sizeof score); if(off < 0){ hprint(&c->hout, "bad offset %#llx\n", off); return -1; } off += arena->base; blk = vtmalloc(ClumpSize + VtMaxLumpSize); if(readpart(arena->part, off, blk, ClumpSize + VtMaxLumpSize) != ClumpSize + VtMaxLumpSize){ hprint(&c->hout, "reading at %#llx: %r\n", off); vtfree(blk); return -1; } if(unpackclump(&cl, blk, arena->clumpmagic) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>"); rerrstr(err, sizeof err); if(strstr(err, "magic")){ hprint(&c->hout, "trying again with magic=%#ux<br>\n", U32GET(blk)); if(unpackclump(&cl, blk, U32GET(blk)) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>\n"); goto error; } }else goto error; } hprint(&c->hout, "<pre>type=%d size=%d uncsize=%d score=%V\n", cl.info.type, cl.info.size, cl.info.uncsize, cl.info.score); hprint(&c->hout, "encoding=%d creator=%d time=%d %s</pre>\n", cl.encoding, cl.creator, cl.time, fmttime(err, cl.time)); if(cl.info.type == VtCorruptType) hprint(&c->hout, "clump is marked corrupt<br>\n"); if(cl.info.size >= VtMaxLumpSize){ hprint(&c->hout, "clump too big\n"); goto error; } switch(cl.encoding){ case ClumpECompress: blk2 = vtmalloc(VtMaxLumpSize); unwhackinit(&uw); n = unwhack(&uw, blk2, cl.info.uncsize, blk+ClumpSize, cl.info.size); if(n < 0){ hprint(&c->hout, "decompression failed\n"); vtfree(blk2); goto error; } if(n != cl.info.uncsize){ hprint(&c->hout, "got wrong amount: %d wanted %d\n", n, cl.info.uncsize); // hhex(blk2, n); vtfree(blk2); goto error; } scoremem(xscore, blk2, cl.info.uncsize); vtfree(blk2); break; case ClumpENone: scoremem(xscore, blk+ClumpSize, cl.info.size); break; } hprint(&c->hout, "score=%V<br>\n", xscore); if(scorestr && scorecmp(score, xscore) != 0) hprint(&c->hout, "score does NOT match expected %V\n", score); vtfree(blk); return 0; error: // hhex(blk, ClumpSize + VtMaxLumpSize); vtfree(blk); return -1; }
void threadmain(int argc, char *argv[]) { int i; char *file; Arena *arena; u64int offset, aoffset; Part *part; uchar buf[8192]; ArenaHead head; ZClump zerocl; ventifmtinstall(); qlock(&godot); aoffset = 0; ARGBEGIN{ case 'f': fast = 1; ventidoublechecksha1 = 0; break; case 'h': host = EARGF(usage()); break; case 'o': haveaoffset = 1; aoffset = strtoull(EARGF(usage()), 0, 0); break; case 'M': maxwrites = atoi(EARGF(usage())); break; case 'v': verbose = 1; break; default: usage(); break; }ARGEND offset = ~(u64int)0; switch(argc) { default: usage(); case 2: offset = strtoull(argv[1], 0, 0); /* fall through */ case 1: file = argv[0]; } fmtinstall('V', vtscorefmt); statsinit(); part = initpart(file, OREAD); if(part == nil) sysfatal("can't open file %s: %r", file); if(readpart(part, aoffset, buf, sizeof buf) < 0) sysfatal("can't read file %s: %r", file); if(unpackarenahead(&head, buf) < 0) sysfatal("corrupted arena header: %r"); if(aoffset+head.size > part->size) sysfatal("arena is truncated: want %llud bytes have %llud", head.size, part->size); partblocksize(part, head.blocksize); initdcache(8 * MaxDiskBlock); arena = initarena(part, aoffset, head.size, head.blocksize); if(arena == nil) sysfatal("initarena: %r"); z = nil; if(host==nil || strcmp(host, "/dev/null") != 0){ z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); } c = chancreate(sizeof(ZClump), 0); for(i=0; i<12; i++) vtproc(vtsendthread, nil); rdarena(arena, offset); if(vtsync(z) < 0) sysfatal("executing sync: %r"); memset(&zerocl, 0, sizeof zerocl); for(i=0; i<12; i++) send(c, &zerocl); if(z){ vthangup(z); } threadexitsall(0); }
static int diskarenapart(HConnect *c, char *disk, Part *p) { char *arenaname; ArenaPart ap; ArenaHead head; Arena arena; char *table; char *score; char *clump; uchar *blk; vlong start, end, off; char tbuf[60]; hprint(&c->hout, "<h1>arena partition %s</h1>\n", disk); if((table = readap(p, &ap)) == nil){ hprint(&c->hout, "%r\n"); goto out; } hprint(&c->hout, "<pre>\n"); hprint(&c->hout, "version=%d blocksize=%d base=%d\n", ap.version, ap.blocksize, ap.arenabase); hprint(&c->hout, "</pre>\n"); arenaname = hargstr(c, "arena", ""); if(arenaname[0] == 0){ diskarenatable(c, disk, table); goto out; } if(xfindarena(table, arenaname, &start, &end) < 0){ hprint(&c->hout, "no such arena %s\n", arenaname); goto out; } hprint(&c->hout, "<h2>arena %s</h2>\n", arenaname); hprint(&c->hout, "<pre>start=%#llx end=%#llx<pre>\n", start, end); if(end < start || end - start < HeadSize){ hprint(&c->hout, "bad size %#llx\n", end - start); goto out; } // read arena header, tail blk = vtmalloc(HeadSize); if(readpart(p, start, blk, HeadSize) != HeadSize){ hprint(&c->hout, "reading header: %r\n"); vtfree(blk); goto out; } if(unpackarenahead(&head, blk) < 0){ hprint(&c->hout, "corrupt arena header: %r\n"); // hhex(blk, HeadSize); vtfree(blk); goto out; } vtfree(blk); hprint(&c->hout, "head:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s blocksize=%d size=%#llx clumpmagic=%#ux\n", head.version, head.name, head.blocksize, head.size, head.clumpmagic); hprint(&c->hout, "</pre><br><br>\n"); if(head.blocksize > MaxIoSize || head.blocksize >= end - start){ hprint(&c->hout, "corrupt block size %d\n", head.blocksize); goto out; } blk = vtmalloc(head.blocksize); if(readpart(p, end - head.blocksize, blk, head.blocksize) < 0){ hprint(&c->hout, "reading tail: %r\n"); vtfree(blk); goto out; } memset(&arena, 0, sizeof arena); arena.part = p; arena.blocksize = head.blocksize; arena.clumpmax = head.blocksize / ClumpInfoSize; arena.base = start + head.blocksize; arena.size = end - start - 2 * head.blocksize; if(unpackarena(&arena, blk) < 0){ vtfree(blk); goto out; } scorecp(arena.score, blk+head.blocksize - VtScoreSize); vtfree(blk); hprint(&c->hout, "tail:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s\n", arena.version, arena.name); hprint(&c->hout, "ctime=%d %s\n", arena.ctime, fmttime(tbuf, arena.ctime)); hprint(&c->hout, "wtime=%d %s\n", arena.wtime, fmttime(tbuf, arena.wtime)); hprint(&c->hout, "clumpmagic=%#ux\n", arena.clumpmagic); hprint(&c->hout, "score %V\n", arena.score); hprint(&c->hout, "diskstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.diskstats.clumps, arena.diskstats.cclumps, arena.diskstats.used, arena.diskstats.uncsize, arena.diskstats.sealed); hprint(&c->hout, "memstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.memstats.clumps, arena.memstats.cclumps, arena.memstats.used, arena.memstats.uncsize, arena.memstats.sealed); if(arena.clumpmax == 0){ hprint(&c->hout, "bad clumpmax\n"); goto out; } score = hargstr(c, "score", ""); clump = hargstr(c, "clump", ""); if(clump[0]){ off = strtoull(clump, 0, 0); diskarenaclump(c, &arena, off, score[0] ? score : nil); }else if(score[0]){ diskarenaclump(c, &arena, -1, score); }else{ diskarenatoc(c, &arena); } out: free(table); return 0; }