Finish truncate applet (untested)

This commit is contained in:
Nathan Fisher 2023-04-17 22:40:49 -04:00
parent 8e302f3f85
commit 97679e43a6
1 changed files with 49 additions and 6 deletions

View File

@ -1,7 +1,9 @@
use std::fs::File;
use {
super::Cmd,
clap::{Arg, ArgAction, ArgGroup, Command, ValueHint},
std::{error::Error, fmt, fs, num::ParseIntError},
std::{error::Error, fmt, fs, num::ParseIntError, path::PathBuf},
};
#[derive(Debug, Default)]
@ -65,12 +67,49 @@ impl Cmd for Truncate {
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
let size = if let Some(file) = matches.get_one::<String>("reference") {
let num: i64 = fs::metadata(file)?.len().try_into()?;
Size { operator: Operator::Equal, num }
Size {
operator: Operator::Equal,
num,
}
} else if let Some(s) = matches.get_one::<String>("size") {
parse_size(s)?
} else {
unreachable!();
};
matches
.get_many::<String>("file")
.unwrap()
.try_for_each(|file| {
let path = PathBuf::from(file);
if !matches.get_flag("create") && !path.exists() {
return Ok(());
}
let fd = File::options().write(true).create(true).open(&path)?;
let current: i64 = fd.metadata()?.len().try_into()?;
let len = match size.operator {
Operator::Equal => size.num,
Operator::Add => size.num + current,
Operator::Remove => current - size.num,
Operator::ModUp => {
if current % size.num == 0 {
current
} else {
let fraction = current / size.num;
(fraction + 1) * size.num
}
}
Operator::ModDown => {
if current % size.num == 0 {
current
} else {
let fraction = current / size.num;
fraction * size.num
}
}
};
unistd::ftruncate(&fd, len)?;
Ok::<(), Box<dyn Error>>(())
})?;
Ok(())
}
@ -79,6 +118,7 @@ impl Cmd for Truncate {
}
}
#[derive(PartialEq)]
enum Operator {
Equal,
Add,
@ -201,13 +241,16 @@ fn parse_size(size: &str) -> Result<Size, ParseSizeError> {
if let Some(m) = multiplier {
match m {
Multiplier::Kilo => num *= 1024,
Multiplier::Mega => num *= (1024 * 1024),
Multiplier::Giga => num *= (1024 * 1024 * 1024),
Multiplier::Tera => num *= (1024 * 1024 * 1024 * 1024),
Multiplier::Mega => num *= 1024 * 1024,
Multiplier::Giga => num *= 1024 * 1024 * 1024,
Multiplier::Tera => num *= 1024 * 1024 * 1024 * 1024,
}
}
match operator {
Some(operator) => Ok(Size { operator, num }),
None => Ok(Size { operator: Operator::Equal, num }),
None => Ok(Size {
operator: Operator::Equal,
num,
}),
}
}