From 06bbfb6004942bfcddd930e746ee7a2bfe5c3872 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 26 Jul 2016 21:16:52 +0200 Subject: builtins.{fetchurl,fetchTarball}: Support a sha256 attribute Also, allow builtins.{fetchurl,fetchTarball} in restricted mode if a hash is specified. --- src/libstore/download.cc | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src/libstore/download.cc') diff --git a/src/libstore/download.cc b/src/libstore/download.cc index 04a2b325c651..f099268953ab 100644 --- a/src/libstore/download.cc +++ b/src/libstore/download.cc @@ -3,6 +3,7 @@ #include "globals.hh" #include "hash.hh" #include "store-api.hh" +#include "archive.hh" #include @@ -221,10 +222,21 @@ ref makeDownloader() return make_ref(); } -Path Downloader::downloadCached(ref store, const string & url_, bool unpack) +Path Downloader::downloadCached(ref store, const string & url_, bool unpack, const Hash & expectedHash) { auto url = resolveUri(url_); + string name; + auto p = url.rfind('/'); + if (p != string::npos) name = string(url, p + 1); + + Path expectedStorePath; + if (expectedHash) { + expectedStorePath = store->makeFixedOutputPath(unpack, expectedHash.type, expectedHash, name); + if (store->isValidPath(expectedStorePath)) + return expectedStorePath; + } + Path cacheDir = getCacheDir() + "/nix/tarballs"; createDirs(cacheDir); @@ -258,10 +270,6 @@ Path Downloader::downloadCached(ref store, const string & url_, bool unpa storePath = ""; } - string name; - auto p = url.rfind('/'); - if (p != string::npos) name = string(url, p + 1); - if (!skip) { try { @@ -269,8 +277,16 @@ Path Downloader::downloadCached(ref store, const string & url_, bool unpa options.expectedETag = expectedETag; auto res = download(url, options); - if (!res.cached) - storePath = store->addTextToStore(name, *res.data, PathSet(), false); + if (!res.cached) { + ValidPathInfo info; + StringSink sink; + dumpString(*res.data, sink); + Hash hash = hashString(expectedHash ? expectedHash.type : htSHA256, *res.data); + info.path = store->makeFixedOutputPath(false, hash.type, hash, name); + info.narHash = hashString(htSHA256, *sink.s); + store->addToStore(info, *sink.s, false, true); + storePath = info.path; + } assert(!storePath.empty()); replaceSymlink(storePath, fileLink); @@ -300,9 +316,12 @@ Path Downloader::downloadCached(ref store, const string & url_, bool unpa unpackedStorePath = store->addToStore(name, tmpDir, true, htSHA256, defaultPathFilter, false); } replaceSymlink(unpackedStorePath, unpackedLink); - return unpackedStorePath; + storePath = unpackedStorePath; } + if (expectedStorePath != "" && storePath != expectedStorePath) + throw nix::Error(format("hash mismatch in file downloaded from ā€˜%sā€™") % url); + return storePath; } -- cgit 1.4.1