mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 20:17: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:
parent
3a6605844f
commit
f9a088cecf
2 changed files with 45 additions and 73 deletions
|
@ -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,59 +213,27 @@ 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,
|
|
||||||
};
|
|
||||||
if ch == 'B' {
|
|
||||||
ch = s_chars.next()?;
|
|
||||||
offset += 1;
|
|
||||||
}
|
}
|
||||||
ch = ch.to_ascii_uppercase();
|
ParseSizeError::SizeTooBig(_) => {
|
||||||
|
crash!(1, "--block-size argument '{}' too large", size_arg)
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
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"] {
|
for env_var in &["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
|
||||||
let env_size = env::var(env_var).ok();
|
if let Ok(env_size) = env::var(env_var) {
|
||||||
if let Some(quantity) = translate_to_pure_number(&env_size.as_deref()) {
|
if let Ok(v) = parse_size(&env_size) {
|
||||||
return quantity;
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if env::var("POSIXLY_CORRECT").is_ok() {
|
if env::var("POSIXLY_CORRECT").is_ok() {
|
||||||
512
|
512
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,7 +241,6 @@ fn read_block_size(s: Option<&str>) -> u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// this takes `my_stat` to avoid having to stat files multiple times.
|
// this takes `my_stat` to avoid having to stat files multiple times.
|
||||||
// XXX: this should use the impl Trait return type when it is stabilized
|
// XXX: this should use the impl Trait return type when it is stabilized
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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!()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue