diff --git a/Cargo.lock b/Cargo.lock index a6f6792..762d81e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,6 +385,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "erased-serde" version = "0.3.25" @@ -985,6 +997,7 @@ dependencies = [ "serde_json", "serde_with", "strum", + "sysctl", "tar", "target-lexicon", "tempfile", @@ -1411,6 +1424,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.21" @@ -1649,6 +1671,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysctl" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed66d6a2ccbd656659289bc90767895b7abbdec897a0fc6031aca3ed1cb51d3e" +dependencies = [ + "bitflags", + "byteorder", + "enum-as-inner", + "libc", + "thiserror", + "walkdir", +] + [[package]] name = "tar" version = "0.4.38" @@ -2025,6 +2061,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 8069c66..da63502 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ is_ci = { version = "1.1.1", default-features = false, optional = true } strum = { version = "0.24.1", features = ["derive"] } nix-config-parser = { version = "0.1.2", features = ["serde"] } which = "4.4.0" +sysctl = "0.5.4" [dev-dependencies] eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] } diff --git a/src/planner/macos.rs b/src/planner/macos.rs index 331b6cb..343dfed 100644 --- a/src/planner/macos.rs +++ b/src/planner/macos.rs @@ -87,6 +87,8 @@ impl Planner for Macos { } async fn plan(&self) -> Result>>, PlannerError> { + ensure_not_running_in_rosetta().await?; + let root_disk = match &self.root_disk { root_disk @ Some(_) => root_disk.clone(), None => { @@ -214,3 +216,23 @@ impl Into for Macos { BuiltinPlanner::Macos(self) } } + +async fn ensure_not_running_in_rosetta() -> Result<(), PlannerError> { + use sysctl::{Ctl, Sysctl}; + const CTLNAME: &str = "sysctl.proc_translated"; + + match Ctl::new(CTLNAME) { + // This Mac doesn't have Rosetta! + Err(sysctl::SysctlError::NotFound(_)) => (), + Err(e) => Err(e)?, + Ok(ctl) => { + let str_val = ctl.value_string()?; + + if str_val == "1" { + return Err(PlannerError::RosettaDetected); + } + }, + } + + Ok(()) +} diff --git a/src/planner/mod.rs b/src/planner/mod.rs index fe10573..8417bda 100644 --- a/src/planner/mod.rs +++ b/src/planner/mod.rs @@ -298,6 +298,10 @@ pub enum PlannerError { /// A MacOS (Darwin) plist related error #[error(transparent)] Plist(#[from] plist::Error), + #[error(transparent)] + Sysctl(#[from] sysctl::SysctlError), + #[error("Detected that this process is running under Rosetta, using Nix in Rosetta is not supported (Please open an issue with your use case)")] + RosettaDetected, /// A Linux SELinux related error #[error("This installer doesn't yet support SELinux in `Enforcing` mode. If SELinux is important to you, please see https://github.com/DeterminateSystems/nix-installer/issues/124. You can also try again after setting SELinux to `Permissive` mode with `setenforce Permissive`")] SelinuxEnforcing, @@ -322,6 +326,8 @@ impl HasExpectedErrors for PlannerError { PlannerError::Action(_) => None, PlannerError::InstallSettings(_) => None, PlannerError::Plist(_) => None, + PlannerError::Sysctl(_) => None, + this @ PlannerError::RosettaDetected => Some(Box::new(this)), PlannerError::Utf8(_) => None, PlannerError::SelinuxEnforcing => Some(Box::new(self)), PlannerError::Custom(_) => None,