unvac: add -d flag (David Swasey)
This commit is contained in:
parent
115dbcecc8
commit
286bb40b76
5 changed files with 97 additions and 23 deletions
|
|
@ -34,7 +34,7 @@ vac, unvac \- create, extract a vac archive on Venti
|
||||||
.PP
|
.PP
|
||||||
.B unvac
|
.B unvac
|
||||||
[
|
[
|
||||||
.B -Tctv
|
.B -Tcdtv
|
||||||
] [
|
] [
|
||||||
.B -h
|
.B -h
|
||||||
.I host
|
.I host
|
||||||
|
|
@ -207,6 +207,13 @@ to the time listed in the archive.
|
||||||
.B -c
|
.B -c
|
||||||
Write extracted files to standard output instead of creating a file.
|
Write extracted files to standard output instead of creating a file.
|
||||||
.TP
|
.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
|
.B -t
|
||||||
Print a list of the files to standard output rather than extracting them.
|
Print a list of the files to standard output rather than extracting them.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
||||||
|
|
@ -2061,3 +2061,32 @@ vacfssync(VacFs *fs)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
VacFs *fs;
|
VacFs *fs;
|
||||||
int tostdout;
|
int tostdout;
|
||||||
|
int diff;
|
||||||
int nwant;
|
int nwant;
|
||||||
char **want;
|
char **want;
|
||||||
int *found;
|
int *found;
|
||||||
|
|
@ -23,14 +24,20 @@ void unvac(VacFile*, char*, VacDir*);
|
||||||
void
|
void
|
||||||
usage(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");
|
threadexitsall("usage");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
vlong data;
|
||||||
|
vlong skipdata;
|
||||||
|
} stats;
|
||||||
|
|
||||||
void
|
void
|
||||||
threadmain(int argc, char *argv[])
|
threadmain(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i, printstats;
|
||||||
char *host;
|
char *host;
|
||||||
VacFile *f;
|
VacFile *f;
|
||||||
|
|
||||||
|
|
@ -41,6 +48,8 @@ threadmain(int argc, char *argv[])
|
||||||
fmtinstall('M', dirmodefmt);
|
fmtinstall('M', dirmodefmt);
|
||||||
|
|
||||||
host = nil;
|
host = nil;
|
||||||
|
printstats = 0;
|
||||||
|
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'T':
|
case 'T':
|
||||||
settimes = 1;
|
settimes = 1;
|
||||||
|
|
@ -51,9 +60,15 @@ threadmain(int argc, char *argv[])
|
||||||
case 'c':
|
case 'c':
|
||||||
tostdout++;
|
tostdout++;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
diff++;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
host = EARGF(usage());
|
host = EARGF(usage());
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
printstats++;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
table++;
|
table++;
|
||||||
break;
|
break;
|
||||||
|
|
@ -67,6 +82,11 @@ threadmain(int argc, char *argv[])
|
||||||
if(argc < 1)
|
if(argc < 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
if(tostdout && diff){
|
||||||
|
fprint(2, "cannot use -c with -d\n");
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
conn = vtdial(host);
|
conn = vtdial(host);
|
||||||
if(conn == nil)
|
if(conn == nil)
|
||||||
sysfatal("could not connect to server: %r");
|
sysfatal("could not connect to server: %r");
|
||||||
|
|
@ -94,6 +114,9 @@ threadmain(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
if(errors)
|
if(errors)
|
||||||
threadexitsall("errors");
|
threadexitsall("errors");
|
||||||
|
if(printstats)
|
||||||
|
fprint(2, "%lld bytes read, %lld bytes skipped\n",
|
||||||
|
stats.data, stats.skipdata);
|
||||||
threadexitsall(0);
|
threadexitsall(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +166,7 @@ void
|
||||||
unvac(VacFile *f, char *name, VacDir *vdir)
|
unvac(VacFile *f, char *name, VacDir *vdir)
|
||||||
{
|
{
|
||||||
static char buf[65536];
|
static char buf[65536];
|
||||||
int fd, n;
|
int fd, n, m, bsize;
|
||||||
ulong mode, mode9;
|
ulong mode, mode9;
|
||||||
char *newname;
|
char *newname;
|
||||||
char *what;
|
char *what;
|
||||||
|
|
@ -256,23 +279,53 @@ unvac(VacFile *f, char *name, VacDir *vdir)
|
||||||
vdeclose(vde);
|
vdeclose(vde);
|
||||||
}else{
|
}else{
|
||||||
if(!table){
|
if(!table){
|
||||||
|
off = 0;
|
||||||
if(tostdout)
|
if(tostdout)
|
||||||
fd = dup(1, -1);
|
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){
|
else if((fd = create(name, OWRITE, mode&0777)) < 0){
|
||||||
fprint(2, "create %s: %r\n", name);
|
fprint(2, "create %s: %r\n", name);
|
||||||
errors++;
|
errors++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
off = 0;
|
|
||||||
while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
|
while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
|
||||||
if(writen(fd, buf, n) != n){
|
if(writen(fd, buf, n) != n){
|
||||||
fprint(2, "write %s: %r\n", name);
|
fprint(2, "write %s: %r\n", name);
|
||||||
|
Err:
|
||||||
errors++;
|
errors++;
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(name);
|
remove(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
off += n;
|
off += n;
|
||||||
|
stats.data += n;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -439,24 +439,6 @@ enum {
|
||||||
};
|
};
|
||||||
#endif
|
#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,
|
* Archive the file named name, which has stat info d,
|
||||||
* into the vac directory fp (p = parent).
|
* into the vac directory fp (p = parent).
|
||||||
|
|
|
||||||
|
|
@ -142,3 +142,6 @@ int vderead(VacDirEnum*, VacDir *);
|
||||||
void vdeclose(VacDirEnum*);
|
void vdeclose(VacDirEnum*);
|
||||||
int vdeunread(VacDirEnum*);
|
int vdeunread(VacDirEnum*);
|
||||||
|
|
||||||
|
int vacfiledsize(VacFile *f);
|
||||||
|
int sha1matches(VacFile *f, ulong b, uchar *buf, int n);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue