Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/more android #18

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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: 1 addition & 1 deletion .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ concurrency:

env:
TERMUX: v0.118.0
KEY_POSTFIX: nextest+rustc-hash+adb+sshd+upgrade+XGB+inc15
KEY_POSTFIX: nextest+rustc-hash+adb+sshd+upgrade+XGB+inc16
COMMON_EMULATOR_OPTIONS: -no-window -noaudio -no-boot-anim -camera-back none -gpu swiftshader_indirect
EMULATOR_DISK_SIZE: 12GB
EMULATOR_HEAP_SIZE: 2048M
Expand Down
196 changes: 167 additions & 29 deletions src/uu/df/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
use std::fmt;
use std::ops::AddAssign;

use u128 as InodesIntT;
type MaybeInodesT = Option<InodesIntT>;

/// A row in the filesystem usage data table.
///
/// A row comprises several pieces of information, including the
/// filesystem device, the mountpoint, the number of bytes used, etc.
#[derive(Clone)]
pub(crate) struct Row {
/// The filename given on the command-line, if given.
file: Option<String>,
Expand Down Expand Up @@ -58,13 +62,13 @@
bytes_capacity: Option<f64>,

/// Total number of inodes in the filesystem.
inodes: u64,
inodes: MaybeInodesT,

/// Number of used inodes.
inodes_used: u64,
inodes_used: MaybeInodesT,

/// Number of free inodes.
inodes_free: u64,
inodes_free: MaybeInodesT,

/// Percentage of inodes that are used, given as a float between 0 and 1.
///
Expand All @@ -85,14 +89,36 @@
bytes_usage: None,
#[cfg(target_os = "macos")]
bytes_capacity: None,
inodes: 0,
inodes_used: 0,
inodes_free: 0,
inodes: Some(0),
inodes_used: Some(0),
inodes_free: Some(0),
inodes_usage: None,
}
}
}

fn checked_accumulation_op(accumulator: &MaybeInodesT, summand: &MaybeInodesT) -> MaybeInodesT {
let a = (*accumulator)?;
if let Some(s) = *summand {
if s > InodesIntT::MAX / 2 {
eprintln!("invalid inodes number ({s}) - filesystem will be ignored");
*accumulator
} else {
a.checked_add(s)
}
} else {
*accumulator
}
}

fn calc_inode_usage(inodes: MaybeInodesT, inodes_used: MaybeInodesT) -> Option<f64> {
if inodes? == 0 {
None
} else {
Some(inodes_used? as f64 / inodes? as f64)
}
}

impl AddAssign for Row {
/// Sum the numeric values of two rows.
///
Expand All @@ -102,8 +128,8 @@
let bytes = self.bytes + rhs.bytes;
let bytes_used = self.bytes_used + rhs.bytes_used;
let bytes_avail = self.bytes_avail + rhs.bytes_avail;
let inodes = self.inodes + rhs.inodes;
let inodes_used = self.inodes_used + rhs.inodes_used;
let inodes = checked_accumulation_op(&self.inodes, &rhs.inodes);
let inodes_used = checked_accumulation_op(&self.inodes_used, &rhs.inodes_used);
*self = Self {
file: None,
fs_device: "total".into(),
Expand All @@ -125,12 +151,8 @@
bytes_capacity: None,
inodes,
inodes_used,
inodes_free: self.inodes_free + rhs.inodes_free,
inodes_usage: if inodes == 0 {
None
} else {
Some(inodes_used as f64 / inodes as f64)
},
inodes_free: checked_accumulation_op(&self.inodes_free, &rhs.inodes_free),
inodes_usage: calc_inode_usage(inodes, inodes_used),
}
}
}
Expand Down Expand Up @@ -178,9 +200,9 @@
} else {
Some(bavail as f64 / ((bused + bavail) as f64))
},
inodes: files,
inodes_used: fused,
inodes_free: ffree,
inodes: Some(files as InodesIntT),
inodes_used: Some(fused as InodesIntT),
inodes_free: Some(ffree as InodesIntT),
inodes_usage: if files == 0 {
None
} else {
Expand Down Expand Up @@ -235,11 +257,15 @@
/// Get a string giving the scaled version of the input number.
///
/// The scaling factor is defined in the `options` field.
fn scaled_inodes(&self, size: u64) -> String {
if let Some(h) = self.options.human_readable {
to_magnitude_and_suffix(size.into(), SuffixType::HumanReadable(h))
fn scaled_inodes(&self, maybe_size: MaybeInodesT) -> String {
if let Some(size) = maybe_size {
if let Some(h) = self.options.human_readable {
to_magnitude_and_suffix(size, SuffixType::HumanReadable(h))
} else {
size.to_string()
}
} else {
size.to_string()
"int_overflow".into()
}
}

Expand Down Expand Up @@ -505,9 +531,9 @@
#[cfg(target_os = "macos")]
bytes_capacity: Some(0.5),

inodes: 10,
inodes_used: 2,
inodes_free: 8,
inodes: Some(10),
inodes_used: Some(2),
inodes_free: Some(8),
inodes_usage: Some(0.2),
}
}
Expand Down Expand Up @@ -698,9 +724,9 @@
fs_device: "my_device".to_string(),
fs_mount: "my_mount".to_string(),

inodes: 10,
inodes_used: 2,
inodes_free: 8,
inodes: Some(10),
inodes_used: Some(2),
inodes_free: Some(8),
inodes_usage: Some(0.2),

..Default::default()
Expand All @@ -721,7 +747,7 @@
};
let row = Row {
bytes: 100,
inodes: 10,
inodes: Some(10),
..Default::default()
};
let fmt = RowFormatter::new(&row, &options, false);
Expand Down Expand Up @@ -846,6 +872,118 @@

let row = Row::from(d);

assert_eq!(row.inodes_used, 0);
assert_eq!(row.inodes_used, Some(0));
}

#[test]
fn test_row_accumulation_u64_overflow() {
let total = u64::MAX as super::InodesIntT;
let used1 = 3000 as super::InodesIntT;

Check failure on line 881 in src/uu/df/src/table.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (ubuntu-22.04, unix)

ERROR: `cargo clippy`: casting integer literal to `u128` is unnecessary (file:'src/uu/df/src/table.rs', line:881)
let used2 = 50000 as super::InodesIntT;

Check failure on line 882 in src/uu/df/src/table.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (ubuntu-22.04, unix)

ERROR: `cargo clippy`: casting integer literal to `u128` is unnecessary (file:'src/uu/df/src/table.rs', line:882)

let mut row1 = Row {
inodes: Some(total),
inodes_used: Some(used1),
inodes_free: Some(total - used1),
..Default::default()
};

let row2 = Row {
inodes: Some(total),
inodes_used: Some(used2),
inodes_free: Some(total - used2),
..Default::default()
};

row1 += row2;

assert_eq!(row1.inodes, Some(total * 2));
assert_eq!(row1.inodes_used, Some(used1 + used2));
assert_eq!(row1.inodes_free, Some(total * 2 - used1 - used2));
}

#[test]
fn test_row_accumulation_close_to_u128_overflow() {
let total = u128::MAX as super::InodesIntT / 2 - 1;

Check failure on line 907 in src/uu/df/src/table.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (ubuntu-22.04, unix)

ERROR: `cargo clippy`: casting to the same type is unnecessary (`u128` -> `u128`) (file:'src/uu/df/src/table.rs', line:907)
let used1 = total - 50000;
let used2 = total - 100000;

let mut row1 = Row {
inodes: Some(total),
inodes_used: Some(used1),
inodes_free: Some(total - used1),
..Default::default()
};

let row2 = Row {
inodes: Some(total),
inodes_used: Some(used2),
inodes_free: Some(total - used2),
..Default::default()
};

row1 += row2;

assert_eq!(row1.inodes, Some(total * 2));
assert_eq!(row1.inodes_used, Some(used1 + used2));
assert_eq!(row1.inodes_free, Some(total * 2 - used1 - used2));
}

#[test]
fn test_row_accumulation_and_usage_close_over_u128_overflow() {
let total = u128::MAX as super::InodesIntT / 2 - 1;

Check failure on line 934 in src/uu/df/src/table.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (ubuntu-22.04, unix)

ERROR: `cargo clippy`: casting to the same type is unnecessary (`u128` -> `u128`) (file:'src/uu/df/src/table.rs', line:934)
let used1 = total / 2;
let free1 = total - used1;
let used2 = total / 2 - 10;
let free2 = total - used2;

let mut row1 = Row {
inodes: Some(total),
inodes_used: Some(used1),
inodes_free: Some(free1),
..Default::default()
};

let row2 = Row {
inodes: Some(total),
inodes_used: Some(used2),
inodes_free: Some(free2),
..Default::default()
};

row1 += row2.clone();

assert_eq!(row1.inodes, Some(total * 2));
assert_eq!(row1.inodes_used, Some(used1 + used2));
assert_eq!(row1.inodes_free, Some(free1 + free2));
assert_eq!(row1.inodes_usage, Some(0.5));

row1 += row2.clone();

assert_eq!(row1.inodes, None); // total * 3
assert_eq!(row1.inodes_used, Some(used1 + used2 * 2));
assert_eq!(row1.inodes_free, Some(free1 + free2 * 2));
assert_eq!(row1.inodes_usage, None);

row1 += row2.clone();

assert_eq!(row1.inodes, None); // total * 4
assert_eq!(row1.inodes_used, Some(used1 + used2 * 3)); // used * 4
assert_eq!(row1.inodes_free, None); // free * 4
assert_eq!(row1.inodes_usage, None);

row1 += row2.clone();

assert_eq!(row1.inodes, None); // total * 5
assert_eq!(row1.inodes_used, None); // used * 5
assert_eq!(row1.inodes_free, None); // free * 5
assert_eq!(row1.inodes_usage, None);

row1 += row2.clone();

assert_eq!(row1.inodes, None); // total * 6
assert_eq!(row1.inodes_used, None); // used * 6
assert_eq!(row1.inodes_free, None); // free * 6
assert_eq!(row1.inodes_usage, None);
}
}
13 changes: 9 additions & 4 deletions tests/by-util/test_df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,18 @@ fn test_type_option() {
#[test]
#[cfg(not(any(target_os = "freebsd", target_os = "windows")))] // FIXME: fix test for FreeBSD & Win
fn test_type_option_with_file() {
let fs_type = new_ucmd!()
let fs_type_cwd = new_ucmd!()
.args(&["--output=fstype", "."])
.succeeds()
.stdout_move_str();
let fs_type = fs_type.lines().nth(1).unwrap().trim();
let fs_type_cwd = fs_type_cwd.lines().nth(1).unwrap().trim();
let fs_type_root_dir = new_ucmd!()
.args(&["--output=fstype", "/"])
.succeeds()
.stdout_move_str();
let fs_type_root_dir = fs_type_root_dir.lines().nth(1).unwrap().trim();

new_ucmd!().args(&["-t", fs_type, "."]).succeeds();
new_ucmd!().args(&["-t", fs_type_cwd, "."]).succeeds();
new_ucmd!()
.args(&["-t", "nonexisting", "."])
.fails()
Expand All @@ -283,7 +288,7 @@ fn test_type_option_with_file() {
let fs_types: Vec<_> = fs_types
.lines()
.skip(1)
.filter(|t| t.trim() != fs_type && t.trim() != "")
.filter(|t| t.trim() != fs_type_cwd && t.trim() != fs_type_root_dir && t.trim() != "")
.collect();

if !fs_types.is_empty() {
Expand Down
Loading
Loading