use flashkraft_gui::{FlashKraft, Message};
use iced::{Settings, Task};
fn main() -> iced::Result {
#[cfg(unix)]
{
let real_uid = nix::unistd::getuid();
let effective_uid = nix::unistd::geteuid();
if effective_uid.is_root() {
flashkraft_core::flash_helper::set_real_uid(real_uid.as_raw());
} else {
#[cfg(not(test))]
try_reexec_as_root();
flashkraft_core::flash_helper::set_real_uid(real_uid.as_raw());
}
}
iced::application(
|| {
let initial_state = FlashKraft::new();
let initial_command = Task::perform(
flashkraft_core::commands::load_drives(),
Message::DrivesRefreshed,
);
(initial_state, initial_command)
},
FlashKraft::update,
FlashKraft::view,
)
.title("FlashKraft - OS Image Writer")
.subscription(FlashKraft::subscription)
.theme(|state: &FlashKraft| state.theme.clone())
.settings(Settings {
fonts: vec![iced_fonts::BOOTSTRAP_FONT_BYTES.into()],
..Default::default()
})
.window(iced::window::Settings {
size: iced::Size::new(1300.0, 700.0),
resizable: false,
decorations: true,
..Default::default()
})
.run()
}
#[cfg(all(unix, not(test)))]
fn try_reexec_as_root() {
use std::ffi::CString;
if std::env::var("FLASHKRAFT_ESCALATED").as_deref() == Ok("1") {
return;
}
let self_exe = match std::fs::read_link("/proc/self/exe").or_else(|_| {
std::env::current_exe()
}) {
Ok(p) => p,
Err(_) => return,
};
let self_exe_str = match self_exe.to_str() {
Some(s) => s.to_owned(),
None => return,
};
let extra_args: Vec<String> = std::env::args().skip(1).collect();
std::env::set_var("FLASHKRAFT_ESCALATED", "1");
if which_exists("sudo") {
let mut argv: Vec<CString> = Vec::new();
argv.push(c_str("sudo"));
argv.push(c_str("-E")); argv.push(c_str(&self_exe_str));
for arg in &extra_args {
argv.push(c_str(arg));
}
let _ = nix::unistd::execvp(&c_str("sudo"), &argv);
}
if which_exists("pkexec") {
let mut argv: Vec<CString> = Vec::new();
argv.push(c_str("pkexec"));
argv.push(c_str(&self_exe_str));
for arg in &extra_args {
argv.push(c_str(arg));
}
let _ = nix::unistd::execvp(&c_str("pkexec"), &argv);
}
std::env::remove_var("FLASHKRAFT_ESCALATED");
}
#[cfg(all(unix, not(test)))]
fn which_exists(name: &str) -> bool {
if let Ok(path_var) = std::env::var("PATH") {
for dir in path_var.split(':') {
let candidate = std::path::Path::new(dir).join(name);
if candidate.is_file() {
use std::os::unix::fs::PermissionsExt;
if let Ok(meta) = std::fs::metadata(&candidate) {
if meta.permissions().mode() & 0o111 != 0 {
return true;
}
}
}
}
}
false
}
#[cfg(all(unix, not(test)))]
fn c_str(s: &str) -> std::ffi::CString {
let sanitised: Vec<u8> = s.bytes().map(|b| if b == 0 { b'?' } else { b }).collect();
std::ffi::CString::new(sanitised).unwrap_or_else(|_| std::ffi::CString::new("?").unwrap())
}