1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +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 chrono::Local;
use clap::{App, Arg}; use clap::{App, Arg};
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryFrom;
use std::env; use std::env;
use std::fs; use std::fs;
use std::io::{stderr, ErrorKind, Result, Write}; 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::os::windows::io::AsRawHandle;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::{Duration, UNIX_EPOCH}; use std::time::{Duration, UNIX_EPOCH};
use uucore::parse_size::{parse_size, ParseSizeError};
use uucore::InvalidEncodingHandling; use uucore::InvalidEncodingHandling;
#[cfg(windows)] #[cfg(windows)]
use winapi::shared::minwindef::{DWORD, LPVOID}; use winapi::shared::minwindef::{DWORD, LPVOID};
@ -211,64 +213,31 @@ fn get_file_info(path: &PathBuf) -> Option<FileInfo> {
result result
} }
fn unit_string_to_number(s: &str) -> Option<u64> { fn read_block_size(s: Option<&str>) -> usize {
let mut offset = 0; if let Some(size_arg) = s {
let mut s_chars = s.chars().rev(); match parse_size(size_arg) {
Ok(v) => v,
let (mut ch, multiple) = match s_chars.next() { Err(e) => match e {
Some('B') | Some('b') => ('B', 1000u64), ParseSizeError::ParseFailure(_) => {
Some(ch) => (ch, 1024u64), crash!(1, "invalid suffix in --block-size argument '{}'", size_arg)
None => return None, }
}; ParseSizeError::SizeTooBig(_) => {
if ch == 'B' { crash!(1, "--block-size argument '{}' too large", size_arg)
ch = s_chars.next()?; }
offset += 1; },
} }
ch = ch.to_ascii_uppercase(); } else {
for env_var in &["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
let unit = UNITS if let Ok(env_size) = env::var(env_var) {
.iter() if let Ok(v) = parse_size(&env_size) {
.rev() return v;
.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;
} }
} }
}
if env::var("POSIXLY_CORRECT").is_ok() { if env::var("POSIXLY_CORRECT").is_ok() {
512 512
} else { } else {
1024 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) { let multiplier: u64 = if matches.is_present(options::SI) {
1000 1000
@ -733,26 +702,12 @@ mod test_du {
#[allow(unused_imports)] #[allow(unused_imports)]
use super::*; 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] #[test]
fn test_read_block_size() { fn test_read_block_size() {
let test_data = [ let test_data = [
(Some("10".to_string()), 10), (Some("1024".to_string()), 1024),
(Some("K".to_string()), 1024),
(None, 1024), (None, 1024),
(Some("BAD_STRING".to_string()), 1024),
]; ];
for it in test_data.iter() { for it in test_data.iter() {
assert_eq!(read_block_size(it.0.as_deref()), it.1); 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] #[test]
fn test_du_basics_bad_name() { fn test_du_basics_bad_name() {
new_ucmd!() new_ucmd!()