1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

Merge pull request #1185 from Arcterus/du-cleanup

du: clean up block size parsing code
This commit is contained in:
rkn 2018-04-20 14:32:27 +04:00 committed by GitHub
commit cc51fdb7a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -14,6 +14,8 @@ extern crate time;
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
// XXX: remove when we no longer support 1.22.0
use std::ascii::AsciiExt;
use std::collections::HashSet; use std::collections::HashSet;
use std::env; use std::env;
use std::fs; use std::fs;
@ -37,7 +39,7 @@ const LONG_HELP: &'static str = "
"; ";
// TODO: Suport Z & Y (currently limited by size of u64) // TODO: Suport Z & Y (currently limited by size of u64)
static UNITS: [(char, u32); 6] = [('E', 6), ('P', 5), ('T', 4), ('G', 3), ('M', 2), ('K', 1)]; const UNITS: [(char, u32); 6] = [('K', 1), ('M', 2), ('G', 3), ('T', 4), ('P', 5), ('E', 6)];
struct Options { struct Options {
all: bool, all: bool,
@ -76,47 +78,39 @@ impl Stat {
} }
} }
fn unit_string_to_number(s: &str) -> Option<u64> {
let mut offset = 0;
let mut s_chars = s.chars().rev();
let (mut ch, multiple) = match s_chars.next() {
Some('B') | Some('b') => ('B', 1000u64),
Some(ch) => (ch, 1024u64),
None => return None,
};
if ch == 'B' {
ch = s_chars.next()?;
offset += 1;
}
ch = ch.to_ascii_uppercase();
let unit = UNITS
.iter()
.find(|&&(unit_ch, _)| unit_ch == ch)
.map(|&(_, val)| {
// we found a match, so increment offset
offset += 1;
val
})
.or_else(|| if multiple == 1024 { Some(0) } else { None })?;
let number = s[..s.len() - offset].parse::<u64>().ok()?;
Some(number * multiple.pow(unit))
}
fn translate_to_pure_number(s: &Option<String>) -> Option<u64> { fn translate_to_pure_number(s: &Option<String>) -> Option<u64> {
match s { match s {
&Some(ref s) => { &Some(ref s) => unit_string_to_number(s),
let mut found_number = false;
let mut found_letter = false;
let mut numbers = String::new();
let mut letters = String::new();
for c in s.trim().chars() {
if found_letter && c.is_digit(10) || !found_number && !c.is_digit(10) {
return None;
} else if c.is_digit(10) {
found_number = true;
numbers.push(c);
} else if c.is_alphabetic() {
found_letter = true;
letters.push(c);
}
}
let number = numbers.parse::<u64>().unwrap();
let multiple = match letters[..].to_uppercase().as_str() {
"" => 1,
"K" => 1024u64.pow(1),
"M" => 1024u64.pow(2),
"G" => 1024u64.pow(3),
"T" => 1024u64.pow(4),
"P" => 1024u64.pow(5),
"E" => 1024u64.pow(6),
"Z" => 1024u64.pow(7),
"Y" => 1024u64.pow(8),
"KB" => 1000u64.pow(1),
"MB" => 1000u64.pow(2),
"GB" => 1000u64.pow(3),
"TB" => 1000u64.pow(4),
"PB" => 1000u64.pow(5),
"EB" => 1000u64.pow(6),
"ZB" => 1000u64.pow(7),
"YB" => 1000u64.pow(8),
_ => return None,
};
Some(number * multiple)
}
&None => None, &None => None,
} }
} }
@ -125,15 +119,13 @@ fn read_block_size(s: Option<String>) -> u64 {
match translate_to_pure_number(&s) { match translate_to_pure_number(&s) {
Some(v) => v, Some(v) => v,
None => { None => {
match s { if let Some(value) = s {
Some(value) => show_error!("invalid --block-size argument '{}'", value), show_error!("invalid --block-size argument '{}'", value);
_ => (),
}; };
for env_var in ["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"].into_iter() { for env_var in &["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
match translate_to_pure_number(&env::var(env_var).ok()) { if let Some(quantity) = translate_to_pure_number(&env::var(env_var).ok()) {
Some(quantity) => return quantity, return quantity;
None => (),
} }
} }
@ -174,7 +166,8 @@ fn du(
for f in read.into_iter() { for f in read.into_iter() {
match f { match f {
Ok(entry) => match Stat::new(entry.path()) { Ok(entry) => {
match Stat::new(entry.path()) {
Ok(this_stat) => { Ok(this_stat) => {
if this_stat.is_dir { if this_stat.is_dir {
futures.push(du(this_stat, options, depth + 1, inodes)); futures.push(du(this_stat, options, depth + 1, inodes));
@ -191,18 +184,15 @@ fn du(
} }
} }
Err(error) => show_error!("{}", error), Err(error) => show_error!("{}", error),
}, }
}
Err(error) => show_error!("{}", error), Err(error) => show_error!("{}", error),
} }
} }
} }
stats.extend( stats.extend(futures.into_iter().flat_map(|val| val).rev().filter_map(
futures |stat| {
.into_iter()
.flat_map(|val| val)
.rev()
.filter_map(|stat| {
if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path { if !options.separate_dirs && stat.path.parent().unwrap() == my_stat.path {
my_stat.size += stat.size; my_stat.size += stat.size;
my_stat.blocks += stat.blocks; my_stat.blocks += stat.blocks;
@ -212,8 +202,8 @@ fn du(
} else { } else {
None None
} }
}), },
); ));
stats.push(my_stat); stats.push(my_stat);
Box::new(stats.into_iter()) Box::new(stats.into_iter())
} }
@ -344,7 +334,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
}; };
let time_format_str = match matches.opt_str("time-style") { let time_format_str = match matches.opt_str("time-style") {
Some(s) => match &s[..] { Some(s) => {
match &s[..] {
"full-iso" => "%Y-%m-%d %H:%M:%S.%f %z", "full-iso" => "%Y-%m-%d %H:%M:%S.%f %z",
"long-iso" => "%Y-%m-%d %H:%M", "long-iso" => "%Y-%m-%d %H:%M",
"iso" => "%Y-%m-%d", "iso" => "%Y-%m-%d",
@ -361,7 +352,8 @@ Try '{} --help' for more information.",
); );
return 1; return 1;
} }
}, }
}
None => "%Y-%m-%d %H:%M", None => "%Y-%m-%d %H:%M",
}; };
@ -389,7 +381,8 @@ Try '{} --help' for more information.",
let tm = { let tm = {
let (secs, nsecs) = { let (secs, nsecs) = {
let time = match matches.opt_str("time") { let time = match matches.opt_str("time") {
Some(s) => match &s[..] { Some(s) => {
match &s[..] {
"accessed" => stat.accessed, "accessed" => stat.accessed,
"created" => stat.created, "created" => stat.created,
"modified" => stat.modified, "modified" => stat.modified,
@ -403,7 +396,8 @@ Try '{} --help' for more information.",
); );
return 1; return 1;
} }
}, }
}
None => stat.modified, None => stat.modified,
}; };
((time / 1000) as i64, (time % 1000 * 1000000) as i32) ((time / 1000) as i64, (time % 1000 * 1000000) as i32)