Skip to main content

tauri/
process.rs

1// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5//! Types and functions related to child processes management.
6
7use crate::Env;
8
9use std::path::PathBuf;
10
11/// Finds the current running binary's path.
12///
13/// With exception to any following platform-specific behavior, the path is cached as soon as
14/// possible, and then used repeatedly instead of querying for a new path every time this function
15/// is called.
16///
17/// # Platform-specific behavior
18///
19/// ## Linux
20///
21/// On Linux, this function will **attempt** to detect if it's currently running from a
22/// valid [AppImage] and use that path instead.
23///
24/// ## macOS
25///
26/// On `macOS`, this function will return an error if the original path contained any symlinks
27/// due to less protection on macOS regarding symlinks. This behavior can be disabled by setting the
28/// `process-relaunch-dangerous-allow-symlink-macos` feature, although it is *highly discouraged*.
29///
30/// # Security
31///
32/// See [`tauri_utils::platform::current_exe`] for possible security implications.
33///
34/// # Examples
35///
36/// ```rust,no_run
37/// use tauri::{process::current_binary, Env, Manager};
38/// let current_binary_path = current_binary(&Env::default()).unwrap();
39///
40/// tauri::Builder::default()
41///   .setup(|app| {
42///     let current_binary_path = current_binary(&app.env())?;
43///     Ok(())
44///   });
45/// ```
46///
47/// [AppImage]: https://appimage.org/
48pub fn current_binary(_env: &Env) -> std::io::Result<PathBuf> {
49  // if we are running from an AppImage, we ONLY want the set AppImage path
50  #[cfg(target_os = "linux")]
51  if let Some(app_image_path) = &_env.appimage {
52    return Ok(PathBuf::from(app_image_path));
53  }
54
55  tauri_utils::platform::current_exe()
56}
57
58/// Restarts the currently running binary.
59///
60/// See [`current_binary`] for platform specific behavior, and
61/// [`tauri_utils::platform::current_exe`] for possible security implications.
62///
63/// # Examples
64///
65/// ```rust,no_run
66/// use tauri::{process::restart, Env, Manager};
67///
68/// tauri::Builder::default()
69///   .setup(|app| {
70///     restart(&app.env());
71///     Ok(())
72///   });
73/// ```
74pub fn restart(env: &Env) -> ! {
75  use std::process::{exit, Command};
76
77  if let Ok(path) = current_binary(env) {
78    // on macOS on updates the binary name might have changed
79    // so we'll read the Contents/Info.plist file to determine the binary path
80    #[cfg(target_os = "macos")]
81    restart_macos_app(&path, env);
82
83    if let Err(e) = Command::new(path).args(env.args_os.iter().skip(1)).spawn() {
84      log::error!("failed to restart app: {e}");
85    }
86  }
87
88  exit(0);
89}
90
91#[cfg(target_os = "macos")]
92fn restart_macos_app(current_binary: &std::path::Path, env: &Env) {
93  use std::process::{exit, Command};
94
95  if let Some(macos_directory) = current_binary.parent() {
96    if macos_directory.components().next_back()
97      != Some(std::path::Component::Normal(std::ffi::OsStr::new("MacOS")))
98    {
99      return;
100    }
101
102    if let Some(contents_directory) = macos_directory.parent() {
103      if contents_directory.components().next_back()
104        != Some(std::path::Component::Normal(std::ffi::OsStr::new(
105          "Contents",
106        )))
107      {
108        return;
109      }
110
111      if let Ok(info_plist) =
112        plist::from_file::<_, plist::Dictionary>(contents_directory.join("Info.plist"))
113      {
114        if let Some(binary_name) = info_plist
115          .get("CFBundleExecutable")
116          .and_then(|v| v.as_string())
117        {
118          if let Err(e) = Command::new(macos_directory.join(binary_name))
119            .args(env.args_os.iter().skip(1))
120            .spawn()
121          {
122            log::error!("failed to restart app: {e}");
123          }
124
125          exit(0);
126        }
127      }
128    }
129  }
130}