1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

du: use "parse_size" from uucore

* fix stderr to be the same than GNU's `du` in case of invalid SIZE
This commit is contained in:
Jan Scheer 2021-05-31 15:22:37 +02:00
parent 3a6605844f
commit f9a088cecf
2 changed files with 45 additions and 73 deletions

View file

@ -14,6 +14,7 @@ use chrono::prelude::DateTime;
use chrono::Local;
use clap::{App, Arg};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::env;
use std::fs;
use std::io::{stderr, ErrorKind, Result, Write};
@ -26,6 +27,7 @@ use std::os::windows::fs::MetadataExt;
use std::os::windows::io::AsRawHandle;
use std::path::PathBuf;
use std::time::{Duration, UNIX_EPOCH};
use uucore::parse_size::{parse_size, ParseSizeError};
use uucore::InvalidEncodingHandling;
#[cfg(windows)]
use winapi::shared::minwindef::{DWORD, LPVOID};
@ -211,64 +213,31 @@ fn get_file_info(path: &PathBuf) -> Option<FileInfo> {
result
}
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()
.rev()
.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<&str>) -> Option<u64> {
match *s {
Some(ref s) => unit_string_to_number(s),
None => None,
}
}
fn read_block_size(s: Option<&str>) -> u64 {
match translate_to_pure_number(&s) {
Some(v) => v,
None => {
if let Some(value) = s {
show_error!("invalid --block-size argument '{}'", value);
};
for env_var in &["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
let env_size = env::var(env_var).ok();
if let Some(quantity) = translate_to_pure_number(&env_size.as_deref()) {
return quantity;
fn read_block_size(s: Option<&str>) -> usize {
if let Some(size_arg) = s {
match parse_size(size_arg) {
Ok(v) => v,
Err(e) => match e {
ParseSizeError::ParseFailure(_) => {
crash!(1, "invalid suffix in --block-size argument '{}'", size_arg)
}
ParseSizeError::SizeTooBig(_) => {
crash!(1, "--block-size argument '{}' too large", size_arg)
}
},
}
} else {
for env_var in &["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
if let Ok(env_size) = env::var(env_var) {
if let Ok(v) = parse_size(&env_size) {
return v;
}
}
if env::var("POSIXLY_CORRECT").is_ok() {
512
} else {
1024
}
}
if env::var("POSIXLY_CORRECT").is_ok() {
512
} else {
1024
}
}
}
@ -595,7 +564,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
};
let block_size = read_block_size(matches.value_of(options::BLOCK_SIZE));
let block_size = u64::try_from(read_block_size(matches.value_of(options::BLOCK_SIZE))).unwrap();
let multiplier: u64 = if matches.is_present(options::SI) {
1000
@ -733,26 +702,12 @@ mod test_du {
#[allow(unused_imports)]
use super::*;
#[test]
fn test_translate_to_pure_number() {
let test_data = [
(Some("10".to_string()), Some(10)),
(Some("10K".to_string()), Some(10 * 1024)),
(Some("5M".to_string()), Some(5 * 1024 * 1024)),
(Some("900KB".to_string()), Some(900 * 1000)),
(Some("BAD_STRING".to_string()), None),
];
for it in test_data.iter() {
assert_eq!(translate_to_pure_number(&it.0.as_deref()), it.1);
}
}
#[test]
fn test_read_block_size() {
let test_data = [
(Some("10".to_string()), 10),
(Some("1024".to_string()), 1024),
(Some("K".to_string()), 1024),
(None, 1024),
(Some("BAD_STRING".to_string()), 1024),
];
for it in test_data.iter() {
assert_eq!(read_block_size(it.0.as_deref()), it.1);

View file

@ -71,6 +71,23 @@ fn _du_basics_subdir(s: &str) {
}
}
#[test]
fn test_du_invalid_size() {
new_ucmd!()
.arg("--block-size=1fb4t")
.arg("/tmp")
.fails()
.code_is(1)
.stderr_only("du: invalid suffix in --block-size argument '1fb4t'");
#[cfg(not(target_pointer_width = "128"))]
new_ucmd!()
.arg("--block-size=1Y")
.arg("/tmp")
.fails()
.code_is(1)
.stderr_only("du: --block-size argument '1Y' too large");
}
#[test]
fn test_du_basics_bad_name() {
new_ucmd!()