forked from extern/nushell
fix: fixcd (#6799)
* fix: fixcd try to fix Log: try to fix the bug with can enter a permisson error fold * change wording * fat * fmt Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
@ -6,6 +6,29 @@ use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value,
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
// when the file under the fold executeable
|
||||
#[cfg(unix)]
|
||||
mod permission_mods {
|
||||
pub type Mode = u32;
|
||||
pub mod unix {
|
||||
use super::Mode;
|
||||
pub const USER_EXECUTE: Mode = libc::S_IXUSR as Mode;
|
||||
pub const GROUP_EXECUTE: Mode = libc::S_IXGRP as Mode;
|
||||
pub const OTHER_EXECUTE: Mode = libc::S_IXOTH as Mode;
|
||||
}
|
||||
}
|
||||
|
||||
// use to return the message of the result of change director
|
||||
// TODO: windows, maybe should use file_attributes function in https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html
|
||||
// TODO: the meaning of the result of the function can be found in https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
|
||||
// TODO: if have realize the logic on windows, remove the cfg
|
||||
#[derive(Debug)]
|
||||
enum PermissionResult<'a> {
|
||||
PermissionOk,
|
||||
PermissionDenied(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Cd;
|
||||
@ -141,6 +164,7 @@ impl Command for Cd {
|
||||
}
|
||||
};
|
||||
|
||||
let path_tointo = path.clone();
|
||||
let path_value = Value::String { val: path, span };
|
||||
let cwd = Value::String {
|
||||
val: cwd.to_string_lossy().to_string(),
|
||||
@ -172,9 +196,16 @@ impl Command for Cd {
|
||||
|
||||
//FIXME: this only changes the current scope, but instead this environment variable
|
||||
//should probably be a block that loads the information from the state in the overlay
|
||||
|
||||
stack.add_env_var("PWD".into(), path_value);
|
||||
Ok(PipelineData::new(call.head))
|
||||
match have_permission(&path_tointo) {
|
||||
PermissionResult::PermissionOk => {
|
||||
stack.add_env_var("PWD".into(), path_value);
|
||||
Ok(PipelineData::new(call.head))
|
||||
}
|
||||
PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError(format!(
|
||||
"Cannot change directory to {}: {}",
|
||||
path_tointo, reason
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
@ -197,3 +228,65 @@ impl Command for Cd {
|
||||
]
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
|
||||
match dir.as_ref().read_dir() {
|
||||
Err(e) => {
|
||||
if matches!(e.kind(), std::io::ErrorKind::PermissionDenied) {
|
||||
PermissionResult::PermissionDenied("Folder is unable to be read")
|
||||
} else {
|
||||
PermissionResult::PermissionOk
|
||||
}
|
||||
}
|
||||
Ok(_) => PermissionResult::PermissionOk,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
|
||||
match dir.as_ref().metadata() {
|
||||
Ok(metadata) => {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let bits = metadata.mode();
|
||||
let has_bit = |bit| bits & bit == bit;
|
||||
let current_user = users::get_current_uid();
|
||||
if current_user == 0 {
|
||||
return PermissionResult::PermissionOk;
|
||||
}
|
||||
let current_group = users::get_current_gid();
|
||||
let owner_user = metadata.uid();
|
||||
let owner_group = metadata.gid();
|
||||
match (current_user == owner_user, current_group == owner_group) {
|
||||
(true, _) => {
|
||||
if has_bit(permission_mods::unix::USER_EXECUTE) {
|
||||
PermissionResult::PermissionOk
|
||||
} else {
|
||||
PermissionResult::PermissionDenied(
|
||||
"You are the owner but do not have the execute permission",
|
||||
)
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
if has_bit(permission_mods::unix::GROUP_EXECUTE) {
|
||||
PermissionResult::PermissionOk
|
||||
} else {
|
||||
PermissionResult::PermissionDenied(
|
||||
"You are in the group but do not have the execute permission",
|
||||
)
|
||||
}
|
||||
}
|
||||
// other_user or root
|
||||
(false, false) => {
|
||||
if has_bit(permission_mods::unix::OTHER_EXECUTE) {
|
||||
PermissionResult::PermissionOk
|
||||
} else {
|
||||
PermissionResult::PermissionDenied(
|
||||
"You are neither the owner, in the group, nor the super user and do not have permission",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => PermissionResult::PermissionDenied("Could not retrieve the metadata"),
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user