* download-using-manifests: don't check the cryptographic hash of
downloaded files; rather, check the hash of the unpacked store path. When the server produces bzipped NAR archives on demand (like Hydra does), the hash of the file is not known in advance; it's streamed from the server. Thus the manifest doesn't contain a hash for the bzipped NAR archive. However, the server does know the hash of the *uncompressed* NAR archive (the "NarHash" field), since it's stored in the Nix database (nix-store -q --hash /nix/store/bla). So we use that instead for checking the integrity of the download.
This commit is contained in:
parent
621093cb1c
commit
041717eda3
1 changed files with 30 additions and 18 deletions
|
@ -185,13 +185,11 @@ while ($queueFront < scalar @queue) {
|
||||||
$format = "" if $baseHashAlgo eq "md5";
|
$format = "" if $baseHashAlgo eq "md5";
|
||||||
my $hash = `$binDir/nix-hash --type '$baseHashAlgo' $format "$patch->{basePath}"`;
|
my $hash = `$binDir/nix-hash --type '$baseHashAlgo' $format "$patch->{basePath}"`;
|
||||||
chomp $hash;
|
chomp $hash;
|
||||||
# print " MY HASH is $hash\n";
|
|
||||||
if ($hash ne $baseHash) {
|
if ($hash ne $baseHash) {
|
||||||
print LOGFILE "$$ rejecting $patch->{basePath}\n";
|
print LOGFILE "$$ rejecting $patch->{basePath}\n";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# print " PATCH from $patch->{basePath}\n";
|
|
||||||
addToQueue $patch->{basePath};
|
addToQueue $patch->{basePath};
|
||||||
addEdge $patch->{basePath}, $u, $patch->{size}, "patch", $patch;
|
addEdge $patch->{basePath}, $u, $patch->{size}, "patch", $patch;
|
||||||
}
|
}
|
||||||
|
@ -199,10 +197,12 @@ while ($queueFront < scalar @queue) {
|
||||||
# Add NAR file edges to the start node.
|
# Add NAR file edges to the start node.
|
||||||
my $narFileList = $narFiles{$u};
|
my $narFileList = $narFiles{$u};
|
||||||
foreach my $narFile (@{$narFileList}) {
|
foreach my $narFile (@{$narFileList}) {
|
||||||
# print " NAR from $narFile->{url}\n";
|
# !!! how to handle files whose size is not known in advance?
|
||||||
addEdge "start", $u, $narFile->{size}, "narfile", $narFile;
|
# For now, assume some arbitrary size (1 MB).
|
||||||
|
addEdge "start", $u, ($narFile->{size} || 1000000), "narfile", $narFile;
|
||||||
if ($u eq $targetPath) {
|
if ($u eq $targetPath) {
|
||||||
print LOGFILE "$$ full-download-would-be $narFile->{size}\n";
|
my $size = $narFile->{size} || -1;
|
||||||
|
print LOGFILE "$$ full-download-would-be $size\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +228,6 @@ while (scalar @todo > 0) {
|
||||||
|
|
||||||
my $u_ = $graph{$u};
|
my $u_ = $graph{$u};
|
||||||
|
|
||||||
# print "IN $u $u_->{d}\n";
|
|
||||||
|
|
||||||
foreach my $edge (@{$u_->{edges}}) {
|
foreach my $edge (@{$u_->{edges}}) {
|
||||||
my $v_ = $graph{$edge->{end}};
|
my $v_ = $graph{$edge->{end}};
|
||||||
if ($v_->{d} > $u_->{d} + $edge->{weight}) {
|
if ($v_->{d} > $u_->{d} + $edge->{weight}) {
|
||||||
|
@ -237,7 +235,6 @@ while (scalar @todo > 0) {
|
||||||
# Store the edge; to edge->start is actually the
|
# Store the edge; to edge->start is actually the
|
||||||
# predecessor.
|
# predecessor.
|
||||||
$v_->{pred} = $edge;
|
$v_->{pred} = $edge;
|
||||||
# print " RELAX $edge->{end} $v_->{d}\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,20 +256,18 @@ while ($cur ne "start") {
|
||||||
my $curStep = 1;
|
my $curStep = 1;
|
||||||
my $maxStep = scalar @path;
|
my $maxStep = scalar @path;
|
||||||
|
|
||||||
sub downloadFile {
|
sub downloadFile {
|
||||||
my $url = shift;
|
my $url = shift;
|
||||||
my ($hashAlgo, $hash) = parseHash(shift);
|
|
||||||
$ENV{"PRINT_PATH"} = 1;
|
$ENV{"PRINT_PATH"} = 1;
|
||||||
$ENV{"QUIET"} = 1;
|
$ENV{"QUIET"} = 1;
|
||||||
$ENV{"NIX_HASH_ALGO"} = $hashAlgo;
|
my ($hash, $path) = `$binDir/nix-prefetch-url '$url'`;
|
||||||
my ($hash2, $path) = `$binDir/nix-prefetch-url '$url' '$hash'`;
|
|
||||||
die "download of `$url' failed" unless $? == 0;
|
die "download of `$url' failed" unless $? == 0;
|
||||||
chomp $hash2;
|
|
||||||
chomp $path;
|
chomp $path;
|
||||||
die "hash mismatch, expected $hash, got $hash2" if $hash ne $hash2;
|
|
||||||
return $path;
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $finalNarHash;
|
||||||
|
|
||||||
while (scalar @path > 0) {
|
while (scalar @path > 0) {
|
||||||
my $edge = pop @path;
|
my $edge = pop @path;
|
||||||
my $u = $edge->{start};
|
my $u = $edge->{start};
|
||||||
|
@ -302,7 +297,7 @@ while (scalar @path > 0) {
|
||||||
|
|
||||||
# Download the patch.
|
# Download the patch.
|
||||||
print " downloading patch...\n";
|
print " downloading patch...\n";
|
||||||
my $patchPath = downloadFile "$patch->{url}", "$patch->{hash}";
|
my $patchPath = downloadFile "$patch->{url}";
|
||||||
|
|
||||||
# Apply the patch to the NAR archive produced in step 1 (for
|
# Apply the patch to the NAR archive produced in step 1 (for
|
||||||
# the already present path) or a later step (for patch sequences).
|
# the already present path) or a later step (for patch sequences).
|
||||||
|
@ -320,17 +315,20 @@ while (scalar @path > 0) {
|
||||||
system("$binDir/nix-store --restore $v < $tmpNar2") == 0
|
system("$binDir/nix-store --restore $v < $tmpNar2") == 0
|
||||||
or die "cannot unpack $tmpNar2 into `$v'";
|
or die "cannot unpack $tmpNar2 into `$v'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$finalNarHash = $patch->{narHash};
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ($edge->{type} eq "narfile") {
|
elsif ($edge->{type} eq "narfile") {
|
||||||
my $narFile = $edge->{info};
|
my $narFile = $edge->{info};
|
||||||
print "downloading `$narFile->{url}' into `$v'\n";
|
print "downloading `$narFile->{url}' into `$v'\n";
|
||||||
|
|
||||||
print LOGFILE "$$ narfile $narFile->{url} $narFile->{size} $v\n";
|
my $size = $narFile->{size} || -1;
|
||||||
|
print LOGFILE "$$ narfile $narFile->{url} $size $v\n";
|
||||||
|
|
||||||
# Download the archive.
|
# Download the archive.
|
||||||
print " downloading archive...\n";
|
print " downloading archive...\n";
|
||||||
my $narFilePath = downloadFile "$narFile->{url}", "$narFile->{hash}";
|
my $narFilePath = downloadFile "$narFile->{url}";
|
||||||
|
|
||||||
if ($curStep < $maxStep) {
|
if ($curStep < $maxStep) {
|
||||||
# The archive will be used a base to a patch.
|
# The archive will be used a base to a patch.
|
||||||
|
@ -342,11 +340,25 @@ while (scalar @path > 0) {
|
||||||
system("@bunzip2@ < '$narFilePath' | $binDir/nix-store --restore '$v'") == 0
|
system("@bunzip2@ < '$narFilePath' | $binDir/nix-store --restore '$v'") == 0
|
||||||
or die "cannot unpack `$narFilePath' into `$v'";
|
or die "cannot unpack `$narFilePath' into `$v'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$finalNarHash = $narFile->{narHash};
|
||||||
}
|
}
|
||||||
|
|
||||||
$curStep++;
|
$curStep++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (defined $finalNarHash) {
|
||||||
|
my ($hashAlgo, $hash) = parseHash $finalNarHash;
|
||||||
|
my $hash2 = `@bindir@/nix-hash --type $hashAlgo --base32 $targetPath`
|
||||||
|
or die "cannot compute hash of path `$targetPath'";
|
||||||
|
chomp $hash2;
|
||||||
|
die "hash mismatch in downloaded path $targetPath; expected $hash, got $hash2"
|
||||||
|
if $hash ne $hash2;
|
||||||
|
} else {
|
||||||
|
die "cannot check integrity of the downloaded path since its hash is not known";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
print LOGFILE "$$ success\n";
|
print LOGFILE "$$ success\n";
|
||||||
close LOGFILE;
|
close LOGFILE;
|
||||||
|
|
Loading…
Reference in a new issue