From b94326a671f82c10e11773231a1023d1d0e8d17d Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Tue, 17 Feb 2026 15:14:34 -0700 Subject: [PATCH] Move away from .unwrap() --- src-tauri/src/lib.rs | 137 +++++++++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 50 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index fbf532e..fa3f577 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,33 +1,76 @@ use sha2::{Digest, Sha512}; +use std::fs::{remove_dir_all}; +use std::io::Cursor; use std::{ - fs::{self, remove_dir_all}, - io::Cursor, + fs::{File, create_dir_all}, + io::{copy}, path::PathBuf, - process::Command, + process::Command }; use tauri::{AppHandle, Manager}; use tauri_plugin_os::platform; use zip::ZipArchive; -fn unzip_to_dir(bytes: &[u8], target: &PathBuf) -> std::io::Result<()> { - let reader = Cursor::new(bytes); - let mut zip = ZipArchive::new(reader).unwrap(); +#[cfg(unix)] +use std::os::unix::fs::PermissionsExt; - for i in 0..zip.len() { - let mut file = zip.by_index(i).unwrap(); - let outpath = target.join(file.mangled_name()); +fn should_skip(name: &str) -> bool { + name.starts_with("__MACOSX/") + || name == "__MACOSX" + || name.ends_with("/.DS_Store") + || name.ends_with(".DS_Store") +} - if file.name().ends_with('/') { - fs::create_dir_all(&outpath)?; - } else { - if let Some(p) = outpath.parent() { - fs::create_dir_all(p)?; +async fn unzip_to_dir(bytes: &[u8], target: &PathBuf) -> String { + let bytes = bytes.to_vec(); + let target = target.clone(); + + let res = tauri::async_runtime::spawn_blocking(move || -> Result<(), String> { + let reader = Cursor::new(bytes); + let mut archive = ZipArchive::new(reader).map_err(|e| e.to_string())?; + + for i in 0..archive.len() { + let mut entry = archive.by_index(i).map_err(|e| e.to_string())?; + let name = entry.name(); + + if should_skip(name) { + continue; + } + + let outpath = target.join(name); + + if entry.is_dir() { + create_dir_all(&outpath).map_err(|e| e.to_string())?; + + #[cfg(unix)] + if let Some(mode) = entry.unix_mode() { + std::fs::set_permissions(&outpath, std::fs::Permissions::from_mode(mode)) + .map_err(|e| e.to_string())?; + } + } else { + if let Some(parent) = outpath.parent() { + create_dir_all(parent).map_err(|e| e.to_string())?; + } + + let mut outfile = File::create(&outpath).map_err(|e| e.to_string())?; + copy(&mut entry, &mut outfile).map_err(|e| e.to_string())?; + + #[cfg(unix)] + if let Some(mode) = entry.unix_mode() { + std::fs::set_permissions(&outpath, std::fs::Permissions::from_mode(mode)) + .map_err(|e| e.to_string())?; + } } - let mut outfile = fs::File::create(&outpath)?; - std::io::copy(&mut file, &mut outfile)?; } + + Ok(()) + }) + .await; + + match res { + Ok(Ok(())) => "1".into(), + _ => "-1".into(), } - Ok(()) } fn get_sha512_hash(data: &[u8]) -> String { @@ -54,60 +97,51 @@ async fn download(app: AppHandle, url: String, hash: String) -> String { return "-2".to_string(); } - let bin_path = app.path().app_local_data_dir().unwrap().join("bin"); + let bin_path = match app.path().app_local_data_dir() { + Ok(p) => p.join("bin"), + Err(_) => return "-1".to_string(), + }; let _ = tokio::fs::create_dir_all(&bin_path).await; - if let Err(_) = unzip_to_dir(&bytes, &bin_path) { - return "-3".to_string(); + let unzip_res = unzip_to_dir(&bytes, &bin_path).await; + if unzip_res == "-1" { + return "-1".to_string(); } drop(bytes); - #[cfg(any(target_os = "linux", target_os = "macos"))] - { - use std::{fs, os::unix::fs::PermissionsExt}; - - let executable_path = if cfg!(target_os = "linux") { - bin_path.join("lncvrt-games-launcher") - } else { - bin_path - .join("Lncvrt Games Launcher.app") - .join("Contents") - .join("MacOS") - .join("lncvrt-games-launcher") - }; - - let mut perms = fs::metadata(&executable_path).unwrap().permissions(); - perms.set_mode(0o755); - fs::set_permissions(&executable_path, perms).unwrap(); - } - return "1".to_string(); } #[allow(unused_variables)] #[tauri::command] fn load(app: AppHandle) { - let bin_path = app.path().app_local_data_dir().unwrap().join("bin"); + let bin_path = match app.path().app_local_data_dir() { + Ok(p) => p.join("bin"), + Err(_) => return, + }; if !bin_path.exists() { return; } if platform() == "macos" { - Command::new("open") + if let Err(_) = Command::new("open") .arg("Lncvrt Games Launcher.app") .current_dir(&bin_path) - .spawn() - .unwrap(); + .spawn() { + eprintln!("Failed to launch game on macOS"); + } } else if platform() == "linux" { - Command::new("./lncvrt-games-launcher") + if let Err(_) = Command::new("./lncvrt-games-launcher") .current_dir(&bin_path) - .spawn() - .unwrap(); + .spawn() { + eprintln!("Failed to launch game on macOS"); + } } else if platform() == "windows" { - Command::new(&bin_path.join("lncvrt-games-launcher.exe")) + if let Err(_) = Command::new(&bin_path.join("lncvrt-games-launcher.exe")) .current_dir(&bin_path) - .spawn() - .unwrap(); + .spawn() { + eprintln!("Failed to launch game on macOS"); + } } app.exit(0); @@ -117,7 +151,10 @@ fn load(app: AppHandle) { pub fn run() { tauri::Builder::default() .setup(|app| { - let app_local_data_dir = app.path().app_local_data_dir().unwrap(); + let app_local_data_dir = match app.path().app_local_data_dir() { + Ok(p) => p, + Err(_) => return Ok(()), + }; let downloads_dir = app_local_data_dir.join("downloads"); let updates_dir = app_local_data_dir.join("updates"); let bin_dir = app_local_data_dir.join("bin");