Skip to content

Commit

Permalink
Merge pull request #145 from gngpp/fix
Browse files Browse the repository at this point in the history
feat: Fix the problem caused by the daemon process discarding permissions
  • Loading branch information
0x676e67 authored Mar 12, 2024
2 parents bc6f445 + 43868fc commit 48d3bf5
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 74 deletions.
5 changes: 3 additions & 2 deletions src/asset/libc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use anyhow::Result;

#[cfg(target_arch = "x86_64")]
#[derive(rust_embed::RustEmbed)]
#[folder = "src/libc/x86_64/"]
Expand All @@ -8,8 +10,7 @@ struct Asset;
#[folder = "src/libc/aarch64/"]
struct Asset;

#[cfg(target_os = "linux")]
pub(crate) fn ld_env(envs: &mut std::collections::HashMap<String, String>) -> anyhow::Result<()> {
pub(crate) fn ld_env(envs: &mut std::collections::HashMap<String, String>) -> Result<()> {
use crate::{constant, util};
use anyhow::Context;
use std::ops::Not;
Expand Down
2 changes: 1 addition & 1 deletion src/asset/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#[cfg(all(target_os = "linux", target_env = "musl"))]
#[cfg(target_os = "linux")]
pub mod libc;
pub mod thunder;
10 changes: 5 additions & 5 deletions src/asset/thunder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use anyhow::Context;
use anyhow::Result;
use core::str;
use std::{
borrow::Cow,
Expand All @@ -6,8 +8,6 @@ use std::{
ops::Not,
path::{Path, PathBuf},
};

use anyhow::Context;
use tar::Archive;

pub struct Asset {
Expand All @@ -31,7 +31,7 @@ impl Asset {
})
}

pub fn init(&self) -> anyhow::Result<()> {
pub fn init(&self) -> Result<()> {
match self.package {
Some(ref filepath) => {
// check filepath is exists
Expand Down Expand Up @@ -90,7 +90,7 @@ impl Asset {
}
}

fn decompressor<T: AsRef<Path>>(dir: T, archive_path: T) -> anyhow::Result<()> {
fn decompressor<T: AsRef<Path>>(dir: T, archive_path: T) -> Result<()> {
const PACKAGE_XZ: &str = "package.tgz";
const PACKAGE_TAR: &str = "package.tar";

Expand Down Expand Up @@ -158,7 +158,7 @@ impl Asset {
Ok(())
}

fn copy_write(mut src: impl Read, dest: &mut File) -> anyhow::Result<()> {
fn copy_write(mut src: impl Read, dest: &mut File) -> Result<()> {
let mut buffer = [0; 1024];

loop {
Expand Down
13 changes: 7 additions & 6 deletions src/daemon.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Result;
use daemonize::Daemonize;
use std::{
fs::{File, Permissions},
Expand All @@ -22,7 +23,7 @@ pub fn check_root() {
}

/// Get the pid of the daemon
pub(crate) fn get_pid() -> Option<String> {
pub fn get_pid() -> Option<String> {
if let Ok(data) = std::fs::read(PID_PATH) {
let binding = String::from_utf8(data).expect("pid file is not utf8");
return Some(binding.trim().to_string());
Expand All @@ -31,7 +32,7 @@ pub(crate) fn get_pid() -> Option<String> {
}

/// Start the daemon
pub(super) fn start() -> anyhow::Result<()> {
pub fn start() -> Result<()> {
if let Some(pid) = get_pid() {
println!("Thunder is already running with pid: {}", pid);
return Ok(());
Expand Down Expand Up @@ -73,7 +74,7 @@ pub(super) fn start() -> anyhow::Result<()> {
}

/// Stop the daemon
pub(super) fn stop() -> anyhow::Result<()> {
pub fn stop() -> Result<()> {
use nix::sys::signal;
use nix::unistd::Pid;

Expand All @@ -94,7 +95,7 @@ pub(super) fn stop() -> anyhow::Result<()> {
}

/// Show the status of the daemon
pub(super) fn status() -> anyhow::Result<()> {
pub fn status() -> Result<()> {
match get_pid() {
Some(pid) => println!("Thunder is running with pid: {}", pid),
None => println!("Thunder is not running"),
Expand All @@ -103,8 +104,8 @@ pub(super) fn status() -> anyhow::Result<()> {
}

/// Show the log of the daemon
pub(super) fn log() -> anyhow::Result<()> {
fn read_and_print_file(file_path: &Path, placeholder: &str) -> anyhow::Result<()> {
pub fn log() -> Result<()> {
fn read_and_print_file(file_path: &Path, placeholder: &str) -> Result<()> {
if !file_path.exists() {
return Ok(());
}
Expand Down
18 changes: 13 additions & 5 deletions src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ use std::ops::Not;
use std::path::Path;
use std::path::PathBuf;

use anyhow::Context;
use rand::Rng;

use crate::asset::thunder::Asset;
use crate::constant;
use crate::util;
use crate::InstallConfig;
use crate::Running;
use anyhow::Context;
use anyhow::Result;
use rand::Rng;

/// Install xunlei
pub struct XunleiInstall(pub InstallConfig);

impl Running for XunleiInstall {
fn run(self) -> anyhow::Result<()> {
fn run(self) -> Result<()> {
// If the package is already installed, skip the installation
if Path::new(constant::SYNOPKG_VAR).exists() {
println!("Thunder already installed");
Expand Down Expand Up @@ -66,13 +66,21 @@ impl Running for XunleiInstall {
let target_dir = PathBuf::from(constant::SYNOPKG_PKGDEST);
// /var/packages/pan-xunlei-com/target/host
let host_dir = PathBuf::from(constant::SYNOPKG_HOST);
// If Synology NAS is not installed, the backend service will not be started
let var_path = Path::new(constant::SYNOPKG_VAR);

// uid and gid
let uid = self.0.uid;
let gid = self.0.gid;

util::create_dir_all(&target_dir, 0o755)?;

// path: /var/packages/pan-xunlei-com/target/var
if !var_path.exists() {
util::create_dir_all(var_path, 0o777)?;
util::chown(var_path, uid, gid)?;
}

// download xunlei binary
let xunlei = Asset::new(self.0.package)?;
xunlei.init()?;
Expand Down Expand Up @@ -175,7 +183,7 @@ impl Running for XunleiInstall {
pub struct XunleiUninstall(pub Option<InstallConfig>);

impl Running for XunleiUninstall {
fn run(self) -> anyhow::Result<()> {
fn run(self) -> Result<()> {
// path: /var/packages/pan-xunlei-com
let path = Path::new(constant::SYNOPKG_PKGBASE);
if path.exists() {
Expand Down
47 changes: 39 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ mod install;
mod serve;
pub mod util;

use anyhow::Result;
use clap::{Args, Parser, Subcommand};
use std::io::{BufRead, Write};
use std::net::SocketAddr;
use std::path::{Path, PathBuf};

pub trait Running {
fn run(self) -> anyhow::Result<()>;
fn run(self) -> Result<()>;
}

#[derive(Parser)]
Expand Down Expand Up @@ -69,7 +70,7 @@ impl InstallConfig {
const PATH: &'static str = "/etc/.thunder";

/// Remove config file
pub fn remove_file(self) -> anyhow::Result<()> {
pub fn remove_file(self) -> Result<()> {
let path = Path::new(Self::PATH);
if path.exists() {
std::fs::remove_file(&Self::PATH)?;
Expand All @@ -78,7 +79,7 @@ impl InstallConfig {
}

/// Write to file
fn write_to_file(&self) -> anyhow::Result<()> {
fn write_to_file(&self) -> Result<()> {
let path = Path::new(Self::PATH);
if !path.exists() {
let mut file = std::fs::File::create(path)?;
Expand Down Expand Up @@ -175,7 +176,7 @@ pub struct ServeConfig {
tls_key: Option<PathBuf>,
}

fn main() -> anyhow::Result<()> {
fn main() -> Result<()> {
let opt = Opt::parse();

match opt.commands {
Expand All @@ -187,12 +188,16 @@ fn main() -> anyhow::Result<()> {
let install_config = InstallConfig::read_from_file().map_or(None, |v| Some(v));
install::XunleiUninstall(install_config).run()?;
}
Commands::Run(config) => {
serve::Serve::new(config, InstallConfig::read_from_file()?).run()?;
Commands::Run(server_config) => {
let install_config = InstallConfig::read_from_file()?;
before_action(&install_config)?;
serve::Serve::new(server_config, install_config).run()?;
}
Commands::Start(config) => {
Commands::Start(server_config) => {
let install_config = InstallConfig::read_from_file()?;
before_action(&install_config)?;
daemon::start()?;
serve::Serve::new(config, InstallConfig::read_from_file()?).run()?;
serve::Serve::new(server_config, install_config).run()?;
}
Commands::Stop => {
daemon::stop()?;
Expand All @@ -206,3 +211,29 @@ fn main() -> anyhow::Result<()> {
}
Ok(())
}

/// Running before the daemon starts, execute the following code
fn before_action(install_config: &InstallConfig) -> Result<()> {
#[cfg(target_os = "linux")]
use nix::mount::MsFlags;

#[cfg(target_os = "linux")]
let _ = nix::mount::umount(&install_config.mount_bind_download_path);
#[cfg(target_os = "linux")]
if nix::mount::mount(
Some(&install_config.download_path),
&install_config.mount_bind_download_path,
<Option<&'static [u8]>>::None,
MsFlags::MS_BIND,
<Option<&'static [u8]>>::None,
)
.is_err()
{
anyhow::bail!(
"Mount {} to {} failed",
install_config.download_path.display(),
install_config.mount_bind_download_path.display()
);
}
Ok(())
}
6 changes: 3 additions & 3 deletions src/serve/auth/token.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::{CHECK_AUTH, EXP, TOKEN_SECRET};
use anyhow::Result;
use jsonwebtokens::{encode, Algorithm, AlgorithmID, Verifier};
use std::{collections::HashMap, time::Duration};

use super::{CHECK_AUTH, EXP, TOKEN_SECRET};

fn get_or_init_secret() -> &'static String {
TOKEN_SECRET.get_or_init(|| {
let secret = if let Some(Some(auth_password)) = CHECK_AUTH.get() {
Expand All @@ -27,7 +27,7 @@ pub fn generate_token() -> anyhow::Result<String> {
Ok(encode(&header, &claims, &alg)?)
}

pub fn verifier(token_str: &str) -> anyhow::Result<()> {
pub fn verifier(token_str: &str) -> Result<()> {
let s = get_or_init_secret();
let alg = Algorithm::new_hmac(AlgorithmID::HS256, s.to_owned())?;
let verifier = Verifier::create().build()?;
Expand Down
40 changes: 6 additions & 34 deletions src/serve/backend.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#[cfg(target_os = "linux")]
use nix::mount::MsFlags;
use crate::serve::ConfigExt;
use crate::ServeConfig;
use crate::{constant, InstallConfig, Running};
use anyhow::Result;
use nix::sys::signal;
use nix::unistd::Pid;
use signal_hook::iterator::Signals;
use std::os::unix::process::CommandExt;

use crate::serve::ConfigExt;
use crate::{constant, InstallConfig, Running};
use crate::{util, ServeConfig};
use std::{ops::Not, path::Path, process::Stdio};
use std::process::Stdio;

pub(super) struct BackendServer(ServeConfig, InstallConfig, tokio::sync::mpsc::Sender<()>);

Expand All @@ -23,33 +21,7 @@ impl BackendServer {
}

impl Running for BackendServer {
fn run(self) -> anyhow::Result<()> {
// If Synology NAS is not installed, the backend service will not be started
let var_path = Path::new(constant::SYNOPKG_VAR);
if var_path.exists().not() {
util::create_dir_all(var_path, 0o777)?;
util::chown(var_path, self.1.uid, self.1.gid)?;
}

#[cfg(target_os = "linux")]
let _ = nix::mount::umount(&self.1.mount_bind_download_path);
#[cfg(target_os = "linux")]
if nix::mount::mount(
Some(&self.1.download_path),
&self.1.mount_bind_download_path,
<Option<&'static [u8]>>::None,
MsFlags::MS_BIND,
<Option<&'static [u8]>>::None,
)
.is_err()
{
anyhow::bail!(
"Mount {} to {} failed",
self.1.download_path.display(),
self.1.mount_bind_download_path.display()
);
}

fn run(self) -> Result<()> {
// environment variables
let envs = (&self.0, &self.1).envs()?;

Expand Down
5 changes: 3 additions & 2 deletions src/serve/frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use super::{
};
use crate::{constant, InstallConfig, Running, ServeConfig};
use anyhow::Context;
use anyhow::Result;
use axum::{
body::{Body, StreamBody},
extract::State,
Expand Down Expand Up @@ -41,7 +42,7 @@ struct User {
pub(super) struct FrontendServer(ServeConfig, InstallConfig, tokio::sync::mpsc::Receiver<()>);

impl Running for FrontendServer {
fn run(self) -> anyhow::Result<()> {
fn run(self) -> Result<()> {
self.start_server()
}
}
Expand All @@ -56,7 +57,7 @@ impl FrontendServer {
}

#[tokio::main]
async fn start_server(self) -> anyhow::Result<()> {
async fn start_server(self) -> Result<()> {
log::info!("Starting frontend server: {}", self.0.bind);

// Set check auth
Expand Down
3 changes: 2 additions & 1 deletion src/serve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
serve::{backend::BackendServer, frontend::FrontendServer},
InstallConfig, Running, ServeConfig,
};
use anyhow::Result;
use std::collections::HashMap;

pub(crate) trait ConfigExt {
Expand All @@ -25,7 +26,7 @@ impl Serve {
}

impl Running for Serve {
fn run(self) -> anyhow::Result<()> {
fn run(self) -> Result<()> {
use std::thread::{Builder, JoinHandle};

let serve_config = self.0.clone();
Expand Down
Loading

0 comments on commit 48d3bf5

Please sign in to comment.