diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-07-26T19·16+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-07-26T19·16+0200 |
commit | 06bbfb6004942bfcddd930e746ee7a2bfe5c3872 (patch) | |
tree | 25395e3e0da92eb914abf4f59f33027269a28224 /src/libstore/download.cc | |
parent | ee3032e4de439b481ce1a4bc7fd8d71ea6ed2c94 (diff) |
builtins.{fetchurl,fetchTarball}: Support a sha256 attribute
Also, allow builtins.{fetchurl,fetchTarball} in restricted mode if a hash is specified.
Diffstat (limited to 'src/libstore/download.cc')
-rw-r--r-- | src/libstore/download.cc | 35 |
1 files changed, 27 insertions, 8 deletions
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 <curl/curl.h> @@ -221,10 +222,21 @@ ref<Downloader> makeDownloader() return make_ref<CurlDownloader>(); } -Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpack) +Path Downloader::downloadCached(ref<Store> 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> 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> 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> 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; } |