Atree* atreeinit(char *arg) { Atree *a; uchar score[VtScoreSize]; fmtinstall('V', scoreFmt); z = vtdial(nil); if(z == nil) fprint(2, "warning: cannot dial venti: %r\n"); else if(vtconnect(z) < 0) { fprint(2, "warning: cannot connect to venti: %r\n"); z = nil; } a = mallocz(sizeof(Atree), 1); if(strncmp(arg, "vac:", 4) == 0) { if(!parseScore(score, arg+4, strlen(arg+4))) { fprint(2, "cannot parse score\n"); return nil; } a->root = initxvacroot(score); } else a->root = initxcache(arg); a->resizefd = -1; return a; }
void threadmain(int argc, char *argv[]) { int i, n; unsigned char score[VtScoreSize]; unsigned char *buf; VtConn *z; char *host; VtRoot root; fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); quotefmtinstall(); host = nil; ARGBEGIN{ case 'h': host = EARGF(usage()); break; default: usage(); break; }ARGEND if(argc == 0) usage(); buf = vtmallocz(VtMaxLumpSize); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); for(i=0; i<argc; i++){ if(vtparsescore(argv[i], nil, score) < 0){ fprint(2, "cannot parse score '%s': %r\n", argv[i]); continue; } n = vtread(z, score, VtRootType, buf, VtMaxLumpSize); if(n < 0){ fprint(2, "could not read block %V: %r\n", score); continue; } if(n != VtRootSize){ fprint(2, "block %V is wrong size %d != 300\n", score, n); continue; } if(vtrootunpack(&root, buf) < 0){ fprint(2, "unpacking block %V: %r\n", score); continue; } print("%V: %q %q %V %d %V\n", score, root.name, root.type, root.score, root.blocksize, root.prev); } vthangup(z); threadexitsall(0); }
void threadmain(int argc, char *argv[]) { char *host; int dotrunc, n, type; uchar *p, score[VtScoreSize]; VtConn *z; fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); host = nil; dotrunc = 0; type = VtDataType; ARGBEGIN{ case 'z': dotrunc = 1; break; case 'h': host = EARGF(usage()); break; case 't': type = atoi(EARGF(usage())); break; default: usage(); break; }ARGEND if(argc != 0) usage(); p = vtmallocz(VtMaxLumpSize+1); n = readn(0, p, VtMaxLumpSize+1); if(n > VtMaxLumpSize) sysfatal("input too big: max block size is %d", VtMaxLumpSize); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(dotrunc) n = vtzerotruncate(type, p, n); if(vtwrite(z, score, type, p, n) < 0) sysfatal("vtwrite: %r"); vthangup(z); print("%V\n", score); threadexitsall(0); }
void threadmain(int argc, char *argv[]) { uchar score[VtScoreSize]; uchar buf[VtRootSize]; VtConn *z; VtRoot root; ARGBEGIN{ case 'h': host = EARGF(usage()); break; default: usage(); break; }ARGEND if(argc != 5) usage(); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); strecpy(root.name, root.name+sizeof root.name, argv[0]); strecpy(root.type, root.type+sizeof root.type, argv[1]); if(vtparsescore(argv[2], nil, root.score) < 0) sysfatal("bad score '%s'", argv[2]); root.blocksize = atoi(argv[3]); if(vtparsescore(argv[4], nil, root.prev) < 0) sysfatal("bad score '%s'", argv[4]); vtrootpack(&root, buf); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(vtwrite(z, score, VtRootType, buf, VtRootSize) < 0) sysfatal("vtwrite: %r"); if(vtsync(z) < 0) sysfatal("vtsync: %r"); vthangup(z); print("%V\n", score); threadexitsall(0); }
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 main(int argc, char *argv[]) { int type, n; unsigned char score[VtScoreSize]; unsigned char *buf; char *prefix; fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); type = -1; ARGBEGIN{ case 'V': chattyventi++; break; case 'f': fast = 1; break; case 'i': if(rewrite) usage(); ignoreerrors = 1; break; case 'm': scoretree = mkavltree(scoretreecmp); break; case 'r': if(ignoreerrors) usage(); rewrite = 1; break; case 't': type = atoi(EARGF(usage())); break; case 'v': verbose = 1; break; default: usage(); break; }ARGEND if(argc != 3) usage(); if(vtparsescore(argv[2], &prefix, score) < 0) sysfatal("could not parse score: %r"); buf = vtmallocz(VtMaxLumpSize); zsrc = vtdial(argv[0]); if(zsrc == nil) sysfatal("could not dial src server: %r"); if(vtconnect(zsrc) < 0) sysfatal("vtconnect src: %r"); zdst = vtdial(argv[1]); if(zdst == nil) sysfatal("could not dial dst server: %r"); if(vtconnect(zdst) < 0) sysfatal("vtconnect dst: %r"); if(type != -1){ n = vtread(zsrc, score, type, buf, VtMaxLumpSize); if(n < 0) sysfatal("could not read block: %r"); }else{ for(type=0; type<VtMaxType; type++){ n = vtread(zsrc, score, type, buf, VtMaxLumpSize); if(n >= 0) break; } if(type == VtMaxType) sysfatal("could not find block %V of any type", score); } walk(score, type, VtDirType); if(changes) print("%s:%V (%d pointers rewritten)\n", prefix, score, changes); if(verbose) print("%d skipped, %d written\n", nskip, nwrite); if(vtsync(zdst) < 0) sysfatal("could not sync dst server: %r"); exits(0); }
void threadmain(int argc, char *argv[]) { int type, n; uchar score[VtScoreSize]; uchar *buf; VtConn *z; char *host; fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); host = nil; type = -1; ARGBEGIN{ case 'h': host = EARGF(usage()); break; case 't': type = atoi(EARGF(usage())); break; default: usage(); break; }ARGEND if(argc != 1) usage(); if(vtparsescore(argv[0], nil, score) < 0) sysfatal("could not parse score '%s': %r", argv[0]); buf = vtmallocz(VtMaxLumpSize); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(type == -1){ n = -1; for(type=0; type<VtMaxType; type++){ n = vtread(z, score, type, buf, VtMaxLumpSize); if(n >= 0){ fprint(2, "venti/read%s%s %V %d\n", host ? " -h" : "", host ? host : "", score, type); break; } } }else n = vtread(z, score, type, buf, VtMaxLumpSize); vthangup(z); if(n < 0) sysfatal("could not read block: %r"); if(write(1, buf, n) != n) sysfatal("write: %r"); threadexitsall(0); }
void threadmain(int argc, char *argv[]) { char *defsrv, *srvname; int p[2], fd; int stdio; char *host = nil; long ncache; stdio = 0; ncache = 256; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); defmnt = nil; defsrv = nil; ARGBEGIN{ case 'd': fmtinstall('F', fcallfmt); dflag = 1; break; case 'c': ncache = atoi(EARGF(usage())); 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': defmnt = EARGF(usage()); break; case 'p': noperm = 1; break; case 'V': chattyventi = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); if(defsrv == nil && defmnt == nil && !stdio) defmnt = "/n/vac"; 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, ncache); 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]; 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); } } procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG); if(!stdio){ close(p[0]); if(defmnt){ if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0) sysfatal("mount %s: %r", defmnt); } } threadexits(0); }
void threadmain(int argc, char *argv[]) { int n; uchar score[VtScoreSize]; uchar *buf; char *host, *type; vlong off; VtEntry e; VtRoot root; VtCache *c; VtConn *z; VtFile *f; quotefmtinstall(); fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); host = nil; ARGBEGIN{ case 'V': chattyventi++; break; case 'h': host = EARGF(usage()); break; case 'v': chatty++; break; default: usage(); break; }ARGEND if(argc != 1) usage(); type = nil; if(vtparsescore(argv[0], &type, score) < 0) sysfatal("could not parse score '%s': %r", argv[0]); if(type == nil || strcmp(type, "file") != 0) sysfatal("bad score - not file:..."); buf = vtmallocz(VtMaxLumpSize); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); // root block ... n = vtread(z, score, VtRootType, buf, VtMaxLumpSize); if(n < 0) sysfatal("could not read root %V: %r", score); if(n != VtRootSize) sysfatal("root block %V is wrong size %d != %d", score, n, VtRootSize); if(vtrootunpack(&root, buf) < 0) sysfatal("unpacking root block %V: %r", score); if(strcmp(root.type, "file") != 0) sysfatal("bad root type %q (not 'file')", root.type); if(chatty) fprint(2, "%V: %q %q %V %d %V\n", score, root.name, root.type, root.score, root.blocksize, root.prev); // ... points at entry block n = vtread(z, root.score, VtDirType, buf, VtMaxLumpSize); if(n < 0) sysfatal("could not read entry %V: %r", root.score); if(n != VtEntrySize) sysfatal("dir block %V is wrong size %d != %d", root.score, n, VtEntrySize); if(vtentryunpack(&e, buf, 0) < 0) sysfatal("unpacking dir block %V: %r", root.score); if((e.type&VtTypeBaseMask) != VtDataType) sysfatal("not a single file"); // open and read file c = vtcachealloc(z, root.blocksize*32); if(c == nil) sysfatal("vtcachealloc: %r"); f = vtfileopenroot(c, &e); if(f == nil) sysfatal("vtfileopenroot: %r"); off = 0; vtfilelock(f, VtOREAD); while((n = vtfileread(f, buf, VtMaxLumpSize, off)) > 0){ write(1, buf, n); off += n; } threadexitsall(0); }
void threadmain(int argc, char *argv[]) { int i, printstats; char *host; VacFile *f; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); fmtinstall('t', mtimefmt); fmtinstall('M', dirmodefmt); host = nil; printstats = 0; ARGBEGIN{ case 'T': settimes = 1; break; case 'V': chattyventi = 1; break; case 'c': tostdout++; break; case 'd': diff++; break; case 'h': host = EARGF(usage()); break; case 's': printstats++; break; case 't': table++; break; case 'v': chatty++; break; default: usage(); }ARGEND if(argc < 1) usage(); if(tostdout && diff){ fprint(2, "cannot use -c with -d\n"); usage(); } 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, 128); if(fs == nil) sysfatal("vacfsopen: %r"); nwant = argc-1; want = argv+1; found = vtmallocz(nwant*sizeof found[0]); if((f = vacfsgetroot(fs)) == nil) sysfatal("vacfsgetroot: %r"); unvac(f, nil, nil); for(i=0; i<nwant; i++){ if(want[i] && !found[i]){ fprint(2, "warning: didn't find %s\n", want[i]); errors++; } } if(errors) threadexitsall("errors"); if(printstats) fprint(2, "%lld bytes read, %lld bytes skipped\n", stats.data, stats.skipdata); threadexitsall(0); }
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); }
void threadmain(int argc, char **argv) { char *pref, *mountname, *mountplace; uchar score[VtScoreSize], prev[VtScoreSize]; int i, fd, csize; vlong bsize; Tm tm; VtEntry e; VtBlock *b; VtCache *c; VtRoot root; char *tmp, *tmpnam; fmtinstall('F', vtfcallfmt); fmtinstall('H', encodefmt); fmtinstall('T', timefmt); fmtinstall('V', vtscorefmt); mountname = sysname(); mountplace = nil; ARGBEGIN{ default: usage(); break; case 'D': debug++; break; case 'V': chattyventi = 1; break; case 'f': fastwrites = 1; break; case 'i': incremental = 1; break; case 'm': mountname = EARGF(usage()); break; case 'M': mountplace = EARGF(usage()); i = strlen(mountplace); if(i > 0 && mountplace[i-1] == '/') mountplace[i-1] = 0; break; case 'n': nop = 1; break; case 's': statustime = atoi(EARGF(usage())); break; case 'v': verbose = 1; break; case 'w': nwritethread = atoi(EARGF(usage())); break; }ARGEND if(argc != 1 && argc != 2) usage(); if(statustime) print("# %T vbackup %s %s\n", argv[0], argc>=2 ? argv[1] : ""); /* * open fs */ if((disk = diskopenfile(argv[0])) == nil) sysfatal("diskopen: %r"); if((disk = diskcache(disk, 32768, 2*MAXQ+16)) == nil) sysfatal("diskcache: %r"); if((fsys = fsysopen(disk)) == nil) sysfatal("fsysopen: %r"); /* * connect to venti */ if((z = vtdial(nil)) == nil) sysfatal("vtdial: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); /* * set up venti block cache */ zero = vtmallocz(fsys->blocksize); bsize = fsys->blocksize; csize = 50; /* plenty; could probably do with 5 */ if(verbose) fprint(2, "cache %d blocks\n", csize); c = vtcachealloc(z, bsize*csize); zcache = c; /* * parse starting score */ memset(prev, 0, sizeof prev); if(argc == 1){ vfile = vtfilecreateroot(c, (fsys->blocksize/VtScoreSize)*VtScoreSize, fsys->blocksize, VtDataType); if(vfile == nil) sysfatal("vtfilecreateroot: %r"); vtfilelock(vfile, VtORDWR); if(vtfilewrite(vfile, zero, 1, bsize*fsys->nblock-1) != 1) sysfatal("vtfilewrite: %r"); if(vtfileflush(vfile) < 0) sysfatal("vtfileflush: %r"); }else{ if(vtparsescore(argv[1], &pref, score) < 0) sysfatal("bad score: %r"); if(pref!=nil && strcmp(pref, fsys->type) != 0) sysfatal("score is %s but fsys is %s", pref, fsys->type); b = vtcacheglobal(c, score, VtRootType, VtRootSize); if(b){ if(vtrootunpack(&root, b->data) < 0) sysfatal("bad root: %r"); if(strcmp(root.type, fsys->type) != 0) sysfatal("root is %s but fsys is %s", root.type, fsys->type); memmove(prev, score, VtScoreSize); memmove(score, root.score, VtScoreSize); vtblockput(b); } b = vtcacheglobal(c, score, VtDirType, VtEntrySize); if(b == nil) sysfatal("vtcacheglobal %V: %r", score); if(vtentryunpack(&e, b->data, 0) < 0) sysfatal("%V: vtentryunpack failed", score); if(verbose) fprint(2, "entry: size %llud psize %d dsize %d\n", e.size, e.psize, e.dsize); vtblockput(b); if((vfile = vtfileopenroot(c, &e)) == nil) sysfatal("vtfileopenroot: %r"); vtfilelock(vfile, VtORDWR); if(e.dsize != bsize) sysfatal("file system block sizes don't match %d %lld", e.dsize, bsize); if(e.size != fsys->nblock*bsize) sysfatal("file system block counts don't match %lld %lld", e.size, fsys->nblock*bsize); } tmpnam = nil; if(incremental){ if(vtfilegetentry(vfile, &e) < 0) sysfatal("vtfilegetentry: %r"); if((vscores = vtfileopenroot(c, &e)) == nil) sysfatal("vtfileopenroot: %r"); vtfileunlock(vfile); }else{ /* * write scores of blocks into temporary file */ if((tmp = getenv("TMP")) != nil){ /* okay, good */ }else if(access("/var/tmp", 0) >= 0) tmp = "/var/tmp"; else tmp = "/tmp"; tmpnam = smprint("%s/vbackup.XXXXXX", tmp); if(tmpnam == nil) sysfatal("smprint: %r"); if((fd = opentemp(tmpnam, ORDWR|ORCLOSE)) < 0) sysfatal("opentemp %s: %r", tmpnam); if(statustime) print("# %T reading scores into %s\n", tmpnam); if(verbose) fprint(2, "read scores into %s...\n", tmpnam); Binit(&bscores, fd, OWRITE); for(i=0; i<fsys->nblock; i++){ if(vtfileblockscore(vfile, i, score) < 0) sysfatal("vtfileblockhash %d: %r", i); if(Bwrite(&bscores, score, VtScoreSize) != VtScoreSize) sysfatal("Bwrite: %r"); } Bterm(&bscores); vtfileunlock(vfile); /* * prep scores for rereading */ seek(fd, 0, 0); Binit(&bscores, fd, OREAD); } /* * start the main processes */ if(statustime) print("# %T starting procs\n"); qcmp = qalloc(); qventi = qalloc(); rlock(&endlk); proccreate(fsysproc, nil, STACK); rlock(&endlk); proccreate(ventiproc, nil, STACK); rlock(&endlk); proccreate(cmpproc, nil, STACK); if(statustime){ rlock(&endlk); proccreate(statusproc, nil, STACK); } /* * wait for processes to finish */ wlock(&endlk); qfree(qcmp); qfree(qventi); if(statustime) print("# %T procs exited: %d of %d %d-byte blocks changed, " "%d read, %d written, %d skipped, %d copied\n", nchange, fsys->nblock, fsys->blocksize, vtcachenread, vtcachenwrite, nskip, vtcachencopy); /* * prepare root block */ if(incremental) vtfileclose(vscores); vtfilelock(vfile, -1); if(vtfileflush(vfile) < 0) sysfatal("vtfileflush: %r"); if(vtfilegetentry(vfile, &e) < 0) sysfatal("vtfilegetentry: %r"); vtfileunlock(vfile); vtfileclose(vfile); b = vtcacheallocblock(c, VtDirType, VtEntrySize); if(b == nil) sysfatal("vtcacheallocblock: %r"); vtentrypack(&e, b->data, 0); if(vtblockwrite(b) < 0) sysfatal("vtblockwrite: %r"); memset(&root, 0, sizeof root); strecpy(root.name, root.name+sizeof root.name, argv[0]); strecpy(root.type, root.type+sizeof root.type, fsys->type); memmove(root.score, b->score, VtScoreSize); root.blocksize = fsys->blocksize; memmove(root.prev, prev, VtScoreSize); vtblockput(b); b = vtcacheallocblock(c, VtRootType, VtRootSize); if(b == nil) sysfatal("vtcacheallocblock: %r"); vtrootpack(&root, b->data); if(vtblockwrite(b) < 0) sysfatal("vtblockwrite: %r"); tm = *localtime(time(0)); tm.year += 1900; tm.mon++; if(mountplace == nil) mountplace = guessmountplace(argv[0]); print("mount /%s/%d/%02d%02d%s %s:%V %d/%02d%02d/%02d%02d\n", mountname, tm.year, tm.mon, tm.mday, mountplace, root.type, b->score, tm.year, tm.mon, tm.mday, tm.hour, tm.min); print("# %T %s %s:%V\n", argv[0], root.type, b->score); if(statustime) print("# %T venti sync\n"); vtblockput(b); if(vtsync(z) < 0) sysfatal("vtsync: %r"); if(statustime) print("# %T synced\n"); fsysclose(fsys); diskclose(disk); vtcachefree(zcache); // Vtgoodbye hangs on Linux - not sure why. // Probably vtfcallrpc doesn't quite get the // remote hangup right. Also probably related // to the vtrecvproc problem below. // vtgoodbye(z); // Leak here, because I can't seem to make // the vtrecvproc exit. // vtfreeconn(z); free(tmpnam); z = nil; zcache = nil; fsys = nil; disk = nil; threadexitsall(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); }