commit 286bb40b76f35ffee1e6789895782af203e0dae3 from: Russ Cox date: Sun Dec 07 00:14:10 2008 UTC unvac: add -d flag (David Swasey) commit - 115dbcecc8d35d12b54d17dc1cba39089ad37b5f commit + 286bb40b76f35ffee1e6789895782af203e0dae3 blob - 7de41ee622c593018db745c48c99576f907efa0e blob + 3ce718df103aec47e1150743db80b47cf95c2ac6 --- man/man1/vac.1 +++ man/man1/vac.1 @@ -34,7 +34,7 @@ vac, unvac \- create, extract a vac archive on Venti .PP .B unvac [ -.B -Tctv +.B -Tcdtv ] [ .B -h .I host @@ -207,6 +207,13 @@ to the time listed in the archive. .B -c Write extracted files to standard output instead of creating a file. .TP +.B -d +Reduce the number of blocks read from Venti by +comparing the files to be stored with their counterparts +in the file system. +This option cannot be used with +.BR -c . +.TP .B -t Print a list of the files to standard output rather than extracting them. .TP blob - 598dae092b6b3b7a5bfc422cb30be97750952401 blob + faa558f3df96ea9d8aff6b39bb11c77a5f293eb4 --- src/cmd/vac/file.c +++ src/cmd/vac/file.c @@ -2060,4 +2060,33 @@ vacfssync(VacFs *fs) if(vtsync(fs->z) < 0) return -1; return 0; +} + +int +vacfiledsize(VacFile *f) +{ + VtEntry e; + + if(vacfilegetentries(f,&e,nil) < 0) + return -1; + return e.dsize; } + +/* + * Does block b of f have the same SHA1 hash as the n bytes at buf? + */ +int +sha1matches(VacFile *f, ulong b, uchar *buf, int n) +{ + uchar fscore[VtScoreSize]; + uchar bufscore[VtScoreSize]; + + if(vacfileblockscore(f, b, fscore) < 0) + return 0; + n = vtzerotruncate(VtDataType, buf, n); + sha1(buf, n, bufscore, nil); + if(memcmp(bufscore, fscore, VtScoreSize) == 0) + return 1; + return 0; +} + blob - d4f863ccf86053e976b73c6c508b5fc73eef2638 blob + ab799cb0a9b79a31f283b2cc9a1821cc8fb52643 --- src/cmd/vac/unvac.c +++ src/cmd/vac/unvac.c @@ -8,6 +8,7 @@ VacFs *fs; int tostdout; +int diff; int nwant; char **want; int *found; @@ -23,14 +24,20 @@ void unvac(VacFile*, char*, VacDir*); void usage(void) { - fprint(2, "usage: unvac [-TVctv] [-h host] file.vac [file ...]\n"); + fprint(2, "usage: unvac [-TVcdtv] [-h host] file.vac [file ...]\n"); threadexitsall("usage"); } +struct +{ + vlong data; + vlong skipdata; +} stats; + void threadmain(int argc, char *argv[]) { - int i; + int i, printstats; char *host; VacFile *f; @@ -41,6 +48,8 @@ threadmain(int argc, char *argv[]) fmtinstall('M', dirmodefmt); host = nil; + printstats = 0; + ARGBEGIN{ case 'T': settimes = 1; @@ -50,10 +59,16 @@ threadmain(int argc, char *argv[]) break; case 'c': tostdout++; + break; + case 'd': + diff++; break; case 'h': host = EARGF(usage()); break; + case 's': + printstats++; + break; case 't': table++; break; @@ -67,6 +82,11 @@ threadmain(int argc, char *argv[]) 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"); @@ -94,6 +114,9 @@ threadmain(int argc, char *argv[]) } if(errors) threadexitsall("errors"); + if(printstats) + fprint(2, "%lld bytes read, %lld bytes skipped\n", + stats.data, stats.skipdata); threadexitsall(0); } @@ -143,7 +166,7 @@ void unvac(VacFile *f, char *name, VacDir *vdir) { static char buf[65536]; - int fd, n; + int fd, n, m, bsize; ulong mode, mode9; char *newname; char *what; @@ -256,23 +279,53 @@ unvac(VacFile *f, char *name, VacDir *vdir) vdeclose(vde); }else{ if(!table){ + off = 0; if(tostdout) fd = dup(1, -1); + else if(diff && (fd = open(name, ORDWR)) >= 0){ + bsize = vacfiledsize(f); + while((n = readn(fd, buf, bsize)) > 0){ + if(sha1matches(f, off/bsize, (uchar*)buf, n)){ + off += n; + stats.skipdata += n; + continue; + } + seek(fd, off, 0); + if((m = vacfileread(f, buf, n, off)) < 0) + break; + if(writen(fd, buf, m) != m){ + fprint(2, "write %s: %r\n", name); + goto Err; + } + off += m; + stats.data += m; + if(m < n){ + nulldir(&d); + d.length = off; + if(dirfwstat(fd, &d) < 0){ + fprint(2, "dirfwstat %s: %r\n", name); + goto Err; + } + break; + } + } + } else if((fd = create(name, OWRITE, mode&0777)) < 0){ fprint(2, "create %s: %r\n", name); errors++; return; } - off = 0; while((n = vacfileread(f, buf, sizeof buf, off)) > 0){ if(writen(fd, buf, n) != n){ fprint(2, "write %s: %r\n", name); + Err: errors++; close(fd); remove(name); return; } off += n; + stats.data += n; } close(fd); } blob - 99651981b13c321e25a4fa5fc52f597a27203882 blob + d6c17b4b808274fe151a9f5f66258c5f3fc176ad --- src/cmd/vac/vac.c +++ src/cmd/vac/vac.c @@ -438,24 +438,6 @@ enum { DMDEVICE }; #endif - -/* - * Does block b of f have the same SHA1 hash as the n bytes at buf? - */ -static int -sha1matches(VacFile *f, ulong b, uchar *buf, int n) -{ - uchar fscore[VtScoreSize]; - uchar bufscore[VtScoreSize]; - - if(vacfileblockscore(f, b, fscore) < 0) - return 0; - n = vtzerotruncate(VtDataType, buf, n); - sha1(buf, n, bufscore, nil); - if(memcmp(bufscore, fscore, VtScoreSize) == 0) - return 1; - return 0; -} /* * Archive the file named name, which has stat info d, blob - 0b82d0ebf22965f92ad2d63a8320d1b229108fd2 blob + cb599a9c3c1b81a9ce6cae086343a6cd35dd4879 --- src/cmd/vac/vac.h +++ src/cmd/vac/vac.h @@ -142,3 +142,6 @@ int vderead(VacDirEnum*, VacDir *); void vdeclose(VacDirEnum*); int vdeunread(VacDirEnum*); +int vacfiledsize(VacFile *f); +int sha1matches(VacFile *f, ulong b, uchar *buf, int n); +