aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/vac
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2008-12-06 16:14:10 -0800
committerRuss Cox <rsc@swtch.com>2008-12-06 16:14:10 -0800
commit286bb40b76f35ffee1e6789895782af203e0dae3 (patch)
treeb9fc8b72d8699e6cb71ce680c701f365ab7b6d53 /src/cmd/vac
parent115dbcecc8d35d12b54d17dc1cba39089ad37b5f (diff)
downloadplan9port-286bb40b76f35ffee1e6789895782af203e0dae3.tar.gz
plan9port-286bb40b76f35ffee1e6789895782af203e0dae3.tar.bz2
plan9port-286bb40b76f35ffee1e6789895782af203e0dae3.zip
unvac: add -d flag (David Swasey)
Diffstat (limited to 'src/cmd/vac')
-rw-r--r--src/cmd/vac/file.c29
-rw-r--r--src/cmd/vac/unvac.c61
-rw-r--r--src/cmd/vac/vac.c18
-rw-r--r--src/cmd/vac/vac.h3
4 files changed, 89 insertions, 22 deletions
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
@@ -440,24 +440,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);
+