Rollup merge of #122723 - bjorn3:archive_writer_fixes, r=nnethercote

Use same file permissions for ar_archive_writer as the LLVM archive writer

This is required to switch to ar_archive_writer in the future without regressions. In addition to this PR support for reading thin archives needs to be added (https://github.com/rust-lang/rust/issues/107407) to fix all known regressions.

Fixes https://github.com/rust-lang/rust/issues/107495
This commit is contained in:
Matthias Krüger 2024-04-17 18:01:38 +02:00 committed by GitHub
commit d5258af4c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 8 deletions

View File

@ -13,7 +13,7 @@
use tempfile::Builder as TempFileBuilder;
use std::error::Error;
use std::fs::File;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@ -280,12 +280,21 @@ fn build_inner(self, output: &Path) -> io::Result<bool> {
// 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()
// The tempfile crate currently uses 0o600 as mode for the temporary files and directories
// it creates. We need it to be the default mode for back compat reasons however. (See
// #107495) To handle this we are telling tempfile to create a temporary directory instead
// and then inside this directory create a file using File::create.
let archive_tmpdir = 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))?;
.tempdir_in(output.parent().unwrap_or_else(|| Path::new("")))
.map_err(|err| {
io_error_context("couldn't create a directory for the temp file", err)
})?;
let archive_tmpfile_path = archive_tmpdir.path().join("tmp.a");
let mut archive_tmpfile = File::create_new(&archive_tmpfile_path)
.map_err(|err| io_error_context("couldn't create the temp file", err))?;
write_archive_to_stream(archive_tmpfile.as_file_mut(), &entries, archive_kind, false)?;
write_archive_to_stream(&mut archive_tmpfile, &entries, archive_kind, false)?;
let any_entries = !entries.is_empty();
drop(entries);
@ -293,9 +302,11 @@ fn build_inner(self, output: &Path) -> io::Result<bool> {
// output archive to the same location as an input archive on Windows.
drop(self.src_archives);
archive_tmpfile
.persist(output)
.map_err(|err| io_error_context("failed to rename archive file", err.error))?;
fs::rename(archive_tmpfile_path, output)
.map_err(|err| io_error_context("failed to rename archive file", err))?;
archive_tmpdir
.close()
.map_err(|err| io_error_context("failed to remove temporary directory", err))?;
Ok(any_entries)
}

View File

@ -0,0 +1 @@
// Empty

View File

@ -0,0 +1,31 @@
#![feature(rustc_private)]
#[cfg(unix)]
extern crate libc;
extern crate run_make_support;
use run_make_support::{aux_build, tmp_dir};
use std::fs;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
fn main() {
#[cfg(unix)]
unsafe {
libc::umask(0o002);
}
aux_build().arg("foo.rs").run();
verify(&tmp_dir().join("libfoo.rlib"));
}
fn verify(path: &Path) {
let perm = fs::metadata(path).unwrap().permissions();
assert!(!perm.readonly());
// Check that the file is readable for everyone
#[cfg(unix)]
assert_eq!(perm.mode(), 0o100664);
}