Skip to content

Commit

Permalink
fix(updater): allow to use elevated permission to copy and override core
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat616 committed Dec 29, 2023
1 parent 9e1d76e commit 6c992b7
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 25 deletions.
2 changes: 1 addition & 1 deletion backend/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ rs-snowflake = "0.6"
rocksdb = "0.21"
thiserror = { workspace = true, version = "1.0" }
simd-json = "0.13.4"
runas = "=1.0.0" # blocked by https://github.com/mitsuhiko/rust-runas/issues/13

[target.'cfg(windows)'.dependencies]
runas = "=1.0.0" # blocked by https://github.com/mitsuhiko/rust-runas/issues/13
deelevate = "0.2.0"
winreg = { version = "0.50", features = ["transactions"] }
windows-sys = { version = "0.48", features = [
Expand Down
92 changes: 68 additions & 24 deletions backend/tauri/src/core/updater.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::{collections::HashMap, io::Cursor, path::Path, sync::OnceLock};

use super::CoreManager;
use crate::config::ClashCore;
use anyhow::{anyhow, Result};
use gunzip::Decompressor;
use log::debug;
use serde::{de, Deserialize, Serialize};
use log::{debug, warn};
use runas::Command as RunasCommand;
use serde::{Deserialize, Serialize};
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
use tempfile::{tempdir, TempDir};
use tokio::{join, sync::RwLock, task::spawn_blocking};
use zip::ZipArchive;

use super::CoreManager;

pub struct Updater {
manifest_version: ManifestVersion,
mirror: String,
Expand Down Expand Up @@ -123,14 +123,15 @@ impl Updater {
self.mirror.as_str(),
"MetaCubeX/mihomo/releases/download/Prerelease-Alpha/version.txt"
);
Ok(client
.get(url)
.send()
.await?
.text()
.await?
.trim()
.to_string())
let res = client.get(url).send().await?;
let status_code = res.status();
if !status_code.is_success() {
anyhow::bail!(
"failed to get mihomo alpha version: response status is {}, expected 200",
status_code
);
}
Ok(res.text().await?.trim().to_string())
}

pub async fn update_core(&self, core_type: &ClashCore) -> Result<()> {
Expand Down Expand Up @@ -165,10 +166,42 @@ impl Updater {
let core_dir = core_dir.parent().ok_or(anyhow!("failed to get core dir"))?;
let target_core = core_dir.join(target_core);
debug!("copying core to {:?}", target_core);
std::fs::copy(
tmp_dir.path().join(core_type.clone().to_string()),
target_core,
)?;
let tmp_core_path = tmp_dir.path().join(core_type.clone().to_string());
match std::fs::copy(tmp_core_path.clone(), target_core.clone()) {
Ok(_) => {}
Err(err) => {
warn!(
"failed to copy core: {}, trying to use elevated permission to copy and override core",
err
);
#[cfg(target_os = "windows")]
{
// 防止 UAC 弹窗堵塞主线程
tokio::task::spawn_blocking(move || {
RunasCommand::new("cmd")
.args(&[
"/C",
"copy",
"/Y",
tmp_core_path.to_str().unwrap(),
target_core.to_str().unwrap(),
])
.status()
})
.await??;
}
#[cfg(not(target_os = "windows"))]
{
RunasCommand::new("cp")
.args(&[
"-f",
tmp_core_path.to_str().unwrap(),
target_core.to_str().unwrap(),
])
.status()?;
}
}
};

// 5. if core is used before, restart it
if current_core == *core_type {
Expand Down Expand Up @@ -235,7 +268,15 @@ impl Updater {
let mut dst = std::fs::File::create(&file_path)?;

let client = reqwest::Client::new();
let mut buff = Cursor::new(client.get(url).send().await?.bytes().await?);
let res = client.get(url).send().await?;
let status_code = res.status();
if !status_code.is_success() {
anyhow::bail!(
"failed to download core: response status is {}, expected 200",
status_code
);
}
let mut buff = Cursor::new(res.bytes().await?);
std::io::copy(&mut buff, &mut dst)?;
Ok(artifact)
}
Expand Down Expand Up @@ -284,7 +325,7 @@ fn decompress_and_set_permission(
};
let tmp_core = tmp_path.join(core_type.clone().to_string());
debug!("writing core to {:?} ({} bytes)", tmp_core, buff.len());
let mut core_file = std::fs::File::create(tmp_core.to_owned())?;
let mut core_file = std::fs::File::create(&tmp_core)?;
std::io::copy(&mut buff.as_slice(), &mut core_file)?;
#[cfg(target_family = "unix")]
{
Expand All @@ -300,12 +341,15 @@ pub async fn get_latest_version_manifest(mirror: &str) -> Result<ManifestVersion
);
log::debug!("{}", url);
let client = reqwest::Client::new();
Ok(client
.get(url)
.send()
.await?
.json::<ManifestVersion>()
.await?)
let res = client.get(url).send().await?;
let status_code = res.status();
if !status_code.is_success() {
anyhow::bail!(
"failed to get latest version manifest: response status is {}, expected 200",
status_code
);
}
Ok(res.json::<ManifestVersion>().await?)
}

enum CoreTypeMeta {
Expand Down

0 comments on commit 6c992b7

Please sign in to comment.