void run(void (*fn)(char*, char*), Channel *c) { int i, t, j, packets; char *buf2, *buf; buf2 = vtmalloc(blocksize); buf = vtmalloc(blocksize); cur = 0; packets = totalbytes/blocksize; if(maxpackets == 0) maxpackets = packets; order = vtmalloc(packets*sizeof order[0]); for(i=0; i<packets; i++) order[i] = i; if(permute){ for(i=1; i<packets; i++){ j = nrand(i+1); t = order[i]; order[i] = order[j]; order[j] = t; } } for(i=0; i<packets && i<maxpackets; i++){ memmove(buf, template, blocksize);
/* * load clump info group information by scanning entire toc. */ static void loadcig(Arena *arena) { uint32_t i, j, ncig, nci; ArenaCIG *cig; ClumpInfo *ci; uint64_t offset; int ms; if(arena->cig || arena->ncig < 0) return; // fprint(2, "loadcig %s\n", arena->name); ncig = (arena->memstats.clumps+ArenaCIGSize-1) / ArenaCIGSize; if(ncig == 0){ arena->cig = vtmalloc(1); arena->ncig = 0; return; } ms = msec(); cig = vtmalloc(ncig*sizeof cig[0]); ci = vtmalloc(ArenaCIGSize*sizeof ci[0]); offset = 0; for(i=0; i<ncig; i++){ nci = readclumpinfos(arena, i*ArenaCIGSize, ci, ArenaCIGSize); cig[i].offset = offset; for(j=0; j<nci; j++) offset += ClumpSize + ci[j].size; if(nci < ArenaCIGSize){ if(i != ncig-1){ vtfree(ci); vtfree(cig); arena->ncig = -1; fprint(2, "loadcig %s: got %ud cigs, expected %ud\n", arena->name, i+1, ncig); goto out; } } } vtfree(ci); arena->ncig = ncig; arena->cig = cig; out: ms = msec() - ms; addstat2(StatCigLoad, 1, StatCigLoadTime, ms); }
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; }
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 = vtmalloc(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]); } vtfree(kids); return rv; }
VtLog* vtlogopen(char *name, uint size) { uint h; int i, nc; char *p; VtLog *l, *last; if(!ventilogging) return nil; h = hash(name)%nelem(vl.hash); qlock(&vl.lk); last = nil; for(l=vl.hash[h]; l; last=l, l=l->next) if(strcmp(l->name, name) == 0){ if(last){ /* move to front */ last->next = l->next; l->next = vl.hash[h]; vl.hash[h] = l; } l->ref++; qunlock(&vl.lk); return l; } if(size == 0){ qunlock(&vl.lk); return nil; } /* allocate */ nc = (size+LogChunkSize-1)/LogChunkSize; l = vtmalloc(sizeof *l + nc*(sizeof(*l->chunk)+LogChunkSize) + strlen(name)+1); memset(l, 0, sizeof *l); l->chunk = (VtLogChunk*)(l+1); l->nchunk = nc; l->w = l->chunk; p = (char*)(l->chunk+nc); for(i=0; i<nc; i++){ l->chunk[i].p = p; l->chunk[i].wp = p; p += LogChunkSize; l->chunk[i].ep = p; } strcpy(p, name); l->name = p; /* insert */ l->next = vl.hash[h]; vl.hash[h] = l; l->ref++; l->ref++; qunlock(&vl.lk); return l; }
void rdthread(void *v) { char *p, *buf2; buf2 = vtmalloc(blocksize); USED(v); while((p = recvp(cr)) != nil){ rd(p, buf2); free(p); } }
char* vtstrdup(char *s) { int n; char *ss; if(s == nil) return nil; n = strlen(s) + 1; ss = vtmalloc(n); memmove(ss, s, n); return ss; }
static int deeFill(DirEntryEnum *dee) { int i, n; Source *meta, *source; MetaBlock mb; MetaEntry me; File *f; Block *b; DirEntry *de; /* clean up first */ for(i=dee->i; i<dee->n; i++) deCleanup(dee->buf+i); vtfree(dee->buf); dee->buf = nil; dee->i = 0; dee->n = 0; f = dee->file; source = f->source; meta = f->msource; b = sourceBlock(meta, dee->boff, OReadOnly); if(b == nil) goto Err; if(!mbUnpack(&mb, b->data, meta->dsize)) goto Err; n = mb.nindex; dee->buf = vtmalloc(n * sizeof(DirEntry)); for(i=0; i<n; i++){ de = dee->buf + i; meUnpack(&me, &mb, i); if(!deUnpack(de, &me)) goto Err; dee->n++; if(!(de->mode & ModeDir)) if(!dirEntrySize(source, de->entry, de->gen, &de->size)) goto Err; } dee->boff++; blockPut(b); return 1; Err: blockPut(b); return 0; }
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; }
/* * Archive the file named name, which has stat info d, * into the vac directory fp (p = parent). * * If we're doing a vac -d against another archive, the * equivalent directory to fp in that archive is diffp. */ void vac(VacFile *fp, VacFile *diffp, char *name, Dir *d) { char *elem, *s; static char buf[65536]; int fd, i, n, bsize; int64_t off; Dir *dk; // kids VacDir vd, vddiff; VacFile *f, *fdiff; VtEntry e; if(!includefile(name)){ warn("excluding %s%s", name, (d->mode&DMDIR) ? "/" : ""); return; } if(d->mode&DMDIR) stats.ndir++; else stats.nfile++; if(merge && vacmerge(fp, name) >= 0) return; if(verbose) fprint(2, "%s%s\n", name, (d->mode&DMDIR) ? "/" : ""); if((fd = open(name, OREAD)) < 0){ warn("open %s: %r", name); return; } elem = strrchr(name, '/'); if(elem) elem++; else elem = name; plan9tovacdir(&vd, d); if((f = vacfilecreate(fp, elem, vd.mode)) == nil){ warn("vacfilecreate %s: %r", name); return; } if(diffp) fdiff = vacfilewalk(diffp, elem); else fdiff = nil; if(vacfilesetdir(f, &vd) < 0) warn("vacfilesetdir %s: %r", name); if(d->mode&DMDIR){ while((n = dirread(fd, &dk)) > 0){ for(i=0; i<n; i++){ s = vtmalloc(strlen(name)+1+strlen(dk[i].name)+1); strcpy(s, name); strcat(s, "/"); strcat(s, dk[i].name); vac(f, fdiff, s, &dk[i]); free(s); } free(dk); } }else{ off = 0; bsize = fs->bsize; if(fdiff){ /* * Copy fdiff's contents into f by moving the score. * We'll diff and update below. */ if(vacfilegetentries(fdiff, &e, nil) >= 0) if(vacfilesetentries(f, &e, nil) >= 0){ bsize = e.dsize; /* * Or if -q is set, and the metadata looks the same, * don't even bother reading the file. */ if(qdiff && vacfilegetdir(fdiff, &vddiff) >= 0){ if(vddiff.mtime == vd.mtime) if(vddiff.size == vd.size) if(!vddiff.plan9 || (/* vddiff.p9path == vd.p9path && */ vddiff.p9version == vd.p9version)){ stats.skipfiles++; stats.nfile--; vdcleanup(&vddiff); goto Out; } /* * Skip over presumably-unchanged prefix * of an append-only file. */ if(vd.mode&ModeAppend) if(vddiff.size < vd.size) if(vddiff.plan9 && vd.plan9) if(vddiff.p9path == vd.p9path){ off = vd.size/bsize*bsize; if(seek(fd, off, 0) >= 0) stats.skipdata += off; else{ seek(fd, 0, 0); // paranoia off = 0; } } vdcleanup(&vddiff); // XXX different verbose chatty prints for kaminsky? } } } if(qdiff && verbose) fprint(2, "+%s\n", name); while((n = readn(fd, buf, bsize)) > 0){ if(fdiff && sha1matches(f, off/bsize, (uint8_t*)buf, n)){ off += n; stats.skipdata += n; continue; } if(vacfilewrite(f, buf, n, off) < 0){ warn("venti write %s: %r", name); goto Out; } stats.data += n; off += n; } /* * Since we started with fdiff's contents, * set the size in case fdiff was bigger. */ if(fdiff && vacfilesetsize(f, off) < 0) warn("vtfilesetsize %s: %r", name); } Out: vacfileflush(f, 1); vacfiledecref(f); if(fdiff) vacfiledecref(fdiff); close(fd); }
void threadmain(int argc, char **argv) { int i, j, fd, n, printstats; Dir *d; char *s; uint64_t u; VacFile *f, *fdiff; VacFs *fsdiff; int blocksize; int outfd; char *stdinname; char *diffvac; uint64_t qid; fmtinstall('F', vtfcallfmt); fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); blocksize = BlockSize; stdinname = nil; printstats = 0; fsdiff = nil; diffvac = nil; ARGBEGIN{ case 'V': chattyventi++; break; case 'a': archivefile = EARGF(usage()); break; case 'b': u = unittoull(EARGF(usage())); if(u < 512) u = 512; if(u > VtMaxLumpSize) u = VtMaxLumpSize; blocksize = u; break; case 'd': diffvac = EARGF(usage()); break; case 'e': excludepattern(EARGF(usage())); break; case 'f': vacfile = EARGF(usage()); break; case 'h': host = EARGF(usage()); break; case 'i': stdinname = EARGF(usage()); break; case 'm': merge++; break; case 'q': qdiff++; break; case 's': printstats++; break; case 'v': verbose++; break; case 'x': loadexcludefile(EARGF(usage())); break; default: usage(); }ARGEND if(argc == 0 && !stdinname) usage(); if(archivefile && (vacfile || diffvac)){ fprint(2, "cannot use -a with -f, -d\n"); usage(); } z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); // Setup: // fs is the output vac file system // f is directory in output vac to write new files // fdiff is corresponding directory in existing vac if(archivefile){ VacFile *fp; char yyyy[5]; char mmdd[10]; char oldpath[40]; Tm tm; fdiff = nil; if((outfd = open(archivefile, ORDWR)) < 0){ if(access(archivefile, 0) >= 0) sysfatal("open %s: %r", archivefile); if((outfd = create(archivefile, OWRITE, 0666)) < 0) sysfatal("create %s: %r", archivefile); atexit(removevacfile); // because it is new if((fs = vacfscreate(z, blocksize, 512)) == nil) sysfatal("vacfscreate: %r"); }else{ if((fs = vacfsopen(z, archivefile, VtORDWR, 512)) == nil) sysfatal("vacfsopen %s: %r", archivefile); if((fdiff = recentarchive(fs, oldpath)) != nil){ if(verbose) fprint(2, "diff %s\n", oldpath); }else if(verbose) fprint(2, "no recent archive to diff against\n"); } // Create yyyy/mmdd. tm = *localtime(time(0)); snprint(yyyy, sizeof yyyy, "%04d", tm.year+1900); fp = vacfsgetroot(fs); if((f = vacfilewalk(fp, yyyy)) == nil && (f = vacfilecreate(fp, yyyy, ModeDir|0555)) == nil) sysfatal("vacfscreate %s: %r", yyyy); vacfiledecref(fp); fp = f; snprint(mmdd, sizeof mmdd, "%02d%02d", tm.mon+1, tm.mday); n = 0; while((f = vacfilewalk(fp, mmdd)) != nil){ vacfiledecref(f); n++; snprint(mmdd+4, sizeof mmdd-4, ".%d", n); } f = vacfilecreate(fp, mmdd, ModeDir|0555); if(f == nil) sysfatal("vacfscreate %s/%s: %r", yyyy, mmdd); vacfiledecref(fp); if(verbose) fprint(2, "archive %s/%s\n", yyyy, mmdd); }else{ if(vacfile == nil) outfd = 1; else if((outfd = create(vacfile, OWRITE, 0666)) < 0) sysfatal("create %s: %r", vacfile); atexit(removevacfile); if((fs = vacfscreate(z, blocksize, 512)) == nil) sysfatal("vacfscreate: %r"); f = vacfsgetroot(fs); fdiff = nil; if(diffvac){ if((fsdiff = vacfsopen(z, diffvac, VtOREAD, 128)) == nil) warn("vacfsopen %s: %r", diffvac); else fdiff = vacfsgetroot(fsdiff); } } if(stdinname) vacstdin(f, stdinname); for(i=0; i<argc; i++){ // We can't use / and . and .. and ../.. as valid archive // names, so expand to the list of files in the directory. if(argv[i][0] == 0){ warn("empty string given as command-line argument"); continue; } cleanname(argv[i]); if(strcmp(argv[i], "/") == 0 || strcmp(argv[i], ".") == 0 || strcmp(argv[i], "..") == 0 || (strlen(argv[i]) > 3 && strcmp(argv[i]+strlen(argv[i])-3, "/..") == 0)){ if((fd = open(argv[i], OREAD)) < 0){ warn("open %s: %r", argv[i]); continue; } while((n = dirread(fd, &d)) > 0){ for(j=0; j<n; j++){ s = vtmalloc(strlen(argv[i])+1+strlen(d[j].name)+1); strcpy(s, argv[i]); strcat(s, "/"); strcat(s, d[j].name); cleanname(s); vac(f, fdiff, s, &d[j]); } free(d); } close(fd); continue; } if((d = dirstat(argv[i])) == nil){ warn("stat %s: %r", argv[i]); continue; } vac(f, fdiff, argv[i], d); free(d); } if(fdiff) vacfiledecref(fdiff); /* * Record the maximum qid so that vacs can be merged * without introducing overlapping qids. Older versions * of vac arranged that the root would have the largest * qid in the file system, but we can't do that anymore * (the root gets created first!). */ if(_vacfsnextqid(fs, &qid) >= 0) vacfilesetqidspace(f, 0, qid); vacfiledecref(f); /* * Copy fsdiff's root block score into fs's slot for that, * so that vacfssync will copy it into root.prev for us. * Just nice documentation, no effect. */ if(fsdiff) memmove(fs->score, fsdiff->score, VtScoreSize); if(vacfssync(fs) < 0) fprint(2, "vacfssync: %r\n"); fprint(outfd, "vac:%V\n", fs->score); atexitdont(removevacfile); vacfsclose(fs); vthangup(z); if(printstats){ fprint(2, "%d files, %d files skipped, %d directories\n" "%lld data bytes written, %lld data bytes skipped\n", stats.nfile, stats.skipfiles, stats.ndir, stats.data, stats.skipdata); dup(2, 1); packetstats(); } threadexitsall(0); }
void threadmain(int argc, char **argv) { int i; int nofork; char *prog; Job *j; ventilogging = 1; ventifmtinstall(); #ifdef PLAN9PORT bin = unsharp("#9/bin/venti"); #else bin = "/bin/venti"; #endif nofork = 0; ARGBEGIN{ case 'b': bin = EARGF(usage()); break; case 's': nofork = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); if(rdconf(argv[0], &conf) < 0) sysfatal("reading config: %r"); if(conf.httpaddr == nil) sysfatal("config has no httpaddr"); if(conf.smtp != nil && conf.mailfrom == nil) sysfatal("config has smtp but no mailfrom"); if(conf.smtp != nil && conf.mailto == nil) sysfatal("config has smtp but no mailto"); if((mirrorprog = regcomp(mirrorregexp)) == nil) sysfatal("mirrorregexp did not complete"); if((verifyprog = regcomp(verifyregexp)) == nil) sysfatal("verifyregexp did not complete"); if(conf.nverify > 0 && conf.verifyfreq == 0) sysfatal("config has no verifyfreq"); if(conf.nmirror > 0 && conf.mirrorfreq == 0) sysfatal("config has no mirrorfreq"); time0 = time(0); // sendmail("startup", "mgr is starting\n"); logbuf = vtmalloc(LogSize+1); // +1 for NUL errlog = vtlogopen("errors", LogSize); job = vtmalloc((conf.nmirror+conf.nverify)*sizeof job[0]); prog = smprint("%s/mirrorarenas", bin); for(i=0; i<conf.nmirror; i++) { // job: /bin/venti/mirrorarenas -v src dst // filter output j = &job[njob++]; mkjob(j, prog, "-v", conf.mirror[i].src, conf.mirror[i].dst, nil); j->name = smprint("mirror %s %s", conf.mirror[i].src, conf.mirror[i].dst); j->ok = mirrorok; j->freq = conf.mirrorfreq; // 4 hours // TODO: put in config j->offset = (double)i/conf.nmirror; } prog = smprint("%s/verifyarena", bin); for(i=0; i<conf.nverify; i++) { // job: /bin/venti/verifyarena -b 64M -s 1000 -v arena // filter output j = &job[njob++]; mkjob(j, prog, "-b64M", "-s1000", conf.verify[i], nil); j->name = smprint("verify %s", conf.verify[i]); j->ok = verifyok; j->freq = conf.verifyfreq; j->offset = (double)i/conf.nverify; } httpdobj("/mgr", hmanager); httpdobj("/log", xlog); vtproc(httpdproc, conf.httpaddr); vtproc(waitproc, threadwaitchan()); if(nofork) manager(nil); else vtproc(manager, nil); }
void threadmain(int argc, char *argv[]) { char *defsrv, *srvname; int p[2], fd; int stdio; char *host = nil; ulong mem; mem = 16<<20; stdio = 0; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); defmnt = nil; defsrv = nil; ARGBEGIN{ case 'd': fmtinstall('F', fcallfmt); dflag = 1; break; case 'i': defmnt = nil; stdio = 1; mfd[0] = 0; mfd[1] = 1; break; case 'h': host = EARGF(usage()); break; case 'S': defsrv = EARGF(usage()); break; case 's': defsrv = "vacfs"; break; case 'M': mem = unittoull(EARGF(usage())); break; case 'm': defmnt = EARGF(usage()); break; case 'p': noperm = 1; break; case 'V': chattyventi = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); #ifdef PLAN9PORT if(defsrv == nil && defmnt == nil && !stdio){ srvname = strchr(argv[0], '/'); if(srvname) srvname++; else srvname = argv[0]; defsrv = vtmalloc(6+strlen(srvname)+1); strcpy(defsrv, "vacfs."); strcat(defsrv, srvname); if(strcmp(defsrv+strlen(defsrv)-4, ".vac") == 0) defsrv[strlen(defsrv)-4] = 0; } #else if(defsrv == nil && defmnt == nil && !stdio) defmnt = "/n/vac"; #endif if(stdio && defmnt) sysfatal("cannot use -m with -i"); initfcalls(); notify(notifyf); user = getuser(); conn = vtdial(host); if(conn == nil) sysfatal("could not connect to server: %r"); if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); fs = vacfsopen(conn, argv[0], VtOREAD, mem); if(fs == nil) sysfatal("vacfsopen: %r"); if(!stdio){ if(pipe(p) < 0) sysfatal("pipe failed: %r"); mfd[0] = p[0]; mfd[1] = p[0]; srvfd = p[1]; #ifndef PLAN9PORT if(defsrv){ srvname = smprint("/srv/%s", defsrv); fd = create(srvname, OWRITE|ORCLOSE, 0666); if(fd < 0) sysfatal("create %s: %r", srvname); if(fprint(fd, "%d", srvfd) < 0) sysfatal("write %s: %r", srvname); free(srvname); } #endif } #ifdef PLAN9PORT USED(fd); proccreate(srv, 0, 32 * 1024); if(!stdio && post9pservice(p[1], defsrv, defmnt) < 0) sysfatal("post9pservice"); #else procrfork(srv, 0, 32 * 1024, RFFDG|RFNAMEG|RFNOTEG); if(!stdio){ close(p[0]); if(defmnt){ if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0) sysfatal("mount %s: %r", defmnt); } } #endif threadexits(0); }
void sbupdate(Shabuf *sb, uchar *p, vlong offset, int len) { int n, x; vlong o; if(sb->rollback && !sb->hist){ sb->r0 = offset; sb->nhist = 1; sb->hist = vtmalloc(sb->nhist*sizeof *sb->hist); memset(sb->hist, 0, sizeof sb->hist[0]); } if(sb->r0 == 0) sb->r0 = offset; if(sb->offset < offset || sb->offset >= offset+len){ if(0) print("sbupdate %p %#llux+%d but offset=%#llux\n", p, offset, len, sb->offset); return; } x = sb->offset - offset; if(0) print("sbupdate %p %#llux+%d skip %d\n", sb, offset, len, x); if(x){ p += x; offset += x; len -= x; } assert(sb->offset == offset); if(sb->fd > 0) pwrite(sb->fd, p, len, offset - sb->r0); if(!sb->rollback){ sha1(p, len, nil, &sb->state); sb->offset += len; return; } /* save state every 4M so we can roll back quickly */ o = offset - sb->r0; while(len > 0){ n = 4*M - o%(4*M); if(n > len) n = len; sha1(p, n, nil, &sb->state); sb->offset += n; o += n; p += n; len -= n; if(o%(4*M) == 0){ x = o/(4*M); if(x >= sb->nhist){ if(x != sb->nhist) print("oops! x=%d nhist=%d\n", x, sb->nhist); sb->nhist += 32; sb->hist = vtrealloc(sb->hist, sb->nhist*sizeof *sb->hist); } sb->hist[x] = sb->state; } } }
void sendmail(char *content, char *subject, char *msg) { int fd; Biobuf *bin, *bout; if((fd = dial(conf.smtp, 0, 0, 0)) < 0) { vtlogprint(errlog, "dial %s: %r\n", conf.smtp); return; } bin = vtmalloc(sizeof *bin); bout = vtmalloc(sizeof *bout); Binit(bin, fd, OREAD); Binit(bout, fd, OWRITE); if(smtpread(bin, 220) < 0){ error: close(fd); Bterm(bin); Bterm(bout); return; } Bprint(bout, "HELO venti-mgr\n"); Bflush(bout); if(smtpread(bin, 250) < 0) goto error; Bprint(bout, "MAIL FROM:<%s>\n", conf.mailfrom); Bflush(bout); if(smtpread(bin, 250) < 0) goto error; Bprint(bout, "RCPT TO:<%s>\n", conf.mailfrom); Bflush(bout); if(smtpread(bin, 250) < 0) goto error; Bprint(bout, "DATA\n"); Bflush(bout); if(smtpread(bin, 354) < 0) goto error; Bprint(bout, "From: \"venti mgr\" <%s>\n", conf.mailfrom); Bprint(bout, "To: <%s>\n", conf.mailto); Bprint(bout, "Subject: %s\n", subject); Bprint(bout, "MIME-Version: 1.0\n"); Bprint(bout, "Content-Type: %s; charset=\"UTF-8\"\n", content); Bprint(bout, "Content-Transfer-Encoding: quoted-printable\n"); Bprint(bout, "Message-ID: %08lux%[email protected]\n", fastrand(), fastrand()); Bprint(bout, "\n"); qp(bout, msg); Bprint(bout, ".\n"); Bflush(bout); if(smtpread(bin, 250) < 0) goto error; Bprint(bout, "QUIT\n"); Bflush(bout); Bterm(bin); Bterm(bout); close(fd); }
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; }
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, nline; char *p, *q, *table, *table1, *f[10], line[256]; vlong start, stop; ArenaPart ap; ArenaPart ap1; ventifmtinstall(); blocksize = MaxIoSize; ARGBEGIN{ case 'b': blocksize = unittoull(EARGF(usage())); break; case 's': sleepms = atoi(EARGF(usage())); break; case 'v': verbose++; break; default: usage(); break; }ARGEND if(argc < 2) usage(); data = vtmalloc(blocksize); data1 = vtmalloc(blocksize); if((fd = open(argv[0], OREAD)) < 0) sysfatal("open %s: %r", argv[0]); if((fd1 = open(argv[1], OREAD)) < 0) sysfatal("open %s: %r", argv[0]); table = readap(fd, &ap); table1 = readap(fd1, &ap1); if(strcmp(table, table1) != 0) sysfatal("arena partitions do not have identical tables"); nline = atoi(table); p = strchr(table, '\n'); if(p) p++; for(i=0; i<nline; i++){ if(p == nil){ fprint(2, "warning: unexpected arena table end\n"); break; } q = strchr(p, '\n'); if(q) *q++ = 0; if(strlen(p) >= sizeof line){ fprint(2, "warning: long arena table line: %s\n", p); p = q; continue; } strcpy(line, p); memset(f, 0, sizeof f); if(tokenize(line, f, nelem(f)) < 3){ fprint(2, "warning: bad arena table line: %s\n", p); p = q; continue; } p = q; if(shouldcheck(f[0], argv+1, argc-1)){ start = strtoull(f[1], 0, 0); stop = strtoull(f[2], 0, 0); if(stop <= start){ fprint(2, "%s: bad start,stop %lld,%lld\n", f[0], stop, start); continue; } if(seek(fd, start, 0) < 0) fprint(2, "%s: seek to start: %r\n", f[0]); if(seek(fd1, start, 0) < 0) fprint(2, "%s: seek to start: %r\n", f[0]); cmparena(f[0], stop - start); } } for(i=2; i<argc; i++) if(argv[i] != 0) fprint(2, "%s: did not find arena\n", argv[i]); threadexitsall(nil); }