Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/cspell.dictionaries/workspace.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ fcntl
vmsplice

# * vars/libc
memsize
sysctlbyname
COMFOLLOW
EXDEV
FILENO
Expand Down
8 changes: 7 additions & 1 deletion src/uu/df/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ path = "src/df.rs"

[dependencies]
clap = { workspace = true }
uucore = { workspace = true, features = ["libc", "fsext", "parser-size", "fs"] }
uucore = { workspace = true, features = [
"libc",
"fsext",
"parser-size",
"fs",
"format",
] }
unicode-width = { workspace = true }
thiserror = { workspace = true }
fluent = { workspace = true }
Expand Down
47 changes: 37 additions & 10 deletions src/uu/df/src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use std::{env, fmt};

use uucore::{
display::Quotable,
parser::parse_size::{ParseSizeError, parse_size_non_zero_u64, parse_size_u64},
parser::parse_size::{
ParseSizeError, extract_thousands_separator_flag, parse_size_non_zero_u64, parse_size_u64,
},
};

/// The first ten powers of 1024.
Expand Down Expand Up @@ -160,6 +162,13 @@ pub(crate) enum BlockSize {
Bytes(u64),
}

/// Configuration for block size display, including thousands separator flag.
#[derive(Debug, PartialEq)]
pub(crate) struct BlockSizeConfig {
pub(crate) block_size: BlockSize,
pub(crate) use_thousands_separator: bool,
}

impl BlockSize {
/// Returns the associated value
pub(crate) fn as_u64(&self) -> u64 {
Expand Down Expand Up @@ -191,29 +200,47 @@ impl Default for BlockSize {
}
}

pub(crate) fn read_block_size(matches: &ArgMatches) -> Result<BlockSize, ParseSizeError> {
pub(crate) fn read_block_size(matches: &ArgMatches) -> Result<BlockSizeConfig, ParseSizeError> {
if matches.contains_id(OPT_BLOCKSIZE) {
let s = matches.get_one::<String>(OPT_BLOCKSIZE).unwrap();
let bytes = parse_size_u64(s)?;
let (cleaned, use_thousands) = extract_thousands_separator_flag(s);
let bytes = parse_size_u64(cleaned)?;

if bytes > 0 {
Ok(BlockSize::Bytes(bytes))
Ok(BlockSizeConfig {
block_size: BlockSize::Bytes(bytes),
use_thousands_separator: use_thousands,
})
} else {
Err(ParseSizeError::ParseFailure(format!("{}", s.quote())))
}
} else if matches.get_flag(OPT_PORTABILITY) {
Ok(BlockSize::default())
} else if let Some(bytes) = block_size_from_env() {
Ok(BlockSize::Bytes(bytes))
Ok(BlockSizeConfig {
block_size: BlockSize::default(),
use_thousands_separator: false,
})
} else if let Some((bytes, use_thousands)) = block_size_from_env() {
Ok(BlockSizeConfig {
block_size: BlockSize::Bytes(bytes),
use_thousands_separator: use_thousands,
})
} else {
Ok(BlockSize::default())
Ok(BlockSizeConfig {
block_size: BlockSize::default(),
use_thousands_separator: false,
})
}
}

fn block_size_from_env() -> Option<u64> {
fn block_size_from_env() -> Option<(u64, bool)> {
for env_var in ["DF_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"] {
if let Ok(env_size) = env::var(env_var) {
return parse_size_non_zero_u64(&env_size).ok();
let (cleaned, use_thousands) = extract_thousands_separator_flag(&env_size);
if let Ok(size) = parse_size_non_zero_u64(cleaned) {
return Some((size, use_thousands));
}
// If env var is set but invalid, return None (don't check other env vars)
return None;
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/uu/df/src/df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use std::io::stdout;
use std::path::Path;
use thiserror::Error;

use crate::blocks::{BlockSize, read_block_size};
use crate::blocks::{BlockSize, BlockSizeConfig, read_block_size};
use crate::columns::{Column, ColumnError};
use crate::filesystem::Filesystem;
use crate::filesystem::FsError;
Expand Down Expand Up @@ -62,7 +62,7 @@ struct Options {
show_local_fs: bool,
show_all_fs: bool,
human_readable: Option<HumanReadable>,
block_size: BlockSize,
block_size_config: BlockSizeConfig,
header_mode: HeaderMode,

/// Optional list of filesystem types to include in the output table.
Expand Down Expand Up @@ -92,7 +92,10 @@ impl Default for Options {
Self {
show_local_fs: Default::default(),
show_all_fs: Default::default(),
block_size: BlockSize::default(),
block_size_config: BlockSizeConfig {
block_size: BlockSize::default(),
use_thousands_separator: false,
},
human_readable: Option::default(),
header_mode: HeaderMode::default(),
include: Option::default(),
Expand Down Expand Up @@ -167,13 +170,14 @@ impl Options {
show_local_fs: matches.get_flag(OPT_LOCAL),
show_all_fs: matches.get_flag(OPT_ALL),
sync: matches.get_flag(OPT_SYNC),
block_size: read_block_size(matches).map_err(|e| match e {
block_size_config: read_block_size(matches).map_err(|e| match e {
ParseSizeError::InvalidSuffix(s) => OptionsError::InvalidSuffix(s),
ParseSizeError::SizeTooBig(_) => OptionsError::BlockSizeTooLarge(
matches.get_one::<String>(OPT_BLOCKSIZE).unwrap().to_owned(),
),
ParseSizeError::ParseFailure(s) => OptionsError::InvalidBlockSize(s),
ParseSizeError::PhysicalMem(s) => OptionsError::InvalidBlockSize(s),
ParseSizeError::BuilderConfig(e) => OptionsError::InvalidBlockSize(e.to_string()),
})?,
header_mode: {
if matches.get_flag(OPT_HUMAN_READABLE_BINARY)
Expand Down
47 changes: 34 additions & 13 deletions src/uu/df/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
//! collection of data rows ([`Row`]), one per filesystem.
use unicode_width::UnicodeWidthStr;

use crate::blocks::{SuffixType, to_magnitude_and_suffix};
use crate::Options;
use crate::blocks::{BlockSize, SuffixType, to_magnitude_and_suffix};
use crate::columns::{Alignment, Column};
use crate::filesystem::Filesystem;
use crate::{BlockSize, Options};
use uucore::format::human::format_with_thousands_separator;
use uucore::fsext::{FsUsage, MountInfo};
use uucore::translate;

Expand Down Expand Up @@ -308,12 +309,14 @@ impl<'a> RowFormatter<'a> {
let size = bytes_column.scaled;
let s = if let Some(h) = self.options.human_readable {
let size = if self.is_total_row {
let BlockSize::Bytes(d) = self.options.block_size;
let BlockSize::Bytes(d) = self.options.block_size_config.block_size;
d * size
} else {
bytes_column.bytes
};
to_magnitude_and_suffix(size.into(), SuffixType::HumanReadable(h), true)
} else if self.options.block_size_config.use_thousands_separator {
format_with_thousands_separator(size)
} else {
size.to_string()
};
Expand Down Expand Up @@ -421,13 +424,13 @@ impl Header {
HeaderMode::PosixPortability => {
format!(
"{}{}",
options.block_size.as_u64(),
options.block_size_config.block_size.as_u64(),
translate!("df-blocks-suffix")
)
}
_ => format!(
"{}{}",
options.block_size.to_header(),
options.block_size_config.block_size.to_header(),
translate!("df-blocks-suffix")
),
},
Expand Down Expand Up @@ -490,7 +493,7 @@ impl Table {
// showing all filesystems, then print the data as a row in
// the output table.
if options.show_all_fs || filesystem.usage.blocks > 0 {
let row = Row::from_filesystem(filesystem, &options.block_size);
let row = Row::from_filesystem(filesystem, &options.block_size_config.block_size);
let fmt = RowFormatter::new(&row, options, false);
let values = fmt.get_cells();
if options.show_total {
Expand Down Expand Up @@ -578,7 +581,7 @@ mod tests {
use crate::blocks::HumanReadable;
use crate::columns::Column;
use crate::table::{BytesCell, Cell, Header, HeaderMode, Row, RowFormatter, Table};
use crate::{BlockSize, Options};
use crate::{BlockSize, BlockSizeConfig, Options};

fn init() {
unsafe {
Expand Down Expand Up @@ -692,7 +695,10 @@ mod tests {
fn test_header_with_block_size_1024() {
init();
let options = Options {
block_size: BlockSize::Bytes(3 * 1024),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(3 * 1024),
use_thousands_separator: false,
},
..Default::default()
};
assert_eq!(
Expand Down Expand Up @@ -772,7 +778,10 @@ mod tests {
fn test_row_formatter() {
init();
let options = Options {
block_size: BlockSize::Bytes(1),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(1),
use_thousands_separator: false,
},
..Default::default()
};
let row = Row {
Expand All @@ -798,7 +807,10 @@ mod tests {
init();
let options = Options {
columns: COLUMNS_WITH_FS_TYPE.to_vec(),
block_size: BlockSize::Bytes(1),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(1),
use_thousands_separator: false,
},
..Default::default()
};
let row = Row {
Expand All @@ -825,7 +837,10 @@ mod tests {
init();
let options = Options {
columns: COLUMNS_WITH_INODES.to_vec(),
block_size: BlockSize::Bytes(1),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(1),
use_thousands_separator: false,
},
..Default::default()
};
let row = Row {
Expand All @@ -851,7 +866,10 @@ mod tests {
init();
let options = Options {
columns: vec![Column::Size, Column::Itotal],
block_size: BlockSize::Bytes(100),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(100),
use_thousands_separator: false,
},
..Default::default()
};
let row = Row {
Expand Down Expand Up @@ -953,7 +971,10 @@ mod tests {
init();
fn get_formatted_values(bytes: u64, bytes_used: u64, bytes_avail: u64) -> Vec<Cell> {
let options = Options {
block_size: BlockSize::Bytes(1000),
block_size_config: BlockSizeConfig {
block_size: BlockSize::Bytes(1000),
use_thousands_separator: false,
},
columns: vec![Column::Size, Column::Used, Column::Avail],
..Default::default()
};
Expand Down
1 change: 1 addition & 0 deletions src/uu/du/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ du-error-printing-thread-panicked = Printing thread panicked.
du-error-invalid-suffix = invalid suffix in --{ $option } argument { $value }
du-error-invalid-argument = invalid --{ $option } argument { $value }
du-error-argument-too-large = --{ $option } argument { $value } too large
du-error-builder-config = invalid configuration for { $option }: { $error }
du-error-hyphen-file-name-not-allowed = when reading file names from standard input, no file name of '-' allowed

# Verbose/status messages
Expand Down
1 change: 1 addition & 0 deletions src/uu/du/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ du-error-printing-thread-panicked = Le thread d'affichage a paniqué.
du-error-invalid-suffix = suffixe invalide dans l'argument --{ $option } { $value }
du-error-invalid-argument = argument --{ $option } invalide { $value }
du-error-argument-too-large = argument --{ $option } { $value } trop grand
du-error-builder-config = configuration invalide pour { $option }: { $error }
du-error-hyphen-file-name-not-allowed = le nom de fichier '-' n'est pas autorisé lors de la lecture de l'entrée standard

# Messages verbeux/de statut
Expand Down
3 changes: 3 additions & 0 deletions src/uu/du/src/du.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,9 @@ fn format_error_message(error: &ParseSizeError, s: &str, option: &str) -> String
ParseSizeError::SizeTooBig(_) => {
translate!("du-error-argument-too-large", "option" => option, "value" => s.quote())
}
ParseSizeError::BuilderConfig(e) => {
translate!("du-error-builder-config", "option" => option, "error" => e)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/uu/od/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ od-error-overflow = Numerical result out of range
od-error-invalid-suffix = invalid suffix in {$option} argument {$value}
od-error-invalid-argument = invalid {$option} argument {$value}
od-error-argument-too-large = {$option} argument {$value} too large
od-error-builder-config = invalid configuration for {$option}: {$error}
od-error-skip-past-end = tried to skip past end of input

# Help messages
Expand Down
1 change: 1 addition & 0 deletions src/uu/od/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ od-error-parse-failed = échec de l'analyse
od-error-invalid-suffix = suffixe invalide dans l'argument {$option} {$value}
od-error-invalid-argument = argument {$option} invalide {$value}
od-error-argument-too-large = argument {$option} {$value} trop grand
od-error-builder-config = configuration invalide pour {$option}: {$error}
od-error-skip-past-end = tentative d'ignorer au-delà de la fin de l'entrée

# Messages d'aide
Expand Down
3 changes: 3 additions & 0 deletions src/uu/od/src/od.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,5 +821,8 @@ fn format_error_message(error: &ParseSizeError, s: &str, option: &str) -> String
ParseSizeError::SizeTooBig(_) => {
translate!("od-error-argument-too-large", "option" => option, "value" => s.quote())
}
ParseSizeError::BuilderConfig(e) => {
translate!("od-error-builder-config", "option" => option, "error" => e)
}
}
}
1 change: 1 addition & 0 deletions src/uu/sort/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ sort-failed-fetch-rlimit = Failed to fetch rlimit
sort-invalid-suffix-in-option-arg = invalid suffix in --{$option} argument {$arg}
sort-invalid-option-arg = invalid --{$option} argument {$arg}
sort-option-arg-too-large = --{$option} argument {$arg} too large
sort-error-builder-config = invalid configuration for {$option}: {$error}
sort-error-disorder = {$file}:{$line_number}: disorder: {$line}
sort-error-buffer-size-too-big = Buffer size {$size} does not fit in address space
sort-error-no-match-for-key = ^ no match for key
Expand Down
1 change: 1 addition & 0 deletions src/uu/sort/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ sort-failed-fetch-rlimit = Échec de récupération de rlimit
sort-invalid-suffix-in-option-arg = suffixe invalide dans l'argument --{$option} {$arg}
sort-invalid-option-arg = argument --{$option} invalide {$arg}
sort-option-arg-too-large = argument --{$option} {$arg} trop grand
sort-error-builder-config = configuration invalide pour {$option}: {$error}
sort-error-disorder = {$file}:{$line_number}: désordre : {$line}
sort-error-buffer-size-too-big = La taille du tampon {$size} ne rentre pas dans l'espace d'adressage
sort-error-no-match-for-key = ^ aucune correspondance pour la clé
Expand Down
9 changes: 6 additions & 3 deletions src/uu/sort/src/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,9 @@ impl GlobalSettings {
let size = Parser::default()
.with_allow_list(&[
"b", "k", "K", "m", "M", "g", "G", "t", "T", "P", "E", "Z", "Y", "R", "Q", "%",
])
.with_default_unit("K")
.with_b_byte_count(true)
])?
.with_default_unit("K")?
.with_b_byte_count(true)?
.parse(input.trim())?;

usize::try_from(size).map_err(|_| {
Expand Down Expand Up @@ -3081,6 +3081,9 @@ fn format_error_message(error: &ParseSizeError, s: &str, option: &str) -> String
ParseSizeError::SizeTooBig(_) => {
translate!("sort-option-arg-too-large", "option" => option, "arg" => s.quote())
}
ParseSizeError::BuilderConfig(e) => {
translate!("sort-error-builder-config", "option" => option, "error" => e)
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/uucore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ xattr = { workspace = true, optional = true }
[dev-dependencies]
tempfile = { workspace = true }

[target.'cfg(target_os = "linux")'.dependencies]
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
procfs = { workspace = true, optional = true }

[target.'cfg(target_os = "windows")'.dependencies]
Expand Down Expand Up @@ -167,7 +167,7 @@ mode = ["libc"]
perms = ["entries", "libc", "walkdir"]
buf-copy = []
parser-num = ["extendedbigdecimal", "num-traits"]
parser-size = ["parser-num", "procfs"]
parser-size = ["parser-num", "procfs", "libc", "windows-sys"]
parser-glob = ["glob"]
parser = ["parser-num", "parser-size", "parser-glob"]
pipes = []
Expand Down
Loading
Loading