#[cfg(any(target_os = "macos", target_os = "windows"))]
use std::process::Command;
const APP_SALT: &str = "canboat";
pub fn get_machine_id() -> u64 {
let raw = machine_string().unwrap_or_default();
fnv1a_64(format!("{APP_SALT}|{raw}").as_bytes())
}
fn fnv1a_64(bytes: &[u8]) -> u64 {
let mut hash: u64 = 0xcbf2_9ce4_8422_2325; for &b in bytes {
hash ^= b as u64;
hash = hash.wrapping_mul(0x0000_0100_0000_01b3); }
hash
}
#[cfg(target_os = "linux")]
fn machine_string() -> Option<String> {
for p in ["/etc/machine-id", "/var/lib/dbus/machine-id"] {
if let Ok(s) = std::fs::read_to_string(p) {
let s = s.trim().to_string();
if !s.is_empty() {
return Some(s);
}
}
}
None
}
#[cfg(target_os = "macos")]
fn machine_string() -> Option<String> {
let out = Command::new("ioreg")
.args(["-rd1", "-c", "IOPlatformExpertDevice"])
.output()
.ok()?;
let text = String::from_utf8_lossy(&out.stdout);
let line = text.lines().find(|l| l.contains("IOPlatformUUID"))?;
let start = line.find("= \"")? + 3;
let end = line[start..].find('"')? + start;
Some(line[start..end].to_string())
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
fn machine_string() -> Option<String> {
None
}
#[cfg(target_os = "windows")]
fn machine_string() -> Option<String> {
let out = Command::new("reg")
.args([
"query",
r"HKLM\SOFTWARE\Microsoft\Cryptography",
"/v",
"MachineGuid",
])
.output()
.ok()?;
let text = String::from_utf8_lossy(&out.stdout);
let line = text.lines().find(|l| l.contains("MachineGuid"))?;
Some(line.split_whitespace().last()?.to_string())
}