From 24d88d777a09b2c05698ab666661988281612082 Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Mon, 12 May 2025 09:36:36 +0200 Subject: [PATCH 1/2] shred:bitwise method to set OPTIMAL_IO_BLOCK_SIZE The value of the variable remains unchanged (4096 = 2 ^ 12), but using a bitwise expression provides two benefits: - follows the same approach used for configuring BLOCK_SIZE - indicates that a power-of-two value is preferred for this kind of constant --- src/uu/shred/src/shred.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uu/shred/src/shred.rs b/src/uu/shred/src/shred.rs index 92cbb2061..9e44ce6fa 100644 --- a/src/uu/shred/src/shred.rs +++ b/src/uu/shred/src/shred.rs @@ -49,11 +49,11 @@ const NAME_CHARSET: &[u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN const PATTERN_LENGTH: usize = 3; const PATTERN_BUFFER_SIZE: usize = BLOCK_SIZE + PATTERN_LENGTH - 1; -/// Optimal block size for the filesystem. This constant is used for data size alignment, -/// similar to the behavior of GNU shred. Usually, optimal block size is a 4K block, which is why +/// Optimal block size for the filesystem. This constant is used for data size alignment, similar +/// to the behavior of GNU shred. Usually, optimal block size is a 4K block (2^12), which is why /// it's defined as a constant. However, it's possible to get the actual size at runtime using, for /// example, `std::os::unix::fs::MetadataExt::blksize()`. -const OPTIMAL_IO_BLOCK_SIZE: usize = 4096; +const OPTIMAL_IO_BLOCK_SIZE: usize = 1 << 12; /// Patterns that appear in order for the passes /// From 14a8f3f3f95011895b806954ab8ad6450c6a3b51 Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Mon, 12 May 2025 10:01:19 +0200 Subject: [PATCH 2/2] shred:add checks for block sizes This commit adds checks for block size constants. Misconfigured sizes could lead to overflows or performance issues. While such cases are expected to be rare or unlikely, it's better to be notified of them early. --- src/uu/shred/src/shred.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/uu/shred/src/shred.rs b/src/uu/shred/src/shred.rs index 9e44ce6fa..71e3fcef3 100644 --- a/src/uu/shred/src/shred.rs +++ b/src/uu/shred/src/shred.rs @@ -514,12 +514,17 @@ fn wipe_file( } fn split_on_blocks(file_size: u64, exact: bool) -> (u64, u64) { + // OPTIMAL_IO_BLOCK_SIZE must not exceed BLOCK_SIZE. Violating this may cause overflows due + // to alignment or performance issues.This kind of misconfiguration is + // highly unlikely but would indicate a serious error. + const _: () = assert!(OPTIMAL_IO_BLOCK_SIZE <= BLOCK_SIZE); + let file_size = if exact { file_size } else { - // The main idea here is to align the file size to the OPTIMAL_IO_BLOCK_SIZE, and then split it into - // BLOCK_SIZE + remaining bytes. Since the input data is already aligned to N * OPTIMAL_IO_BLOCK_SIZE, - // the output file size will also be aligned and correct. + // The main idea here is to align the file size to the OPTIMAL_IO_BLOCK_SIZE, and then + // split it into BLOCK_SIZE + remaining bytes. Since the input data is already aligned to N + // * OPTIMAL_IO_BLOCK_SIZE, the output file size will also be aligned and correct. file_size.div_ceil(OPTIMAL_IO_BLOCK_SIZE as u64) * OPTIMAL_IO_BLOCK_SIZE as u64 }; (file_size / BLOCK_SIZE as u64, file_size % BLOCK_SIZE as u64)