mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-27 16:51:15 -03:00
Pin down "status fish-path" at startup
On some platforms, Rust's std::env::current_exe() may use relative
paths from at least argv[0]. That function also canonicalizes the
path, so we could only detect this case by duplicating logic from
std::env::current_exe() (not sure if that's worth it).
Relative path canonicalization seems potentially surprising, especially
after fish has used "cd". Let's try to reduce surprise by saving the
value we compute at startup (before any "cd"), and use only that.
The remaining problem is that
creat("/some/directory/with/FISH");
chdir("/some/directory/with/");
execve("/bin/fish", "FISH", "-c", "status fish-path")
surprisingly prints "/some/directory/with/FISH" on some platforms.
But that requires the user actively trying to break things (passing
a relative argv[0] that doesn't match the cwd).
This commit is contained in:
21
src/env/config_paths.rs
vendored
21
src/env/config_paths.rs
vendored
@@ -1,9 +1,10 @@
|
||||
use crate::common::{BUILD_DIR, PROGRAM_NAME};
|
||||
use crate::{FLOG, FLOGF};
|
||||
use fish_build_helper::workspace_root;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// A struct of configuration directories, determined in main() that fish will optionally pass to
|
||||
/// env_init.
|
||||
@@ -22,7 +23,7 @@ pub struct ConfigPaths {
|
||||
|
||||
impl ConfigPaths {
|
||||
pub fn new() -> Self {
|
||||
let exec_path = get_fish_path();
|
||||
let exec_path = FISH_PATH.get_or_init(compute_fish_path);
|
||||
FLOG!(config, format!("executable path: {}", exec_path.display()));
|
||||
let paths = Self::from_exec_path(exec_path);
|
||||
FLOGF!(
|
||||
@@ -57,7 +58,7 @@ fn static_paths() -> Self {
|
||||
}
|
||||
|
||||
#[cfg(feature = "embed-data")]
|
||||
fn from_exec_path(exec_path: PathBuf) -> Self {
|
||||
fn from_exec_path(exec_path: &Path) -> Self {
|
||||
FLOG!(config, "embed-data feature is active, ignoring data paths");
|
||||
Self {
|
||||
sysconf: if exec_path
|
||||
@@ -73,9 +74,7 @@ fn from_exec_path(exec_path: PathBuf) -> Self {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "embed-data"))]
|
||||
fn from_exec_path(unresolved_exec_path: PathBuf) -> Self {
|
||||
use std::path::Path;
|
||||
|
||||
fn from_exec_path(unresolved_exec_path: &Path) -> Self {
|
||||
let invalid_exec_path = |exec_path: &Path| {
|
||||
FLOG!(
|
||||
config,
|
||||
@@ -87,7 +86,7 @@ fn from_exec_path(unresolved_exec_path: PathBuf) -> Self {
|
||||
Self::static_paths()
|
||||
};
|
||||
let Ok(exec_path) = unresolved_exec_path.canonicalize() else {
|
||||
return invalid_exec_path(&unresolved_exec_path);
|
||||
return invalid_exec_path(unresolved_exec_path);
|
||||
};
|
||||
let Some(exec_path_parent) = exec_path.parent() else {
|
||||
return invalid_exec_path(&exec_path);
|
||||
@@ -144,8 +143,14 @@ fn from_exec_path(unresolved_exec_path: PathBuf) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
static FISH_PATH: OnceCell<PathBuf> = OnceCell::new();
|
||||
|
||||
/// Get the absolute path to the fish executable itself
|
||||
pub fn get_fish_path() -> PathBuf {
|
||||
pub fn get_fish_path() -> &'static PathBuf {
|
||||
FISH_PATH.get().unwrap()
|
||||
}
|
||||
|
||||
fn compute_fish_path() -> PathBuf {
|
||||
let Ok(path) = std::env::current_exe() else {
|
||||
assert!(PROGRAM_NAME.get().unwrap() == "fish");
|
||||
return PathBuf::from("fish");
|
||||
|
||||
Reference in New Issue
Block a user