From 286bb40b76f35ffee1e6789895782af203e0dae3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 6 Dec 2008 16:14:10 -0800 Subject: unvac: add -d flag (David Swasey) --- src/cmd/vac/file.c | 29 +++++++++++++++++++++++++ src/cmd/vac/unvac.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/cmd/vac/vac.c | 18 ---------------- src/cmd/vac/vac.h | 3 +++ 4 files changed, 89 insertions(+), 22 deletions(-) (limited to 'src/cmd/vac') diff --git a/src/cmd/vac/file.c b/src/cmd/vac/file.c index 598dae09..faa558f3 100644 --- a/src/cmd/vac/file.c +++ b/src/cmd/vac/file.c @@ -2061,3 +2061,32 @@ vacfssync(VacFs *fs) 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; +} + diff --git a/src/cmd/vac/unvac.c b/src/cmd/vac/unvac.c index d4f863cc..ab799cb0 100644 --- a/src/cmd/vac/unvac.c +++ b/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; @@ -51,9 +60,15 @@ threadmain(int argc, char *argv[]) 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); } diff --git a/src/cmd/vac/vac.c b/src/cmd/vac/vac.c index 99651981..d6c17b4b 100644 --- a/src/cmd/vac/vac.c +++ b/src/cmd/vac/vac.c @@ -439,24 +439,6 @@ enum { }; #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, * into the vac directory fp (p = parent). diff --git a/src/cmd/vac/vac.h b/src/cmd/vac/vac.h index 0b82d0eb..cb599a9c 100644 --- a/src/cmd/vac/vac.h +++ b/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); + -- cgit v1.2.3