cloudpub_client/service/
mod.rs1use anyhow::Result;
2use std::path::PathBuf;
3use std::{env, fs};
4use tracing::debug;
5
6#[cfg(target_os = "windows")]
7mod windows;
8#[cfg(target_os = "windows")]
9pub use windows::*;
10
11#[cfg(target_os = "linux")]
12mod linux;
13#[cfg(target_os = "linux")]
14pub use linux::*;
15
16#[cfg(target_os = "macos")]
17mod macos;
18#[cfg(target_os = "macos")]
19pub use macos::*;
20
21pub trait ServiceManager {
23 fn install(&self) -> Result<()>;
24 fn uninstall(&self) -> Result<()>;
25 fn start(&self) -> Result<()>;
26 fn stop(&self) -> Result<()>;
27 fn status(&self) -> Result<ServiceStatus>;
28}
29
30#[allow(dead_code)]
31#[derive(Debug)]
32pub enum ServiceStatus {
33 Running,
34 Stopped,
35 NotInstalled,
36 Unknown,
37}
38
39#[allow(dead_code)]
40#[derive(Debug)]
41pub struct ServiceConfig {
42 pub name: String,
43 pub display_name: String,
44 pub description: String,
45 pub executable_path: PathBuf,
46 pub args: Vec<String>,
47 pub config_path: PathBuf,
48}
49
50impl ServiceConfig {
51 pub fn get_system_config_path() -> PathBuf {
53 #[cfg(target_os = "windows")]
54 {
55 PathBuf::from(r"C:\ProgramData\cloudpub\client.toml")
57 }
58 #[cfg(target_os = "linux")]
59 {
60 PathBuf::from("/root/.config/cloudpub/client.toml")
62 }
63 #[cfg(target_os = "macos")]
64 {
65 PathBuf::from("/var/root/.config/cloudpub/client.toml")
67 }
68 #[cfg(target_os = "android")]
69 {
70 PathBuf::from("/data/data/com.termux/files/home/.config/cloudpub/client.toml")
72 }
73 }
74
75 #[cfg(any(target_os = "linux", target_os = "macos"))]
77 pub fn get_sudo_user_config_path() -> Option<PathBuf> {
78 if let Ok(sudo_user) = env::var("SUDO_USER") {
80 debug!("Detected SUDO_USER: {}", sudo_user);
81
82 #[cfg(target_os = "linux")]
84 let home_base = "/home";
85 #[cfg(target_os = "macos")]
86 let home_base = "/Users";
87
88 let user_home = PathBuf::from(home_base).join(&sudo_user);
89 let config_path = user_home.join(".config/cloudpub/client.toml");
90
91 debug!("Check for sudo user config location: {:?}", config_path);
92 if config_path.exists() {
93 debug!("Found config at sudo user's location: {:?}", config_path);
94 return Some(config_path);
95 }
96 }
97 debug!("No SUDO_USER detected or config file does not exist");
98 None
99 }
100
101 pub fn copy_config_to_system(&self) -> Result<()> {
103 let system_config_path = Self::get_system_config_path();
104
105 if let Some(parent) = system_config_path.parent() {
107 fs::create_dir_all(parent)?;
108 }
109
110 if self.config_path != system_config_path {
112 fs::copy(&self.config_path, &system_config_path)?;
113 debug!(
114 "Copied config from {:?} to {:?}",
115 self.config_path, system_config_path
116 );
117 }
118
119 Ok(())
120 }
121}
122
123pub fn create_service_manager(config_path: PathBuf) -> Box<dyn ServiceManager> {
124 let exe_path = env::current_exe().expect("Failed to get current executable path");
126
127 let mut args = Vec::new();
129
130 let system_config_path = ServiceConfig::get_system_config_path();
132 let path_str = system_config_path.to_str().unwrap();
133 args.push("--conf".to_string());
134 args.push(path_str.to_string());
135
136 args.push("run".to_string());
138 args.push("--run-as-service".to_string());
139
140 let config = ServiceConfig {
142 #[cfg(target_os = "macos")]
143 name: "ru.cloudpub.clo".to_string(),
144 #[cfg(not(target_os = "macos"))]
145 name: "cloudpub".to_string(),
146 display_name: "CloudPub Client".to_string(),
147 description: "CloudPub Client Service".to_string(),
148 executable_path: exe_path,
149 args,
150 config_path,
151 };
152
153 debug!("Service configuration: {:?}", config);
154
155 #[cfg(target_os = "windows")]
156 {
157 Box::new(WindowsServiceManager::new(config))
158 }
159 #[cfg(target_os = "linux")]
160 {
161 Box::new(LinuxServiceManager::new(config))
162 }
163 #[cfg(target_os = "macos")]
164 {
165 Box::new(MacOSServiceManager::new(config))
166 }
167 #[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "macos")))]
168 {
169 panic!("Unsupported platform for service management");
170 }
171}