about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/download.rs38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 8e9614ec89a..2a0dec75599 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -320,25 +320,43 @@ impl Config {
     }
 
     /// Returns whether the SHA256 checksum of `path` matches `expected`.
-    fn verify(&self, path: &Path, expected: &str) -> bool {
+    pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
         use sha2::Digest;
 
         self.verbose(&format!("verifying {}", path.display()));
+
+        if self.dry_run() {
+            return false;
+        }
+
         let mut hasher = sha2::Sha256::new();
-        // FIXME: this is ok for rustfmt (4.1 MB large at time of writing), but it seems memory-intensive for rustc and larger components.
-        // Consider using streaming IO instead?
-        let contents = if self.dry_run() { vec![] } else { t!(fs::read(path)) };
-        hasher.update(&contents);
-        let found = hex::encode(hasher.finalize().as_slice());
-        let verified = found == expected;
-        if !verified && !self.dry_run() {
+
+        let file = t!(File::open(path));
+        let mut reader = BufReader::new(file);
+
+        loop {
+            let buffer = t!(reader.fill_buf());
+            let l = buffer.len();
+            // break if EOF
+            if l == 0 {
+                break;
+            }
+            hasher.update(buffer);
+            reader.consume(l);
+        }
+
+        let checksum = hex::encode(hasher.finalize().as_slice());
+        let verified = checksum == expected;
+
+        if !verified {
             println!(
                 "invalid checksum: \n\
-                found:    {found}\n\
+                found:    {checksum}\n\
                 expected: {expected}",
             );
         }
-        return verified;
+
+        verified
     }
 }