mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
cd: open directory with O_SEARCH or O_PATH, when the platform supports it
This commit is contained in:
parent
2ecbdb9ae7
commit
a148760963
3 changed files with 29 additions and 9 deletions
|
@ -3,7 +3,7 @@
|
|||
use super::prelude::*;
|
||||
use crate::{
|
||||
env::{EnvMode, Environment},
|
||||
fds::wopen_dir,
|
||||
fds::{wopen_dir, BEST_O_SEARCH},
|
||||
path::path_apply_cdpath,
|
||||
wutil::{normalize_path, wperror, wreadlink},
|
||||
};
|
||||
|
@ -86,7 +86,7 @@ pub fn cd(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> Optio
|
|||
|
||||
errno::set_errno(Errno(0));
|
||||
|
||||
let res = wopen_dir(&norm_dir).map_err(|err| err as i32);
|
||||
let res = wopen_dir(&norm_dir, BEST_O_SEARCH).map_err(|err| err as i32);
|
||||
|
||||
let res = res.and_then(|fd| {
|
||||
if unsafe { fchdir(fd.as_raw_fd()) } == 0 {
|
||||
|
|
29
src/fds.rs
29
src/fds.rs
|
@ -259,15 +259,36 @@ pub fn open_cloexec(path: &CStr, flags: OFlag, mode: nix::sys::stat::Mode) -> ni
|
|||
}
|
||||
}
|
||||
|
||||
/// POSIX specifies an open option O_SEARCH for opening directories for later
|
||||
/// `fchdir` or `openat`, not for `readdir`. The read permission is not checked,
|
||||
/// and the x permission is checked on opening. Not all platforms have this,
|
||||
/// so we fall back to O_PATH or O_RDONLY according to the platform.
|
||||
pub use o_search::BEST_O_SEARCH;
|
||||
|
||||
mod o_search {
|
||||
use super::OFlag;
|
||||
/// On FreeBSD or MacOS we have O_SEARCH.
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
pub const BEST_O_SEARCH: OFlag = unsafe { OFlag::from_bits_unchecked(libc::O_SEARCH) };
|
||||
/// On Linux we can use O_PATH, it has nearly the same semantics. we can use the fd for openat / fchdir, with only requiring
|
||||
/// x permission on the directory.
|
||||
#[cfg(all(not(any(target_os = "macos", target_os = "freebsd")), any(target_os = "linux", target_os = "android")))]
|
||||
pub const BEST_O_SEARCH: OFlag = unsafe { OFlag::from_bits_unchecked(libc::O_PATH) };
|
||||
|
||||
/// Fall back to O_RDONLY, this is what fish did before.
|
||||
#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "macos")))]
|
||||
pub const BEST_O_SEARCH: OFlag = OFlag::O_RDONLY;
|
||||
}
|
||||
|
||||
/// Wide character version of open_dir() that also sets the close-on-exec flag (atomically when
|
||||
/// possible).
|
||||
pub fn wopen_dir(pathname: &wstr) -> nix::Result<OwnedFd> {
|
||||
open_dir(wcs2zstring(pathname).as_c_str())
|
||||
pub fn wopen_dir(pathname: &wstr, flags: OFlag) -> nix::Result<OwnedFd> {
|
||||
open_dir(wcs2zstring(pathname).as_c_str(), flags)
|
||||
}
|
||||
|
||||
/// Narrow version of wopen_dir().
|
||||
pub fn open_dir(path: &CStr) -> nix::Result<OwnedFd> {
|
||||
open_cloexec(path, OFlag::O_RDONLY | OFlag::O_DIRECTORY, nix::sys::stat::Mode::empty()).map(OwnedFd::from)
|
||||
pub fn open_dir(path: &CStr, flags: OFlag) -> nix::Result<OwnedFd> {
|
||||
open_cloexec(path, flags | OFlag::O_DIRECTORY, nix::sys::stat::Mode::empty()).map(OwnedFd::from)
|
||||
}
|
||||
|
||||
/// Close a file descriptor `fd`, retrying on EINTR.
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::event::{self, Event};
|
|||
use crate::expand::{
|
||||
expand_string, replace_home_directory_with_tilde, ExpandFlags, ExpandResultCode,
|
||||
};
|
||||
use crate::fds::open_dir;
|
||||
use crate::fds::{open_dir, BEST_O_SEARCH};
|
||||
use crate::global_safety::RelaxedAtomicBool;
|
||||
use crate::input_common::{terminal_protocols_disable_scoped, TERMINAL_PROTOCOLS};
|
||||
use crate::io::IoChain;
|
||||
|
@ -33,7 +33,6 @@ use crate::wchar::{wstr, WString, L};
|
|||
use crate::wutil::{perror, wgettext, wgettext_fmt};
|
||||
use crate::{function, FLOG};
|
||||
use libc::c_int;
|
||||
use nix::sys::stat::Mode;
|
||||
use once_cell::sync::Lazy;
|
||||
use printf_compat::sprintf;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
|
@ -352,7 +351,7 @@ impl Parser {
|
|||
global_event_blocks: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
match open_dir(CStr::from_bytes_with_nul(b".\0").unwrap()) {
|
||||
match open_dir(CStr::from_bytes_with_nul(b".\0").unwrap(), BEST_O_SEARCH) {
|
||||
Ok(fd) => {
|
||||
result.libdata_mut().cwd_fd = Some(Arc::new(fd));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue