Skip to content

Commit 16046d5

Browse files
committed
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
1 parent 78ba0b8 commit 16046d5

File tree

8 files changed

+151
-6
lines changed

8 files changed

+151
-6
lines changed

src/fs/fields.rs

+5
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ pub struct PermissionsPlus {
8787
}
8888

8989

90+
/// The permissions encoded as octal values
91+
pub struct OctalPermissions {
92+
pub permissions: Permissions,
93+
}
94+
9095
/// A file’s number of hard links on the filesystem.
9196
///
9297
/// Under Unix, a file can exist on the filesystem only once but appear in

src/options/flags.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ pub static NO_USER: Arg = Arg { short: None, long: "no-user", takes_value: Takes
6060
pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: TakesValue::Forbidden };
6161

6262
// optional feature options
63-
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
64-
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
63+
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
64+
pub static EXTENDED: Arg = Arg { short: Some(b'@'), long: "extended", takes_value: TakesValue::Forbidden };
65+
pub static OCTAL: Arg = Arg { short: None, long: "octal-permissions", takes_value: TakesValue::Forbidden };
6566

6667

6768
pub static ALL_ARGS: Args = Args(&[
@@ -77,5 +78,5 @@ pub static ALL_ARGS: Args = Args(&[
7778
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
7879
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME,
7980

80-
&GIT, &EXTENDED,
81+
&GIT, &EXTENDED, &OCTAL
8182
]);

src/options/help.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ LONG VIEW OPTIONS
5656
--no-user suppress the user field
5757
--no-time suppress the time field"##;
5858

59-
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
60-
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
59+
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
60+
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
61+
static OCTAL_HELP: &str = r##" --octal-permissions list each file's permission in octal format"##;
6162

6263

6364
/// All the information needed to display the help text, which depends
@@ -119,6 +120,8 @@ impl fmt::Display for HelpString {
119120
write!(f, "\n{}", EXTENDED_HELP)?;
120121
}
121122

123+
write!(f, "\n{}", OCTAL_HELP)?;
124+
122125
Ok(())
123126
}
124127
}

src/options/view.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,13 @@ impl Columns {
228228
let group = matches.has(&flags::GROUP)?;
229229
let inode = matches.has(&flags::INODE)?;
230230
let links = matches.has(&flags::LINKS)?;
231+
let octal = matches.has(&flags::OCTAL)?;
231232

232233
let permissions = !matches.has(&flags::NO_PERMISSIONS)?;
233234
let filesize = !matches.has(&flags::NO_FILESIZE)?;
234235
let user = !matches.has(&flags::NO_USER)?;
235236

236-
Ok(Columns { time_types, git, blocks, group, inode, links, permissions, filesize, user })
237+
Ok(Columns { time_types, git, octal, blocks, group, inode, links, permissions, filesize, user })
237238
}
238239
}
239240

src/output/render/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ pub use self::times::Render as TimeRender;
2828

2929
mod users;
3030
pub use self::users::Colours as UserColours;
31+
32+
mod octal;
33+
// octal uses just one colour

src/output/render/octal.rs

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
use ansi_term::Style;
2+
3+
use crate::output::cell::TextCell;
4+
use crate::fs::fields as f;
5+
6+
impl f::OctalPermissions {
7+
fn bits_to_octal(r: bool, w: bool, x: bool) -> u8 {
8+
(r as u8) * 4 + (w as u8) * 2 + (x as u8) * 1
9+
}
10+
11+
pub fn render(&self, style: Style) -> TextCell {
12+
13+
let perm = &self.permissions;
14+
let octal_sticky = Self::bits_to_octal(perm.setuid, perm.setgid, perm.sticky);
15+
let octal_owner = Self::bits_to_octal(perm.user_read, perm.user_write, perm.user_execute);
16+
let octal_group = Self::bits_to_octal(perm.group_read, perm.group_write, perm.group_execute);
17+
let octal_other = Self::bits_to_octal(perm.other_read, perm.other_write, perm.other_execute);
18+
19+
TextCell::paint(style, format!("{}{}{}{}", octal_sticky, octal_owner, octal_group, octal_other))
20+
}
21+
22+
}
23+
24+
#[cfg(test)]
25+
pub mod test {
26+
use crate::output::cell::TextCell;
27+
use crate::fs::fields as f;
28+
29+
use ansi_term::Colour::*;
30+
31+
32+
#[test]
33+
fn normal_folder() {
34+
let bits = f::Permissions {
35+
user_read: true, user_write: true, user_execute: true, setuid: false,
36+
group_read: true, group_write: false, group_execute: true, setgid: false,
37+
other_read: true, other_write: false, other_execute: true, sticky: false,
38+
};
39+
40+
let octal = f::OctalPermissions{ permissions: bits };
41+
42+
let expected = TextCell::paint_str(Purple.bold(), "0755");
43+
assert_eq!(expected, octal.render(Purple.bold()).into());
44+
}
45+
46+
#[test]
47+
fn normal_file() {
48+
let bits = f::Permissions {
49+
user_read: true, user_write: true, user_execute: false, setuid: false,
50+
group_read: true, group_write: false, group_execute: false, setgid: false,
51+
other_read: true, other_write: false, other_execute: false, sticky: false,
52+
};
53+
54+
let octal = f::OctalPermissions{ permissions: bits };
55+
56+
let expected = TextCell::paint_str(Purple.bold(), "0644");
57+
assert_eq!(expected, octal.render(Purple.bold()).into());
58+
}
59+
60+
#[test]
61+
fn secret_file() {
62+
let bits = f::Permissions {
63+
user_read: true, user_write: true, user_execute: false, setuid: false,
64+
group_read: false, group_write: false, group_execute: false, setgid: false,
65+
other_read: false, other_write: false, other_execute: false, sticky: false,
66+
};
67+
68+
let octal = f::OctalPermissions{ permissions: bits };
69+
70+
let expected = TextCell::paint_str(Purple.bold(), "0600");
71+
assert_eq!(expected, octal.render(Purple.bold()).into());
72+
}
73+
74+
#[test]
75+
fn sticky1() {
76+
let bits = f::Permissions {
77+
user_read: true, user_write: true, user_execute: true, setuid: true,
78+
group_read: true, group_write: true, group_execute: true, setgid: false,
79+
other_read: true, other_write: true, other_execute: true, sticky: false,
80+
};
81+
82+
let octal = f::OctalPermissions{ permissions: bits };
83+
84+
let expected = TextCell::paint_str(Purple.bold(), "4777");
85+
assert_eq!(expected, octal.render(Purple.bold()).into());
86+
87+
}
88+
89+
#[test]
90+
fn sticky2() {
91+
let bits = f::Permissions {
92+
user_read: true, user_write: true, user_execute: true, setuid: false,
93+
group_read: true, group_write: true, group_execute: true, setgid: true,
94+
other_read: true, other_write: true, other_execute: true, sticky: false,
95+
};
96+
97+
let octal = f::OctalPermissions{ permissions: bits };
98+
99+
let expected = TextCell::paint_str(Purple.bold(), "2777");
100+
assert_eq!(expected, octal.render(Purple.bold()).into());
101+
}
102+
103+
#[test]
104+
fn sticky3() {
105+
let bits = f::Permissions {
106+
user_read: true, user_write: true, user_execute: true, setuid: false,
107+
group_read: true, group_write: true, group_execute: true, setgid: false,
108+
other_read: true, other_write: true, other_execute: true, sticky: true,
109+
};
110+
111+
let octal = f::OctalPermissions{ permissions: bits };
112+
113+
let expected = TextCell::paint_str(Purple.bold(), "1777");
114+
assert_eq!(expected, octal.render(Purple.bold()).into());
115+
}
116+
}

src/output/table.rs

+14
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub struct Columns {
4949
pub blocks: bool,
5050
pub group: bool,
5151
pub git: bool,
52+
pub octal: bool,
5253

5354
// Defaults to true:
5455
pub permissions: bool,
@@ -64,6 +65,10 @@ impl Columns {
6465
columns.push(Column::Inode);
6566
}
6667

68+
if self.octal {
69+
columns.push(Column::Octal);
70+
}
71+
6772
if self.permissions {
6873
columns.push(Column::Permissions);
6974
}
@@ -125,6 +130,7 @@ pub enum Column {
125130
HardLinks,
126131
Inode,
127132
GitStatus,
133+
Octal,
128134
}
129135

130136
/// Each column can pick its own **Alignment**. Usually, numbers are
@@ -161,6 +167,7 @@ impl Column {
161167
Column::HardLinks => "Links",
162168
Column::Inode => "inode",
163169
Column::GitStatus => "Git",
170+
Column::Octal => "Octal",
164171
}
165172
}
166173
}
@@ -350,6 +357,12 @@ impl<'a, 'f> Table<'a> {
350357
}
351358
}
352359

360+
fn octal_permissions(&self, file: &File) -> f::OctalPermissions {
361+
f::OctalPermissions {
362+
permissions: file.permissions(),
363+
}
364+
}
365+
353366
fn display(&self, file: &File, column: &Column, xattrs: bool) -> TextCell {
354367
use crate::output::table::TimeType::*;
355368

@@ -362,6 +375,7 @@ impl<'a, 'f> Table<'a> {
362375
Column::User => file.user().render(self.colours, &*self.env.lock_users()),
363376
Column::Group => file.group().render(self.colours, &*self.env.lock_users()),
364377
Column::GitStatus => self.git_status(file).render(self.colours),
378+
Column::Octal => self.octal_permissions(file).render(self.colours.octal),
365379

366380
Column::Timestamp(Modified) => file.modified_time().render(self.colours.date, &self.env.tz, &self.time_format),
367381
Column::Timestamp(Changed) => file.changed_time() .render(self.colours.date, &self.env.tz, &self.time_format),

src/style/colours.rs

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct Colours {
2323
pub inode: Style,
2424
pub blocks: Style,
2525
pub header: Style,
26+
pub octal: Style,
2627

2728
pub symlink_path: Style,
2829
pub control_char: Style,
@@ -174,6 +175,7 @@ impl Colours {
174175
date: Blue.normal(),
175176
inode: Purple.normal(),
176177
blocks: Cyan.normal(),
178+
octal: Purple.normal(),
177179
header: Style::default().underline(),
178180

179181
symlink_path: Cyan.normal(),

0 commit comments

Comments
 (0)