From 619c968c4693f85d81c3210f50e55920c5694f4e Mon Sep 17 00:00:00 2001 From: Christian Krause Date: Wed, 15 Nov 2023 12:35:09 +0100 Subject: [PATCH] adds flag to use KB_ALLOCATED instead of FILE_SIZE --- src/cli.rs | 14 +++++- src/config.rs | 120 +++++++++++++++++++++++++++++++++----------------- src/output.rs | 22 ++++----- src/policy.rs | 26 ++++++----- 4 files changed, 120 insertions(+), 62 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index d121c57..8775638 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -92,7 +92,7 @@ pub fn build() -> Command { .arg(version) .after_help( "Differences to `du`: `mmdu` defaults to summarized and human readable output \ - and uses apparent size.", + and uses apparent size, i.e. `FILE_SIZE` as the policy attribute.", ) } @@ -128,7 +128,17 @@ fn output() -> Vec { .display_order(3) .help_heading("Counting"); - vec![block, inodes, both] + let kb_allocated = Arg::new("kb-allocated") + .long("kb-allocated") + .action(ArgAction::SetTrue) + .help("KB_ALLOCATED instead of FILE_SIZE") + .long_help( + "Use KB_ALLOCATED instead of FILE_SIZE as the policy attribute.", + ) + .display_order(4) + .help_heading("Counting"); + + vec![block, inodes, both, kb_allocated] } fn filter() -> Vec { diff --git a/src/config.rs b/src/config.rs index cf67230..2174b0e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,8 +42,8 @@ pub struct Config { pub mm_nodes: Option, pub mm_local_work_dir: Option, pub mm_global_work_dir: Option, - pub count_bytes: bool, - pub count_inodes: bool, + pub byte_mode: ByteMode, + pub count_mode: CountMode, } impl From for Config { @@ -79,7 +79,13 @@ impl From for Config { let mm_global_work_dir = args.get_one::("global-work-dir").cloned(); - let (count_bytes, count_inodes) = cbi(&args); + let byte_mode = if args.get_flag("kb-allocated") { + ByteMode::KBAllocated + } else { + ByteMode::FileSize + }; + + let count_mode = CountMode::from(&args); Self { dirs, @@ -89,8 +95,8 @@ impl From for Config { mm_nodes, mm_local_work_dir, mm_global_work_dir, - count_bytes, - count_inodes, + byte_mode, + count_mode, } } } @@ -101,17 +107,40 @@ pub enum Filter { User(String), } -/// Returns whether to count block usage and/or inode usage. -fn cbi(args: &ArgMatches) -> (bool, bool) { - let block = args.get_flag("block"); - let inodes = args.get_flag("inodes"); - let both = args.get_flag("both"); - - // most conditions aren't possible due to `overrides_with_all` - match (block, inodes, both) { - (_, true, _) => (false, true), - (_, _, true) => (true, true), - _ => (true, false), +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ByteMode { + FileSize, + KBAllocated, +} + +impl ByteMode { + pub const fn policy_attribute(self) -> &'static str { + match self { + Self::FileSize => "FILE_SIZE", + Self::KBAllocated => "KB_ALLOCATED", + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CountMode { + Inodes, + Bytes, + Both, +} + +impl From<&ArgMatches> for CountMode { + fn from(args: &ArgMatches) -> Self { + let block = args.get_flag("block"); + let inodes = args.get_flag("inodes"); + let both = args.get_flag("both"); + + // most conditions aren't possible due to `overrides_with_all` + match (block, inodes, both) { + (_, true, _) => Self::Inodes, + (_, _, true) => Self::Both, + _ => Self::Bytes, + } } } @@ -119,44 +148,55 @@ fn cbi(args: &ArgMatches) -> (bool, bool) { // tests // ---------------------------------------------------------------------------- +#[cfg(test)] +impl From for CountMode { + fn from(args: ArgMatches) -> Self { + Self::from(&args) + } +} + #[cfg(test)] mod test { + use super::CountMode; + #[test] - fn cbi() { + fn count_mode() { let cli = crate::cli::build(); assert_eq!( - (true, false), - super::cbi(&cli.clone().get_matches_from([clap::crate_name!()])) + CountMode::Bytes, + CountMode::from( + cli.clone().get_matches_from([clap::crate_name!()]) + ) ); assert_eq!( - (true, false), - super::cbi( - &cli.clone() + CountMode::Bytes, + CountMode::from( + cli.clone() .get_matches_from([clap::crate_name!(), "--block"]) ) ); assert_eq!( - (false, true), - super::cbi( - &cli.clone() + CountMode::Inodes, + CountMode::from( + cli.clone() .get_matches_from([clap::crate_name!(), "--inodes"]) ) ); assert_eq!( - (true, true), - super::cbi( - &cli.clone() + CountMode::Both, + CountMode::from( + cli.clone() .get_matches_from([clap::crate_name!(), "--both"]) ) ); assert_eq!( - (false, true), - super::cbi(&cli.clone().get_matches_from([ + CountMode::Inodes, + CountMode::from(cli.clone().get_matches_from([ clap::crate_name!(), "--block", "--inodes" @@ -164,8 +204,8 @@ mod test { ); assert_eq!( - (true, true), - super::cbi(&cli.clone().get_matches_from([ + CountMode::Both, + CountMode::from(cli.clone().get_matches_from([ clap::crate_name!(), "--block", "--both" @@ -173,8 +213,8 @@ mod test { ); assert_eq!( - (true, false), - super::cbi(&cli.clone().get_matches_from([ + CountMode::Bytes, + CountMode::from(cli.clone().get_matches_from([ clap::crate_name!(), "--inodes", "--block" @@ -182,8 +222,8 @@ mod test { ); assert_eq!( - (true, true), - super::cbi(&cli.clone().get_matches_from([ + CountMode::Both, + CountMode::from(cli.clone().get_matches_from([ clap::crate_name!(), "--inodes", "--both" @@ -191,8 +231,8 @@ mod test { ); assert_eq!( - (true, false), - super::cbi(&cli.clone().get_matches_from([ + CountMode::Bytes, + CountMode::from(cli.clone().get_matches_from([ clap::crate_name!(), "--both", "--block" @@ -200,8 +240,8 @@ mod test { ); assert_eq!( - (false, true), - super::cbi(&cli.get_matches_from([ + CountMode::Inodes, + CountMode::from(cli.get_matches_from([ clap::crate_name!(), "--both", "--inodes" diff --git a/src/output.rs b/src/output.rs index e0095ea..be3ee54 100644 --- a/src/output.rs +++ b/src/output.rs @@ -27,23 +27,25 @@ use std::path::Path; use bytesize::ByteSize; -use crate::config::Config; +use crate::config::{ByteMode, Config, CountMode}; pub fn output(dir: &Path, inodes: u64, bytes: u64, config: &Config) { - let humanized = humanize(bytes); + let humanized = match config.byte_mode { + ByteMode::FileSize => humanize(ByteSize::b(bytes)), + ByteMode::KBAllocated => humanize(ByteSize::kib(bytes)), + }; + let dir = dir.display(); - if config.count_bytes && config.count_inodes { - println!("{humanized}\t{inodes}\t{dir}"); - } else if config.count_bytes { - println!("{humanized}\t{dir}"); - } else if config.count_inodes { - println!("{inodes}\t{dir}"); + match config.count_mode { + CountMode::Both => println!("{humanized}\t{inodes}\t{dir}"), + CountMode::Bytes => println!("{humanized}\t{dir}"), + CountMode::Inodes => println!("{inodes}\t{dir}"), } } -fn humanize(bytes: u64) -> String { - ByteSize(bytes) +fn humanize(bytes: ByteSize) -> String { + bytes .to_string_as(true) .replace("iB", "") .replace(' ', "") diff --git a/src/policy.rs b/src/policy.rs index 1485141..fac9887 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -32,10 +32,12 @@ use crate::config::{Config, Filter}; pub fn size(file: &Path, config: &Config) -> io::Result<()> { let mut file = File::create(file)?; + let attribute = config.byte_mode.policy_attribute(); + let content = match &config.filter { - Some(Filter::Group(group)) => policy_group(group), - Some(Filter::User(user)) => policy_user(user), - None => String::from(POLICY_DEFAULT), + Some(Filter::Group(group)) => policy_group(group, attribute), + Some(Filter::User(user)) => policy_user(user, attribute), + None => policy_default(attribute), }; file.write_all(content.as_bytes())?; @@ -43,7 +45,7 @@ pub fn size(file: &Path, config: &Config) -> io::Result<()> { Ok(()) } -fn policy_group(group: &str) -> String { +fn policy_group(group: &str, attribute: &str) -> String { format!( "RULE EXTERNAL LIST 'size' @@ -52,13 +54,13 @@ fn policy_group(group: &str) -> String { RULE 'TOTAL' LIST 'size' DIRECTORIES_PLUS - SHOW(VARCHAR(FILE_SIZE)) + SHOW(VARCHAR({attribute})) WHERE GROUP_ID = {group} " ) } -fn policy_user(user: &str) -> String { +fn policy_user(user: &str, attribute: &str) -> String { format!( "RULE EXTERNAL LIST 'size' @@ -67,18 +69,22 @@ fn policy_user(user: &str) -> String { RULE 'TOTAL' LIST 'size' DIRECTORIES_PLUS - SHOW(VARCHAR(FILE_SIZE)) + SHOW(VARCHAR({attribute})) WHERE USER_ID = {user} " ) } -const POLICY_DEFAULT: &str = "RULE +fn policy_default(attribute: &str) -> String { + format!( + "RULE EXTERNAL LIST 'size' EXEC '' RULE 'TOTAL' LIST 'size' DIRECTORIES_PLUS - SHOW(VARCHAR(FILE_SIZE)) -"; + SHOW(VARCHAR({attribute})) +" + ) +}