Skip to content

Commit 8165826

Browse files
committed
Fixing permissions issues on Linux
1 parent cdf6f37 commit 8165826

File tree

7 files changed

+46
-43
lines changed

7 files changed

+46
-43
lines changed

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ chrono = "0.4.41"
99
dirs = "6.0.0"
1010
env_logger = "0.11.8"
1111
fltk = { version = "1.5.13", features = ["fltk-bundled"] }
12-
image = "0.25.6"
13-
log = "0.4.27"
12+
image = "0.25.8"
13+
log = "0.4.28"
1414
overtls = { version = "0.3.6" }
1515
qrcode = "0.14.1"
1616
rfd = { version = "0.15.4", default-features = false, features = ["xdg-portal", "tokio"] }
1717
rqrr = "0.10.0"
18-
run-as = { version = "1.2.2", default-features = false }
18+
run-as = { version = "1.2.4", default-features = false }
1919
screenshot = { version = "0.0.7", git = "https://github.com/ssrlive/screenshot-rs.git", rev = "36f877f" }
2020
serde = { version = "1.0.219", features = ["derive"] }
2121
serde_json = "1.0.143"
22-
tokio = { version = "1", features = ["full"] }
22+
tokio = { version = "1.47.1", features = ["full"] }
2323
tray-icon = { version = "0.21.1", default-features = false, features = ["libxdo", "common-controls-v6"] }
2424
tun2proxy = { version = "0.7.14", default-features = false }
2525

2626
[target.'cfg(target_os = "linux")'.dependencies]
27-
gtk = "0.18"
27+
gtk = "0.18.2"

README-CN.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,7 @@ cargo build --release
4343

4444
### 運行
4545

46-
Linux(需 root 權限):
47-
48-
```bash
49-
sudo ./target/release/overtls-gui
50-
```
51-
52-
Windows/macOS:
46+
Windows/macOS/Linux:
5347

5448
```bash
5549
./target/release/overtls-gui

README.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,7 @@ cargo build --release
4545

4646
### Run
4747

48-
On Linux (requires root privileges):
49-
50-
```bash
51-
sudo ./target/release/overtls-gui
52-
```
53-
54-
On Windows/macOS:
48+
On Windows/macOS/Linux:
5549

5650
```bash
5751
./target/release/overtls-gui

src/content_table.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ pub fn create_table(
157157
Ok(json_str) => {
158158
if std::fs::write(&path, json_str).is_ok() {
159159
log::debug!("Node exported to: {}", path.display());
160+
crate::states_manager::set_file_owner_if_needed(&path);
160161
} else {
161162
rfd::MessageDialog::new()
162163
.set_title("Error")

src/core.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,8 @@ pub fn merge_system_settings_to_node_config(system_settings: &SystemSettings, no
1313

1414
pub fn restart_as_admin() -> std::io::Result<std::process::ExitStatus> {
1515
log::debug!("Not running as admin, trying to elevate...");
16-
let args: Vec<String> = std::env::args().collect();
17-
run_as::Command::new(&args[0])
18-
.args(&args[1..])
19-
.gui(true)
20-
.wait_to_complete(false)
21-
.status()
16+
run_as::restart_self_elevated(None, true, false, Some(std::time::Duration::from_secs(10)))?
17+
.ok_or_else(|| std::io::Error::other("Non-blocking restart does not return exit status"))
2218
}
2319

2420
pub fn main_task_block(

src/main.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,13 @@ async fn main() -> Result<(), BoxError> {
3434
// #[cfg(debug_assertions)]
3535
// env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
3636

37-
// Check for root privileges on Linux
38-
#[cfg(target_os = "linux")]
39-
if !run_as::is_elevated() {
40-
let program_name = std::env::args().next().unwrap_or_else(|| "overtls-gui".to_string());
41-
let info = format!("This application requires root privileges to run on Linux.\n\nPlease run with: \nsudo {program_name}\n\n");
42-
eprint!("{info}");
43-
rfd::MessageDialog::new()
44-
.set_title("Error")
45-
.set_description(info)
46-
.set_level(rfd::MessageLevel::Error)
47-
.show();
48-
std::process::exit(1);
49-
}
50-
5137
let (tx, rx) = std::sync::mpsc::channel();
5238

5339
let state = states_manager::load_app_state();
5440
let system_settings = state.system_settings.clone().unwrap_or_default();
5541

5642
if let Err(e) = log::set_boxed_logger(Box::new(system_settings.create_logger(tx))) {
57-
eprintln!("Failed to set logger: {e}");
43+
log::warn!("Failed to set logger: {e}");
5844
}
5945
// Note: No longer use log::set_max_level, as it is now controlled by the Logger internally
6046
log::set_max_level(log::LevelFilter::Trace);
@@ -331,6 +317,7 @@ async fn main() -> Result<(), BoxError> {
331317
Ok(json_str) => {
332318
if std::fs::write(&path, json_str).is_ok() {
333319
log::debug!("Node exported to: {}", path.display());
320+
states_manager::set_file_owner_if_needed(&path);
334321
state_clone.borrow_mut().set_current_path(path.parent().unwrap_or(&origin_path));
335322
} else {
336323
rfd::MessageDialog::new()
@@ -652,6 +639,7 @@ async fn main() -> Result<(), BoxError> {
652639
.unwrap_or(false);
653640
state.borrow_mut().system_settings = Some(new_settings);
654641
if tun2proxy_enable && !run_as::is_elevated() {
642+
save_final_app_state(&state, &remote_nodes, &win, &current_node_index)?;
655643
if let Ok(status) = core::restart_as_admin() {
656644
log::debug!("Restarted as admin with status code {status}, exiting current instance.");
657645
::fltk::app::quit();

src/states_manager.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,28 @@ impl Drop for AppState {
123123
}
124124
}
125125

126+
fn get_real_config_dir() -> PathBuf {
127+
#[cfg(target_os = "linux")]
128+
if let Ok(sudo_user) = std::env::var("SUDO_USER") {
129+
let home_path = PathBuf::from("/home").join(&sudo_user).join(".config");
130+
return home_path;
131+
}
132+
dirs::config_dir().unwrap_or_else(|| std::env::current_dir().unwrap())
133+
}
134+
126135
fn get_config_path() -> PathBuf {
127-
let mut path = dirs::config_dir().unwrap_or_else(|| std::env::current_dir().unwrap());
136+
let mut path = get_real_config_dir();
128137
path.push(env!("CARGO_PKG_NAME"));
129-
let _ = std::fs::create_dir_all(&path);
138+
let _r = std::fs::create_dir_all(&path);
139+
#[cfg(target_os = "linux")]
140+
if _r.is_ok()
141+
&& run_as::is_elevated()
142+
&& let Ok(sudo_user) = std::env::var("SUDO_USER")
143+
&& path.starts_with(format!("/home/{sudo_user}/.config"))
144+
{
145+
// chown -R <sudo_user> <path>
146+
let _ = std::process::Command::new("chown").arg("-R").arg(&sudo_user).arg(&path).status();
147+
}
130148
path.push("config.json");
131149
path
132150
}
@@ -143,7 +161,19 @@ pub fn load_app_state() -> AppState {
143161
pub fn save_app_state(state: &AppState) -> std::io::Result<()> {
144162
let config_path = get_config_path();
145163
let contents = serde_json::to_string_pretty(state).map_err(|e| std::io::Error::other(format!("Failed to serialize state: {e}")))?;
146-
std::fs::write(config_path, contents)
164+
std::fs::write(&config_path, &contents)?;
165+
set_file_owner_if_needed(&config_path);
166+
Ok(())
167+
}
168+
169+
/// If needed, set the specified file to be owned by sudo_user
170+
pub fn set_file_owner_if_needed<P: AsRef<std::path::Path>>(_path: P) {
171+
#[cfg(target_os = "linux")]
172+
if run_as::is_elevated()
173+
&& let Ok(sudo_user) = std::env::var("SUDO_USER")
174+
{
175+
let _ = std::process::Command::new("chown").arg(&sudo_user).arg(_path.as_ref()).status();
176+
}
147177
}
148178

149179
impl SystemSettings {

0 commit comments

Comments
 (0)