Skip to content

Commit 65d8f24

Browse files
dilawarXenira
andcommitted
Use libc to check if current user is sudo
since libc is already in cargo.lock Update crates/cli/src/lib.rs Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs comment -> doc Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs comment -> doc Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs remove commented out line Co-authored-by: Xenira <[email protected]> Update crates/cli/src/lib.rs Co-authored-by: Xenira <[email protected]>
1 parent 8548205 commit 65d8f24

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

crates/cli/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ dialoguer = "0.11"
1919
libloading = "0.8"
2020
cargo_metadata = "0.20"
2121
semver = "1.0"
22-
elevate = "0.6.1"
22+
23+
[target.'cfg(unix)'.dependencies]
24+
libc = "0.2"
2325

2426
[lints.rust]
2527
missing_docs = "warn"

crates/cli/src/lib.rs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ struct Remove {
142142
/// Whether to bypass the remove prompt.
143143
#[clap(long)]
144144
yes: bool,
145+
#[cfg(unix)]
145146
/// Whether to bypass the root check
146147
#[clap(long)]
147148
bypass_root_check: bool,
@@ -198,12 +199,11 @@ impl Install {
198199
self.no_default_features,
199200
)?;
200201

201-
if !self.bypass_root_check {
202-
anyhow::ensure!(
203-
elevate::check() == elevate::RunningAs::User,
204-
"Running as root is not recommended. Use --bypass-root-check to override."
205-
);
206-
}
202+
#[cfg(unix)]
203+
anyhow::ensure!(
204+
self.bypass_root_check || !is_root(),
205+
"Running as root is not recommended. Use --bypass-root-check to override."
206+
);
207207

208208
let (mut ext_dir, mut php_ini) = if let Some(install_dir) = self.install_dir {
209209
(install_dir, None)
@@ -246,10 +246,10 @@ impl Install {
246246
}
247247
}
248248

249-
// Update extension information in the ini file, if fails, try with sudo again.
250-
//
251-
// Write to a temp file then move it to given path. Use `sudo` on unix to move
252-
// file if needed.
249+
/// Update extension line in the ini file.
250+
///
251+
/// Write to a temp file then copy it to a given path. If this fails, then try
252+
/// `sudo mv` on unix.
253253
fn update_ini_file(php_ini: &PathBuf, ext_name: &str, disable: bool) -> anyhow::Result<()> {
254254
let current_ini_content = std::fs::read_to_string(php_ini)?;
255255
let mut ext_line = format!("extension={ext_name}");
@@ -267,25 +267,29 @@ fn update_ini_file(php_ini: &PathBuf, ext_name: &str, disable: bool) -> anyhow::
267267
}
268268

269269
new_lines.push(&ext_line);
270+
270271
write_to_file(new_lines.join("\n"), php_ini)?;
271272
Ok(())
272273
}
273274

274-
// Copy extension, if fails, try with sudo cp.
275-
//
276-
// Checking if we have write permission for ext_dir may fail due to ACL, group
277-
// list and and other nuances. See
278-
// https://doc.rust-lang.org/std/fs/struct.Permissions.html#method.readonly
275+
/// Copy extension, if fails, try with sudo cp.
276+
///
277+
/// Checking if we have write permission for ext_dir may fail due to ACL, group
278+
/// list and and other nuances. See
279+
/// https://doc.rust-lang.org/std/fs/struct.Permissions.html#method.readonly.
279280
fn copy_extension(ext_path: &Utf8PathBuf, ext_dir: &PathBuf) -> anyhow::Result<()> {
280281
if let Err(_e) = std::fs::copy(ext_path, ext_dir) {
281282
#[cfg(unix)]
282283
{
283-
let _ = std::process::Command::new("sudo")
284+
let s = std::process::Command::new("sudo")
284285
.arg("cp")
285286
.arg(ext_path)
286287
.arg(ext_dir)
287288
.status()?;
289+
anyhow::ensure!(s.success(), "Failed to copy extension");
288290
}
291+
#[cfg(not(unix))]
292+
anyhow::bail!("Failed to copy extension: {_e}");
289293
}
290294
Ok(())
291295
}
@@ -599,28 +603,27 @@ fn build_ext(
599603
bail!("Failed to retrieve extension path from artifact")
600604
}
601605

602-
// Write given string to a given filepath.
603-
//
604-
// - Write to a temp file first.
605-
// - Copy the temp file to the given filepath.
606-
// - If it fails, move tempfile using `sudo mv`.
607-
//
608-
// TODO: Try with sudo when error is permission related.
606+
/// Write content to a given filepath.
607+
///
608+
/// We may not have write permission but we may have sudo privilege on unix. So
609+
/// we write to a temp file and then try moving it to given filepath, and retry
610+
/// with sudo on unix.
609611
fn write_to_file(content: String, filepath: &PathBuf) -> anyhow::Result<()> {
610612
// write to a temp file
611613
let tempf = std::env::temp_dir().join("__tmp_cargo_php");
612614
std::fs::write(&tempf, content)?;
613615

614-
// Now move. `rename` will overwrite existing file.
616+
// Now try moving, `rename` will overwrite existing file.
615617
if std::fs::rename(&tempf, filepath).is_err() {
616618
#[cfg(unix)]
617619
{
618620
// if not successful, try with sudo on unix.
619-
let _ = std::process::Command::new("sudo")
621+
let s = std::process::Command::new("sudo")
620622
.arg("mv")
621623
.arg(&tempf)
622624
.arg(filepath)
623625
.status()?;
626+
anyhow::ensure!(s.success(), "Falied to write to {filepath:?}");
624627
}
625628

626629
#[cfg(not(unix))]
@@ -629,3 +632,14 @@ fn write_to_file(content: String, filepath: &PathBuf) -> anyhow::Result<()> {
629632

630633
Ok(())
631634
}
635+
636+
#[cfg(unix)]
637+
fn is_root() -> bool {
638+
let uid = unsafe { libc::getuid() };
639+
let euid = unsafe { libc::geteuid() };
640+
641+
match (uid, euid) {
642+
(_, 0) => true, // suid set
643+
(_, _) => false,
644+
}
645+
}

0 commit comments

Comments
 (0)