Write to temp file before renaming to the final name

This commit is contained in:
bjorn3 2022-12-02 13:05:10 +00:00
parent 0673cde5a3
commit e1edc13afb

View File

@ -10,6 +10,7 @@
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 @@ fn build_inner(self, output: &Path) -> io::Result<bool> {
})
}
let mut w = File::create(output)
.map_err(|err| io_error_context("failed to create archive file", err))?;
// 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(&mut w, &entries, true, archive_kind, true, false)?;
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())
}