Skip to content

Commit

Permalink
adds user and group filters
Browse files Browse the repository at this point in the history
  • Loading branch information
wookietreiber committed Nov 15, 2023
1 parent fa6066f commit 174d40e
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 10 deletions.
25 changes: 25 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ use clap::value_parser;
use clap::{crate_description, crate_name, crate_version};
use clap::{Arg, ArgAction, Command};

pub const CONFLICT_FILTER: &str =
"the filter options --group and --user are in conflict, clap SHOULD NOT \
allow both to be present";

/// Returns command-line parser.
pub fn build() -> Command {
let dir = Arg::new("dir")
Expand Down Expand Up @@ -80,6 +84,7 @@ pub fn build() -> Command {
.disable_version_flag(true)
.arg(dir)
.args(output())
.args(filter())
.args(mmapplypolicy())
.arg(max_depth)
.arg(debug)
Expand Down Expand Up @@ -126,6 +131,26 @@ fn output() -> Vec<Arg> {
vec![block, inodes, both]
}

fn filter() -> Vec<Arg> {
let group = Arg::new("group")
.long("group")
.conflicts_with("user")
.help("filter by group")
.long_help("Consider only inodes owned by this group.")
.value_name("name|gid")
.help_heading("Filtering");

let user = Arg::new("user")
.long("user")
.conflicts_with("group")
.help("filter by user")
.long_help("Consider only inodes owned by this user.")
.value_name("name|uid")
.help_heading("Filtering");

vec![group, user]
}

/// Returns arguments forwarded to `mmapplypolicy`.
fn mmapplypolicy() -> Vec<Arg> {
let nodes = Arg::new("nodes")
Expand Down
20 changes: 20 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn get() -> Config {
pub struct Config {
pub dirs: Option<Vec<PathBuf>>,
pub debug: bool,
pub filter: Option<Filter>,
pub max_depth: Option<usize>,
pub mm_nodes: Option<String>,
pub mm_local_work_dir: Option<PathBuf>,
Expand All @@ -53,6 +54,18 @@ impl From<ArgMatches> for Config {

let debug = args.get_one::<bool>("debug").copied().unwrap_or_default();

let group = args.get_one::<String>("group");
let user = args.get_one::<String>("user");

let filter = match (group, user) {
(None, None) => None,
(Some(group), None) => Some(Filter::Group(group.clone())),
(None, Some(user)) => Some(Filter::User(user.clone())),
(Some(_), Some(_)) => {
unreachable!("{}", crate::cli::CONFLICT_FILTER)
}
};

let max_depth = args
.get_one::<usize>("max-depth")
.copied()
Expand All @@ -71,6 +84,7 @@ impl From<ArgMatches> for Config {
Self {
dirs,
debug,
filter,
max_depth,
mm_nodes,
mm_local_work_dir,
Expand All @@ -81,6 +95,12 @@ impl From<ArgMatches> for Config {
}
}

#[derive(Debug)]
pub enum Filter {
Group(String),
User(String),
}

/// Returns whether to count block usage and/or inode usage.
fn cbi(args: &ArgMatches) -> (bool, bool) {
let block = args.get_flag("block");
Expand Down
51 changes: 42 additions & 9 deletions src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,58 @@ use std::fs::File;
use std::io::{self, Write};
use std::path::Path;

// ----------------------------------------------------------------------------
// normal disk usage
// ----------------------------------------------------------------------------
use crate::config::{Config, Filter};

pub fn size(file: &Path) -> io::Result<()> {
pub fn size(file: &Path, config: &Config) -> io::Result<()> {
let mut file = File::create(file)?;

let content = "
RULE
let content = match &config.filter {
Some(Filter::Group(group)) => policy_group(group),
Some(Filter::User(user)) => policy_user(user),
None => String::from(POLICY_DEFAULT),
};

file.write_all(content.as_bytes())?;

Ok(())
}

fn policy_group(group: &str) -> String {
format!(
"RULE
EXTERNAL LIST 'size'
EXEC ''
RULE 'TOTAL'
LIST 'size'
DIRECTORIES_PLUS
SHOW(VARCHAR(FILE_SIZE))
";
WHERE GROUP_ID = {group}
"
)
}

file.write_all(content.as_bytes())?;
fn policy_user(user: &str) -> String {
format!(
"RULE
EXTERNAL LIST 'size'
EXEC ''
Ok(())
RULE 'TOTAL'
LIST 'size'
DIRECTORIES_PLUS
SHOW(VARCHAR(FILE_SIZE))
WHERE USER_ID = {user}
"
)
}

const POLICY_DEFAULT: &str = "RULE
EXTERNAL LIST 'size'
EXEC ''
RULE 'TOTAL'
LIST 'size'
DIRECTORIES_PLUS
SHOW(VARCHAR(FILE_SIZE))
";
2 changes: 1 addition & 1 deletion src/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub fn run(dir: &Path, config: &Config) -> Result<()> {
let policy = tmp.path().join(".policy");
let prefix = tmp.path().join(crate_name!());

policy::size(&policy).with_context(|| {
policy::size(&policy, config).with_context(|| {
format!("writing policy file to {}", policy.display())
})?;

Expand Down

0 comments on commit 174d40e

Please sign in to comment.