unvac: add -d flag (David Swasey)

This commit is contained in:
Russ Cox 2008-12-06 16:14:10 -08:00
parent 115dbcecc8
commit 286bb40b76
5 changed files with 97 additions and 23 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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).

View file

@ -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);