Fix and refactor cd for Filesystem Shell.
* Fix and refactor cd for Filesystem Shell.
Reorder check conditions, don't check existence twice.
If building for unix check exec bit on folder.
* Import PermissionsExt only on unix target.
* It seems that this is the correct way?
@@ -18,6 +18,9 @@ use std::path::PathBuf;
use std::sync::atomic::Ordering;
use trash as SendToTrash;
+#[cfg(unix)]
+use std::os::unix::fs::PermissionsExt;
+
pub struct FilesystemShell {
pub(crate) path: String,
pub(crate) last_path: String,
@@ -185,8 +188,15 @@ impl Shell for FilesystemShell {
PathBuf::from(&self.last_path)
} else {
let path = PathBuf::from(self.path());
+ let path = dunce::canonicalize(path.join(&target)).map_err(|_| {
+ ShellError::labeled_error(
+ "Cannot change to directory",
+ "directory not found",
+ &v.tag,
+ )
+ })?;
- if target.exists() && !target.is_dir() {
+ if !path.is_dir() {
return Err(ShellError::labeled_error(
"Cannot change to directory",
"is not a directory",
@@ -194,16 +204,32 @@ impl Shell for FilesystemShell {
));
}
- match dunce::canonicalize(path.join(&target)) {
- Ok(p) => p,
- Err(_) => {
+ #[cfg(unix)]
+ {
+ let has_exec = path
+ .metadata()
+ .map(|m| {
+ let mode = umask::Mode::from(m.permissions().mode());
+ mode.has(umask::ALL_EXEC)
+ })
+ .map_err(|e| {
+ ShellError::labeled_error(
+ "Cannot change to directory",
+ format!("cannot stat ({})", e),
+ &v.tag,
+ )
+ })?;
+
+ if !has_exec {
return Err(ShellError::labeled_error(
"Cannot change to directory",
- "directory not found",
+ "permission denied",
&v.tag,
- ))
+ ));
}
}
+
+ path
}
}
};
