1use std::io::stderr;
2use std::path::PathBuf;
3use std::process::Command;
4use std::{ffi::OsString, os::unix::process::CommandExt};
5
6use anyhow::{anyhow, Context, Result};
7
8pub fn re_exec_with_executable(executable_path: PathBuf) -> std::io::Error {
9 let mut args = std::env::args_os();
10 let arg0 = args.next();
11 let mut cmd = Command::new(&executable_path);
12 cmd.args(args);
13 if let Some(a0) = arg0 {
14 cmd.arg0(a0);
15 }
16 cmd.exec()
17}
18
19pub fn current_exe() -> Result<PathBuf> {
20 let path = std::env::current_exe().context("getting the path to the current executable")?;
21 let deleted_str = " (deleted)";
24 let s = path.to_string_lossy();
25 if s.ends_with(deleted_str) {
26 let os = path.as_os_str().to_owned();
27 let mut bs = os.into_encoded_bytes();
28 if bs.ends_with(deleted_str.as_bytes()) {
29 bs.truncate(bs.len() - deleted_str.as_bytes().len());
30 } else {
31 use std::io::Write;
32 _ = writeln!(
33 &mut stderr(),
34 "can't find the bytes after a first match, in {path:?}"
35 );
36 return Ok(path);
37 }
38 let os = unsafe { OsString::from_encoded_bytes_unchecked(bs) };
39 Ok(os.into())
40 } else {
41 Ok(path)
42 }
43}
44
45pub fn _re_exec() -> Result<()> {
47 let path = current_exe()?;
48 Err(re_exec_with_executable(path.clone()))
49 .with_context(|| anyhow!("executing the binary {path:?}"))
50}
51
52pub fn re_exec() -> anyhow::Error {
54 match _re_exec() {
55 Ok(()) => unreachable!(),
56 Err(e) => e,
57 }
58}