mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
truncate: prevent underflow when reducing size
Prevent usize underflow when reducing the size of a file by more than its current size. For example, if `f` is a file with 3 bytes, then truncate -s-5 f will now set the size of the file to 0 instead of causing a panic.
This commit is contained in:
parent
f1d72018d7
commit
0454d3b243
2 changed files with 40 additions and 1 deletions
|
@ -31,18 +31,38 @@ impl TruncateMode {
|
|||
///
|
||||
/// `fsize` is the size of the reference file, in bytes.
|
||||
///
|
||||
/// If the mode is [`TruncateMode::Reduce`] and the value to
|
||||
/// reduce by is greater than `fsize`, then this function returns
|
||||
/// 0 (since it cannot return a negative number).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Extending a file of 10 bytes by 5 bytes:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let mode = TruncateMode::Extend(5);
|
||||
/// let fsize = 10;
|
||||
/// assert_eq!(mode.to_size(fsize), 15);
|
||||
/// ```
|
||||
///
|
||||
/// Reducing a file by more than its size results in 0:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let mode = TruncateMode::Reduce(5);
|
||||
/// let fsize = 3;
|
||||
/// assert_eq!(mode.to_size(fsize), 0);
|
||||
/// ```
|
||||
fn to_size(&self, fsize: usize) -> usize {
|
||||
match self {
|
||||
TruncateMode::Absolute(size) => *size,
|
||||
TruncateMode::Extend(size) => fsize + size,
|
||||
TruncateMode::Reduce(size) => fsize - size,
|
||||
TruncateMode::Reduce(size) => {
|
||||
if *size > fsize {
|
||||
0
|
||||
} else {
|
||||
fsize - size
|
||||
}
|
||||
}
|
||||
TruncateMode::AtMost(size) => fsize.min(*size),
|
||||
TruncateMode::AtLeast(size) => fsize.max(*size),
|
||||
TruncateMode::RoundDown(size) => fsize - fsize % size,
|
||||
|
@ -377,4 +397,11 @@ mod tests {
|
|||
assert_eq!(parse_mode_and_size("/10"), Ok(TruncateMode::RoundDown(10)));
|
||||
assert_eq!(parse_mode_and_size("%10"), Ok(TruncateMode::RoundUp(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_size() {
|
||||
assert_eq!(TruncateMode::Extend(5).to_size(10), 15);
|
||||
assert_eq!(TruncateMode::Reduce(5).to_size(10), 5);
|
||||
assert_eq!(TruncateMode::Reduce(5).to_size(3), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,3 +377,15 @@ fn test_division_by_zero_reference_and_size() {
|
|||
.no_stdout()
|
||||
.stderr_contains("division by zero");
|
||||
}
|
||||
|
||||
/// Test that truncate with a relative size less than 0 is not an error.
|
||||
#[test]
|
||||
fn test_underflow_relative_size() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
ucmd.args(&["-s-1", FILE1])
|
||||
.succeeds()
|
||||
.no_stdout()
|
||||
.no_stderr();
|
||||
assert!(at.file_exists(FILE1));
|
||||
assert!(at.read_bytes(FILE1).is_empty());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue