From 43aafd2f1c9f5ce5eb45673f41f615d850addf33 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Wed, 2 May 2018 23:23:05 +0200 Subject: [PATCH] chmod: show human-friendly permissions when --changes or --verbose is used. Like GNU chmod. --- src/chmod/chmod.rs | 16 +++++++---- src/ls/Cargo.toml | 2 +- src/ls/ls.rs | 60 +++------------------------------------ src/uucore/fs.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 62 deletions(-) diff --git a/src/chmod/chmod.rs b/src/chmod/chmod.rs index 4fb6457c7..6e53fb5f5 100644 --- a/src/chmod/chmod.rs +++ b/src/chmod/chmod.rs @@ -22,6 +22,7 @@ use std::path::Path; use walker::Walker; #[cfg(not(windows))] use uucore::mode; +use uucore::fs::display_permissions_unix; const NAME: &'static str = "chmod"; static SUMMARY: &'static str = "Change the mode of each FILE to MODE. @@ -226,10 +227,11 @@ impl Chmoder { Ok(()) } + #[cfg(unix)] fn change_file(&self, fperm: u32, mode: u32, file: &Path, path: &str) -> Result<(), i32> { if fperm == mode { if self.verbose && !self.changes { - show_info!("mode of '{}' retained as {:o}", file.display(), fperm); + show_info!("mode of '{}' retained as {:o} ({})", file.display(), fperm, display_permissions_unix(fperm)); } Ok(()) } else if let Err(err) = @@ -240,20 +242,24 @@ impl Chmoder { } if self.verbose { show_info!( - "failed to change mode of file '{}' from {:o} to {:o}", + "failed to change mode of file '{}' from {:o} ({}) to {:o} ({})", file.display(), fperm, - mode + display_permissions_unix(fperm), + mode, + display_permissions_unix(mode) ); } Err(1) } else { if self.verbose || self.changes { show_info!( - "mode of '{}' changed from {:o} to {:o}", + "mode of '{}' changed from {:o} ({}) to {:o} ({})", file.display(), fperm, - mode + display_permissions_unix(fperm), + mode, + display_permissions_unix(mode) ); } Ok(()) diff --git a/src/ls/Cargo.toml b/src/ls/Cargo.toml index 05fa01611..26e628c58 100644 --- a/src/ls/Cargo.toml +++ b/src/ls/Cargo.toml @@ -19,7 +19,7 @@ unicode-width = "0.1.4" [dependencies.uucore] path = "../uucore" -features = ["entries"] +features = ["entries", "fs"] [[bin]] name = "ls" diff --git a/src/ls/ls.rs b/src/ls/ls.rs index 2f380a181..7bfaf3461 100644 --- a/src/ls/ls.rs +++ b/src/ls/ls.rs @@ -24,8 +24,8 @@ extern crate lazy_static; #[macro_use] extern crate uucore; #[cfg(unix)] -use uucore::libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, - S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR}; +use uucore::libc::{mode_t, S_ISGID, S_ISUID, S_ISVTX, S_IWOTH, + S_IXGRP, S_IXOTH, S_IXUSR}; use std::fs; use std::fs::{DirEntry, FileType, Metadata}; @@ -395,6 +395,8 @@ fn display_items(items: &Vec, strip: Option<&Path>, options: &getopts:: } } +use uucore::fs::display_permissions; + fn display_item_long( item: &PathBuf, strip: Option<&Path>, @@ -697,57 +699,3 @@ fn display_symlink_count(metadata: &Metadata) -> String { metadata.nlink().to_string() } -#[cfg(not(unix))] -#[allow(unused_variables)] -fn display_permissions(metadata: &Metadata) -> String { - String::from("---------") -} - -#[cfg(unix)] -fn display_permissions(metadata: &Metadata) -> String { - let mode = metadata.mode() as mode_t; - let mut result = String::with_capacity(9); - result.push(if has!(mode, S_IRUSR) { 'r' } else { '-' }); - result.push(if has!(mode, S_IWUSR) { 'w' } else { '-' }); - result.push(if has!(mode, S_ISUID) { - if has!(mode, S_IXUSR) { - 's' - } else { - 'S' - } - } else if has!(mode, S_IXUSR) { - 'x' - } else { - '-' - }); - - result.push(if has!(mode, S_IRGRP) { 'r' } else { '-' }); - result.push(if has!(mode, S_IWGRP) { 'w' } else { '-' }); - result.push(if has!(mode, S_ISGID) { - if has!(mode, S_IXGRP) { - 's' - } else { - 'S' - } - } else if has!(mode, S_IXGRP) { - 'x' - } else { - '-' - }); - - result.push(if has!(mode, S_IROTH) { 'r' } else { '-' }); - result.push(if has!(mode, S_IWOTH) { 'w' } else { '-' }); - result.push(if has!(mode, S_ISVTX) { - if has!(mode, S_IXOTH) { - 't' - } else { - 'T' - } - } else if has!(mode, S_IXOTH) { - 'x' - } else { - '-' - }); - - result -} diff --git a/src/uucore/fs.rs b/src/uucore/fs.rs index cecaf529f..78ccfbef3 100644 --- a/src/uucore/fs.rs +++ b/src/uucore/fs.rs @@ -11,8 +11,13 @@ extern crate termion; #[cfg(unix)] use super::libc; +#[cfg(unix)] +use super::libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, + S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR}; use std::env; use std::fs; +#[cfg(any(unix, target_os = "redox"))] +use std::os::unix::fs::MetadataExt; #[cfg(target_os = "redox")] use std::io; use std::io::{Error, ErrorKind}; @@ -20,6 +25,12 @@ use std::io::Result as IOResult; use std::path::{Component, Path, PathBuf}; use std::borrow::Cow; +macro_rules! has { + ($mode:expr, $perm:expr) => ( + $mode & ($perm as u32) != 0 + ) +} + pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> { if path.components().all(|e| e != Component::ParentDir) { return path.into(); @@ -195,3 +206,63 @@ pub fn is_stderr_interactive() -> bool { pub fn is_stderr_interactive() -> bool { termion::is_tty(&io::stderr()) } + +#[cfg(not(unix))] +#[allow(unused_variables)] +pub fn display_permissions(metadata: &fs::Metadata) -> String { + String::from("---------") +} + +#[cfg(unix)] +pub fn display_permissions(metadata: &fs::Metadata) -> String { + let mode: mode_t = metadata.mode() as mode_t; + display_permissions_unix(mode as u32) +} + +#[cfg(unix)] +pub fn display_permissions_unix(mode: u32) -> String { + let mut result = String::with_capacity(9); + result.push(if has!(mode, S_IRUSR) { 'r' } else { '-' }); + result.push(if has!(mode, S_IWUSR) { 'w' } else { '-' }); + result.push(if has!(mode, S_ISUID) { + if has!(mode, S_IXUSR) { + 's' + } else { + 'S' + } + } else if has!(mode, S_IXUSR) { + 'x' + } else { + '-' + }); + + result.push(if has!(mode, S_IRGRP) { 'r' } else { '-' }); + result.push(if has!(mode, S_IWGRP) { 'w' } else { '-' }); + result.push(if has!(mode, S_ISGID) { + if has!(mode, S_IXGRP) { + 's' + } else { + 'S' + } + } else if has!(mode, S_IXGRP) { + 'x' + } else { + '-' + }); + + result.push(if has!(mode, S_IROTH) { 'r' } else { '-' }); + result.push(if has!(mode, S_IWOTH) { 'w' } else { '-' }); + result.push(if has!(mode, S_ISVTX) { + if has!(mode, S_IXOTH) { + 't' + } else { + 'T' + } + } else if has!(mode, S_IXOTH) { + 'x' + } else { + '-' + }); + + result +}