Skip to content

Commit e6dd3c8

Browse files
authored
Merge pull request #2183 from lzutao/sudo-check
Simplify sudo check on unix
2 parents d6366cb + 6551379 commit e6dd3c8

File tree

2 files changed

+54
-50
lines changed

2 files changed

+54
-50
lines changed

src/cli/self_update.rs

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ pub fn install(no_prompt: bool, verbose: bool, quiet: bool, mut opts: InstallOpt
238238
do_pre_install_sanity_checks()?;
239239
do_pre_install_options_sanity_checks(&opts)?;
240240
check_existence_of_rustc_or_cargo_in_path(no_prompt)?;
241+
#[cfg(unix)]
241242
do_anti_sudo_check(no_prompt)?;
242243

243244
let mut term = term2::stdout();
@@ -467,63 +468,33 @@ fn do_pre_install_options_sanity_checks(opts: &InstallOpts) -> Result<()> {
467468
// If the user is trying to install with sudo, on some systems this will
468469
// result in writing root-owned files to the user's home directory, because
469470
// sudo is configured not to change $HOME. Don't let that bogosity happen.
470-
#[allow(dead_code)]
471+
#[cfg(unix)]
471472
fn do_anti_sudo_check(no_prompt: bool) -> Result<()> {
472-
use std::ffi::OsString;
473-
474-
#[cfg(unix)]
475-
pub fn home_mismatch() -> (bool, OsString, String) {
476-
use std::ffi::CStr;
477-
use std::mem::MaybeUninit;
478-
use std::ptr;
479-
473+
pub fn home_mismatch() -> (bool, PathBuf, PathBuf) {
474+
let fallback = || (false, PathBuf::new(), PathBuf::new());
480475
// test runner should set this, nothing else
481-
if let Ok(true) = env::var("RUSTUP_INIT_SKIP_SUDO_CHECK").map(|s| s == "yes") {
482-
return (false, OsString::new(), String::new());
483-
}
484-
let mut buf = [0u8; 1024];
485-
let mut pwd = MaybeUninit::<libc::passwd>::uninit();
486-
let mut pwdp: *mut libc::passwd = ptr::null_mut();
487-
let rv = unsafe {
488-
libc::getpwuid_r(
489-
libc::geteuid(),
490-
pwd.as_mut_ptr(),
491-
buf.as_mut_ptr().cast::<libc::c_char>(),
492-
buf.len(),
493-
(&mut pwdp) as *mut *mut libc::passwd,
494-
)
495-
};
496-
if rv != 0 || pwdp.is_null() {
497-
warn!("getpwuid_r: couldn't get user data");
498-
return (false, OsString::new(), String::new());
476+
if env::var_os("RUSTUP_INIT_SKIP_SUDO_CHECK").map_or(false, |s| s == "yes") {
477+
return fallback();
499478
}
500-
let pwd = unsafe { pwd.assume_init() };
501-
let pw_dir = unsafe { CStr::from_ptr(pwd.pw_dir) }.to_str().ok();
502-
let env_home = env::var_os("HOME");
503-
match (env_home, pw_dir) {
504-
(None, _) | (_, None) => (false, OsString::new(), String::new()),
505-
(Some(eh), Some(pd)) => (eh != pd, eh, String::from(pd)),
506-
}
507-
}
508479

509-
#[cfg(not(unix))]
510-
pub fn home_mismatch() -> (bool, OsString, String) {
511-
(false, OsString::new(), String::new())
480+
match (utils::home_dir_from_passwd(), env::var_os("HOME")) {
481+
(Some(pw), Some(eh)) if eh != pw => return (true, PathBuf::from(eh), pw),
482+
(None, _) => warn!("getpwuid_r: couldn't get user data"),
483+
_ => {}
484+
}
485+
fallback()
512486
}
513487

514-
match (home_mismatch(), no_prompt) {
515-
((false, _, _), _) => (),
516-
((true, env_home, euid_home), false) => {
488+
match home_mismatch() {
489+
(false, _, _) => {}
490+
(true, env_home, euid_home) => {
517491
err!("$HOME differs from euid-obtained home directory: you may be using sudo");
518-
err!("$HOME directory: {:?}", env_home);
519-
err!("euid-obtained home directory: {}", euid_home);
520-
err!("if this is what you want, restart the installation with `-y'");
521-
process::exit(1);
522-
}
523-
((true, env_home, euid_home), true) => {
524-
warn!("$HOME differs from euid-obtained home directory: you may be using sudo");
525-
warn!("$HOME directory: {:?}", env_home);
526-
warn!("euid-obtained home directory: {}", euid_home);
492+
err!("$HOME directory: {}", env_home.display());
493+
err!("euid-obtained home directory: {}", euid_home.display());
494+
if !no_prompt {
495+
err!("if this is what you want, restart the installation with `-y'");
496+
process::exit(1);
497+
}
527498
}
528499
}
529500

src/utils/utils.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,39 @@ impl<'a> io::Read for FileReaderWithProgress<'a> {
670670
}
671671
}
672672

673+
// search user database to get home dir of euid user
674+
#[cfg(unix)]
675+
pub fn home_dir_from_passwd() -> Option<PathBuf> {
676+
use std::ffi::CStr;
677+
use std::mem::MaybeUninit;
678+
use std::os::unix::ffi::OsStringExt;
679+
use std::ptr;
680+
unsafe {
681+
let init_size = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
682+
-1 => 1024,
683+
n => n as usize,
684+
};
685+
let mut buf = Vec::with_capacity(init_size);
686+
let mut pwd: MaybeUninit<libc::passwd> = MaybeUninit::uninit();
687+
let mut pwdp = ptr::null_mut();
688+
match libc::getpwuid_r(
689+
libc::geteuid(),
690+
pwd.as_mut_ptr(),
691+
buf.as_mut_ptr(),
692+
buf.capacity(),
693+
&mut pwdp,
694+
) {
695+
0 if !pwdp.is_null() => {
696+
let pwd = pwd.assume_init();
697+
let bytes = CStr::from_ptr(pwd.pw_dir).to_bytes().to_vec();
698+
let pw_dir = OsString::from_vec(bytes);
699+
Some(PathBuf::from(pw_dir))
700+
}
701+
_ => None,
702+
}
703+
}
704+
}
705+
673706
#[cfg(test)]
674707
mod tests {
675708
use super::*;

0 commit comments

Comments
 (0)