Add --octal-permissions argument

Using --octal_permissions will insert another column before the existing
permissions where permissions are encoded using octal values as
requested in #316
This commit is contained in:
Lars Haalck 2020-07-24 13:47:34 +02:00
parent 78ba0b8973
commit 16046d57de
No known key found for this signature in database
GPG Key ID: 802827E17A7038A9
8 changed files with 151 additions and 6 deletions

View File

@ -87,6 +87,11 @@ pub struct PermissionsPlus {
}
/// The permissions encoded as octal values
pub struct OctalPermissions {
pub permissions: Permissions,
}
/// A files number of hard links on the filesystem.
///
/// Under Unix, a file can exist on the filesystem only once but appear in

View File

@ -62,6 +62,7 @@ pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: Takes
// optional feature options
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
pub static OCTAL: Arg = Arg { short: None, long: "octal-permissions", takes_value: TakesValue::Forbidden };
pub static ALL_ARGS: Args = Args(&[
@ -77,5 +78,5 @@ pub static ALL_ARGS: Args = Args(&[
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME,
&GIT, &EXTENDED,
&GIT, &EXTENDED, &OCTAL
]);

View File

@ -58,6 +58,7 @@ LONG VIEW OPTIONS
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
static OCTAL_HELP: &str = r##" --octal-permissions list each file's permission in octal format"##;
/// All the information needed to display the help text, which depends
@ -119,6 +120,8 @@ impl fmt::Display for HelpString {
write!(f, "\n{}", EXTENDED_HELP)?;
}
write!(f, "\n{}", OCTAL_HELP)?;
Ok(())
}
}

View File

@ -228,12 +228,13 @@ impl Columns {
let group = matches.has(&flags::GROUP)?;
let inode = matches.has(&flags::INODE)?;
let links = matches.has(&flags::LINKS)?;
let octal = matches.has(&flags::OCTAL)?;
let permissions = !matches.has(&flags::NO_PERMISSIONS)?;
let filesize = !matches.has(&flags::NO_FILESIZE)?;
let user = !matches.has(&flags::NO_USER)?;
Ok(Columns { time_types, git, blocks, group, inode, links, permissions, filesize, user })
Ok(Columns { time_types, git, octal, blocks, group, inode, links, permissions, filesize, user })
}
}

View File

@ -28,3 +28,6 @@ pub use self::times::Render as TimeRender;
mod users;
pub use self::users::Colours as UserColours;
mod octal;
// octal uses just one colour

116
src/output/render/octal.rs Normal file
View File

@ -0,0 +1,116 @@
use ansi_term::Style;
use crate::output::cell::TextCell;
use crate::fs::fields as f;
impl f::OctalPermissions {
fn bits_to_octal(r: bool, w: bool, x: bool) -> u8 {
(r as u8) * 4 + (w as u8) * 2 + (x as u8) * 1
}
pub fn render(&self, style: Style) -> TextCell {
let perm = &self.permissions;
let octal_sticky = Self::bits_to_octal(perm.setuid, perm.setgid, perm.sticky);
let octal_owner = Self::bits_to_octal(perm.user_read, perm.user_write, perm.user_execute);
let octal_group = Self::bits_to_octal(perm.group_read, perm.group_write, perm.group_execute);
let octal_other = Self::bits_to_octal(perm.other_read, perm.other_write, perm.other_execute);
TextCell::paint(style, format!("{}{}{}{}", octal_sticky, octal_owner, octal_group, octal_other))
}
}
#[cfg(test)]
pub mod test {
use crate::output::cell::TextCell;
use crate::fs::fields as f;
use ansi_term::Colour::*;
#[test]
fn normal_folder() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: true, setuid: false,
group_read: true, group_write: false, group_execute: true, setgid: false,
other_read: true, other_write: false, other_execute: true, sticky: false,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "0755");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
#[test]
fn normal_file() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: false, setuid: false,
group_read: true, group_write: false, group_execute: false, setgid: false,
other_read: true, other_write: false, other_execute: false, sticky: false,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "0644");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
#[test]
fn secret_file() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: false, setuid: false,
group_read: false, group_write: false, group_execute: false, setgid: false,
other_read: false, other_write: false, other_execute: false, sticky: false,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "0600");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
#[test]
fn sticky1() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: true, setuid: true,
group_read: true, group_write: true, group_execute: true, setgid: false,
other_read: true, other_write: true, other_execute: true, sticky: false,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "4777");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
#[test]
fn sticky2() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: true, setuid: false,
group_read: true, group_write: true, group_execute: true, setgid: true,
other_read: true, other_write: true, other_execute: true, sticky: false,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "2777");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
#[test]
fn sticky3() {
let bits = f::Permissions {
user_read: true, user_write: true, user_execute: true, setuid: false,
group_read: true, group_write: true, group_execute: true, setgid: false,
other_read: true, other_write: true, other_execute: true, sticky: true,
};
let octal = f::OctalPermissions{ permissions: bits };
let expected = TextCell::paint_str(Purple.bold(), "1777");
assert_eq!(expected, octal.render(Purple.bold()).into());
}
}

View File

@ -49,6 +49,7 @@ pub struct Columns {
pub blocks: bool,
pub group: bool,
pub git: bool,
pub octal: bool,
// Defaults to true:
pub permissions: bool,
@ -64,6 +65,10 @@ impl Columns {
columns.push(Column::Inode);
}
if self.octal {
columns.push(Column::Octal);
}
if self.permissions {
columns.push(Column::Permissions);
}
@ -125,6 +130,7 @@ pub enum Column {
HardLinks,
Inode,
GitStatus,
Octal,
}
/// Each column can pick its own **Alignment**. Usually, numbers are
@ -161,6 +167,7 @@ impl Column {
Column::HardLinks => "Links",
Column::Inode => "inode",
Column::GitStatus => "Git",
Column::Octal => "Octal",
}
}
}
@ -350,6 +357,12 @@ impl<'a, 'f> Table<'a> {
}
}
fn octal_permissions(&self, file: &File) -> f::OctalPermissions {
f::OctalPermissions {
permissions: file.permissions(),
}
}
fn display(&self, file: &File, column: &Column, xattrs: bool) -> TextCell {
use crate::output::table::TimeType::*;
@ -362,6 +375,7 @@ impl<'a, 'f> Table<'a> {
Column::User => file.user().render(self.colours, &*self.env.lock_users()),
Column::Group => file.group().render(self.colours, &*self.env.lock_users()),
Column::GitStatus => self.git_status(file).render(self.colours),
Column::Octal => self.octal_permissions(file).render(self.colours.octal),
Column::Timestamp(Modified) => file.modified_time().render(self.colours.date, &self.env.tz, &self.time_format),
Column::Timestamp(Changed) => file.changed_time() .render(self.colours.date, &self.env.tz, &self.time_format),

View File

@ -23,6 +23,7 @@ pub struct Colours {
pub inode: Style,
pub blocks: Style,
pub header: Style,
pub octal: Style,
pub symlink_path: Style,
pub control_char: Style,
@ -174,6 +175,7 @@ impl Colours {
date: Blue.normal(),
inode: Purple.normal(),
blocks: Cyan.normal(),
octal: Purple.normal(),
header: Style::default().underline(),
symlink_path: Cyan.normal(),