#include #include #include #include #include enum { // XXX What to do here? VtMaxLumpSize = 65536, }; int changes; int rewrite; int ignoreerrors; int fast; int verbose; VtConn *zsrc, *zdst; void usage(void) { fprint(2, "usage: copy [-fir] [-t type] srchost dsthost score\n"); threadexitsall("usage"); } void walk(uchar score[VtScoreSize], uint type, int base) { int i, n; uchar *buf; VtEntry e; VtRoot root; if(memcmp(score, vtzeroscore, VtScoreSize) == 0) return; buf = vtmallocz(VtMaxLumpSize); if(fast && vtread(zdst, score, type, buf, VtMaxLumpSize) >= 0){ if(verbose) fprint(2, "skip %V\n", score); free(buf); return; } n = vtread(zsrc, score, type, buf, VtMaxLumpSize); if(n < 0){ if(rewrite){ changes++; memmove(score, vtzeroscore, VtScoreSize); }else if(!ignoreerrors) sysfatal("reading block %V (type %d): %r", score, type); return; } switch(type){ case VtRootType: if(vtrootunpack(&root, buf) < 0){ fprint(2, "warning: could not unpack root in %V %d\n", score, type); break; } walk(root.score, VtDirType, 0); walk(root.prev, VtRootType, 0); if(rewrite) vtrootpack(&root, buf); /* walk might have changed score */ break; case VtDirType: for(i=0; i= 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(vtsync(zdst) < 0) sysfatal("could not sync dst server: %r"); threadexitsall(0); }