#![forbid(unsafe_code)]
#![allow(non_snake_case)]
use windows_sys::Win32::UI::Shell::FOLDERID_ProgramData;
use windows_sys::Win32::UI::Shell::FOLDERID_Profile;
use windows_sys::core::GUID;
use std::path::{Path, PathBuf};
use std::process::ExitCode;
#[cfg(not(target_os = "windows"))]
fn main() -> ExitCode {
println!("This program is supported only on Windows.");
ExitCode::From(3)
}
fn main() -> ExitCode {
let global_i2pd = dirs_sys::known_folder(FOLDERID_ProgramData).map_or(false, |f| detect_scoop_i2pd(&f));
let user_i2pd = dirs_sys::known_folder(FOLDERID_Profile).map_or(false, |f| detect_scoop_i2pd(&f));
if !( global_i2pd || user_i2pd ) {
println!("no scoop i2pd install detected.");
ExitCode::from(1)
} else {
println!("scoop i2pd installation detected: global {}, user {}.", global_i2pd, user_i2pd);
let workdir = { if user_i2pd { get_scoop_i2pd_dir( FOLDERID_Profile ) }
else { get_scoop_i2pd_dir( FOLDERID_ProgramData ) }
};
let exefile = { let mut p = PathBuf::from(&workdir);p.push(I2PD_EXE); p };
if !exefile.exists() {
println!("Error: {} not exists / might have been deleted by antivirus.", I2PD_EXE);
return ExitCode::from(2);
}
std::env::set_current_dir(&workdir).expect("Failed to change working directory to scoop i2pd installation.");
let mut TO_RETRY = Vec::new();
for file in TO_DELETE.iter() {
let file_path = workdir.join(file);
if file_path.exists() {
let rc = std::fs::remove_file(&file_path);
if rc.is_err() {
eprintln!("Can not delete {}, will retry.", file_path.display());
TO_RETRY.push(file_path);
}
}
}
let mut RETRY_COUNTER = 5;
while TO_RETRY.is_empty() == false && RETRY_COUNTER > 0 {
std::thread::sleep(std::time::Duration::from_secs(5));
RETRY_COUNTER -= 1;
TO_RETRY.retain(|file_path| {
if file_path.exists() {
match std::fs::remove_file(file_path) {
Ok(()) => {
eprintln!("Successfully deleted {}", file_path.display());
false }
Err(_) => {
eprintln!("Still cannot delete {}", file_path.display());
true }
}
} else {
false }
});
};
if !TO_RETRY.is_empty() {
eprintln!("Unable to delete all i2pd state files, no more retries left. Will continue.");
};
println!("starting {}", I2PD_EXE);
std::process::Command::new(I2PD_EXE).spawn().expect("Failed to launch i2pd");
ExitCode::SUCCESS
}
}
fn get_scoop_i2pd_dir(folder: GUID) -> PathBuf {
let mut f = dirs_sys::known_folder(folder).unwrap();
f.push(SCOOP_I2PD_INSTALL);
f
}
fn detect_scoop_i2pd(search: impl AsRef<Path>) -> bool {
#[cfg(debug_assertions)]
println!("Testing {}", search.as_ref().display());
let mut p = PathBuf::from(search.as_ref());
if p.is_dir() {
p.push(SCOOP_I2PD_INSTALL);
#[cfg(debug_assertions)]
println!("Testing2 {}", p.display());
p.is_dir()
} else {
false
}
}
const TO_DELETE: [&str; 5] = [ "i2pd.log", "ntcp2.keys", "ssu2.keys", "router.info", "router.keys" ];
const SCOOP_I2PD_INSTALL: &str = "scoop\\apps\\i2pd\\current";
const I2PD_EXE: &str = "i2pd.exe";