Clean up cd.rs (#7876)

Some general cleanup of `cd.rs`; the permission checking code was a
little hard to follow. Reworded comments and variable names,
reorganized+renamed the module used for Unix file permissions.
This commit is contained in:
Reilly Wood 2023-01-27 15:02:38 +01:00 committed by GitHub
parent 9ae2e528c5
commit 76292ef10c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -10,22 +10,16 @@ use nu_protocol::{
}; };
use std::path::Path; use std::path::Path;
// when the file under the fold executable // For checking whether we have permission to cd to a directory
#[cfg(unix)] #[cfg(unix)]
mod permission_mods { mod file_permissions {
pub type Mode = u32; pub type Mode = u32;
pub mod unix {
use super::Mode;
pub const USER_EXECUTE: Mode = libc::S_IXUSR as Mode; pub const USER_EXECUTE: Mode = libc::S_IXUSR as Mode;
pub const GROUP_EXECUTE: Mode = libc::S_IXGRP as Mode; pub const GROUP_EXECUTE: Mode = libc::S_IXGRP as Mode;
pub const OTHER_EXECUTE: Mode = libc::S_IXOTH as Mode; pub const OTHER_EXECUTE: Mode = libc::S_IXOTH as Mode;
} }
}
// use to return the message of the result of change director // The result of checking whether we have permission to cd to a directory
// 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)] #[derive(Debug)]
enum PermissionResult<'a> { enum PermissionResult<'a> {
PermissionOk, PermissionOk,
@ -169,8 +163,10 @@ impl Command for Cd {
} }
}; };
let path_tointo = path.clone(); let path_value = Value::String {
let path_value = Value::String { val: path, span }; val: path.clone(),
span,
};
let cwd = Value::string(cwd.to_string_lossy(), call.head); let cwd = Value::string(cwd.to_string_lossy(), call.head);
let mut shells = get_shells(engine_state, stack, cwd); let mut shells = get_shells(engine_state, stack, cwd);
@ -193,16 +189,16 @@ impl Command for Cd {
stack.add_env_var("OLDPWD".into(), oldpwd) stack.add_env_var("OLDPWD".into(), oldpwd)
} }
match have_permission(&path) {
//FIXME: this only changes the current scope, but instead this environment variable //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 //should probably be a block that loads the information from the state in the overlay
match have_permission(&path_tointo) {
PermissionResult::PermissionOk => { PermissionResult::PermissionOk => {
stack.add_env_var("PWD".into(), path_value); stack.add_env_var("PWD".into(), path_value);
Ok(PipelineData::empty()) Ok(PipelineData::empty())
} }
PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError(format!( PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError(format!(
"Cannot change directory to {}: {}", "Cannot change directory to {}: {}",
path_tointo, reason path, reason
))), ))),
} }
} }
@ -227,6 +223,9 @@ impl Command for Cd {
] ]
} }
} }
// TODO: Maybe we should use file_attributes() from https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html
// More on that here: https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
#[cfg(windows)] #[cfg(windows)]
fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> { fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
match dir.as_ref().read_dir() { match dir.as_ref().read_dir() {
@ -260,26 +259,26 @@ fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
current_user_gid == owner_group, current_user_gid == owner_group,
) { ) {
(true, _) => { (true, _) => {
if has_bit(permission_mods::unix::USER_EXECUTE) { if has_bit(file_permissions::USER_EXECUTE) {
PermissionResult::PermissionOk PermissionResult::PermissionOk
} else { } else {
PermissionResult::PermissionDenied( PermissionResult::PermissionDenied(
"You are the owner but do not have the execute permission", "You are the owner but do not have execute permission",
) )
} }
} }
(false, true) => { (false, true) => {
if has_bit(permission_mods::unix::GROUP_EXECUTE) { if has_bit(file_permissions::GROUP_EXECUTE) {
PermissionResult::PermissionOk PermissionResult::PermissionOk
} else { } else {
PermissionResult::PermissionDenied( PermissionResult::PermissionDenied(
"You are in the group but do not have the execute permission", "You are in the group but do not have execute permission",
) )
} }
} }
(false, false) => { (false, false) => {
if has_bit(permission_mods::unix::OTHER_EXECUTE) if has_bit(file_permissions::OTHER_EXECUTE)
|| (has_bit(permission_mods::unix::GROUP_EXECUTE) || (has_bit(file_permissions::GROUP_EXECUTE)
&& any_group(current_user_gid, owner_group)) && any_group(current_user_gid, owner_group))
{ {
PermissionResult::PermissionOk PermissionResult::PermissionOk
@ -291,7 +290,7 @@ fn have_permission(dir: impl AsRef<Path>) -> PermissionResult<'static> {
} }
} }
} }
Err(_) => PermissionResult::PermissionDenied("Could not retrieve the metadata"), Err(_) => PermissionResult::PermissionDenied("Could not retrieve file metadata"),
} }
} }