about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2022-12-02 13:05:10 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2022-12-02 13:18:20 +0000
commite1edc13afbf7c531432e438c5d95086804d4a4ba (patch)
treeb2647cc9f3183f7bd15ad4bf7a83b2b45e3261dc
parent0673cde5a36db203f18941c125a1665184e056ed (diff)
downloadrust-e1edc13afbf7c531432e438c5d95086804d4a4ba.tar.gz
rust-e1edc13afbf7c531432e438c5d95086804d4a4ba.zip
Write to temp file before renaming to the final name
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs26
1 files changed, 22 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 280fa49e29b..8274caa42bc 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -10,6 +10,7 @@ pub use ar_archive_writer::get_native_object_symbols;
 use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
 use object::read::archive::ArchiveFile;
 use object::read::macho::FatArch;
+use tempfile::Builder as TempFileBuilder;
 
 use std::error::Error;
 use std::fs::File;
@@ -271,10 +272,27 @@ impl<'a> ArArchiveBuilder<'a> {
             })
         }
 
-        let mut w = File::create(output)
-            .map_err(|err| io_error_context("failed to create archive file", err))?;
-
-        write_archive_to_stream(&mut w, &entries, true, archive_kind, true, false)?;
+        // Write to a temporary file first before atomically renaming to the final name.
+        // This prevents programs (including rustc) from attempting to read a partial archive.
+        // It also enables writing an archive with the same filename as a dependency on Windows as
+        // required by a test.
+        let mut archive_tmpfile = TempFileBuilder::new()
+            .suffix(".temp-archive")
+            .tempfile_in(output.parent().unwrap_or_else(|| Path::new("")))
+            .map_err(|err| io_error_context("couldn't create a temp file", err))?;
+
+        write_archive_to_stream(
+            archive_tmpfile.as_file_mut(),
+            &entries,
+            true,
+            archive_kind,
+            true,
+            false,
+        )?;
+
+        archive_tmpfile
+            .persist(output)
+            .map_err(|err| io_error_context("failed to rename archive file", err.error))?;
 
         Ok(!entries.is_empty())
     }