Remove non-portable use of stat

Part of #10634
This commit is contained in:
Johannes Altmanninger 2024-08-05 13:09:24 +02:00
parent ff47c2c628
commit 0705446e6e
2 changed files with 12 additions and 7 deletions

View file

@ -774,7 +774,6 @@ impl EnvUniversal {
let real_path = wrealpath(&self.vars_path).unwrap_or_else(|| self.vars_path.clone()); let real_path = wrealpath(&self.vars_path).unwrap_or_else(|| self.vars_path.clone());
// Ensure we maintain ownership and permissions (#2176). // Ensure we maintain ownership and permissions (#2176).
// let mut sbuf : libc::stat = MaybeUninit::uninit();
if let Ok(md) = wstat(&real_path) { if let Ok(md) = wstat(&real_path) {
if unsafe { libc::fchown(private_fd.as_raw_fd(), md.uid(), md.gid()) } == -1 { if unsafe { libc::fchown(private_fd.as_raw_fd(), md.uid(), md.gid()) } == -1 {
FLOG!(uvar_file, "universal log fchown() failed"); FLOG!(uvar_file, "universal log fchown() failed");

View file

@ -2,12 +2,13 @@
// Everything in this module must be async-signal safe. // Everything in this module must be async-signal safe.
// That means no locking, no allocating, no freeing memory, etc! // That means no locking, no allocating, no freeing memory, etc!
use super::flog_safe::FLOG_SAFE; use super::flog_safe::FLOG_SAFE;
use crate::common::exit_without_destructors;
use crate::nix::getpid; use crate::nix::getpid;
use crate::redirection::Dup2List; use crate::redirection::Dup2List;
use crate::signal::signal_reset_handlers; use crate::signal::signal_reset_handlers;
use libc::{c_char, pid_t}; use crate::{common::exit_without_destructors, wutil::fstat};
use libc::{c_char, pid_t, O_RDONLY};
use std::ffi::CStr; use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;
/// The number of times to try to call fork() before giving up. /// The number of times to try to call fork() before giving up.
const FORK_LAPS: usize = 5; const FORK_LAPS: usize = 5;
@ -339,9 +340,14 @@ pub(crate) fn safe_report_exec_error(
// find must be errors from exec(). // find must be errors from exec().
let mut interpreter_buf = [b'\0'; 128]; let mut interpreter_buf = [b'\0'; 128];
if let Some(interpreter) = get_interpreter(actual_cmd, &mut interpreter_buf) { if let Some(interpreter) = get_interpreter(actual_cmd, &mut interpreter_buf) {
let mut buf: libc::stat = unsafe { std::mem::zeroed() }; let fd = unsafe { libc::open(interpreter.as_ptr(), O_RDONLY) };
let statret = unsafe { libc::stat(interpreter.as_ptr(), &mut buf) }; let md = if fd == -1 {
if statret != 0 || unsafe { libc::access(interpreter.as_ptr(), libc::X_OK) } != 0 { Err(())
} else {
fstat(fd).map_err(|_| ())
};
#[allow(clippy::useless_conversion)] // for mode
if md.is_err() || unsafe { libc::access(interpreter.as_ptr(), libc::X_OK) } != 0 {
// Detect Windows line endings and complain specifically about them. // Detect Windows line endings and complain specifically about them.
let interpreter = interpreter.to_bytes(); let interpreter = interpreter.to_bytes();
if interpreter.last() == Some(&b'\r') { if interpreter.last() == Some(&b'\r') {
@ -361,7 +367,7 @@ pub(crate) fn safe_report_exec_error(
"', which is not an executable command." "', which is not an executable command."
); );
} }
} else if buf.st_mode & libc::S_IFMT == libc::S_IFDIR { } else if md.unwrap().mode() & u32::from(libc::S_IFMT) == u32::from(libc::S_IFDIR) {
FLOG_SAFE!( FLOG_SAFE!(
exec, exec,
"Failed to execute process '", "Failed to execute process '",