@@ -58,13 +58,13 @@ pub(crate) struct Row {
58
58
bytes_capacity : Option < f64 > ,
59
59
60
60
/// Total number of inodes in the filesystem.
61
- inodes : u64 ,
61
+ inodes : u128 ,
62
62
63
63
/// Number of used inodes.
64
- inodes_used : u64 ,
64
+ inodes_used : u128 ,
65
65
66
66
/// Number of free inodes.
67
- inodes_free : u64 ,
67
+ inodes_free : u128 ,
68
68
69
69
/// Percentage of inodes that are used, given as a float between 0 and 1.
70
70
///
@@ -178,9 +178,9 @@ impl From<Filesystem> for Row {
178
178
} else {
179
179
Some ( bavail as f64 / ( ( bused + bavail) as f64 ) )
180
180
} ,
181
- inodes : files,
182
- inodes_used : fused,
183
- inodes_free : ffree,
181
+ inodes : files as u128 ,
182
+ inodes_used : fused as u128 ,
183
+ inodes_free : ffree as u128 ,
184
184
inodes_usage : if files == 0 {
185
185
None
186
186
} else {
@@ -235,9 +235,9 @@ impl<'a> RowFormatter<'a> {
235
235
/// Get a string giving the scaled version of the input number.
236
236
///
237
237
/// The scaling factor is defined in the `options` field.
238
- fn scaled_inodes ( & self , size : u64 ) -> String {
238
+ fn scaled_inodes ( & self , size : u128 ) -> String {
239
239
if let Some ( h) = self . options . human_readable {
240
- to_magnitude_and_suffix ( size. into ( ) , SuffixType :: HumanReadable ( h) )
240
+ to_magnitude_and_suffix ( size, SuffixType :: HumanReadable ( h) )
241
241
} else {
242
242
size. to_string ( )
243
243
}
@@ -395,12 +395,6 @@ impl Table {
395
395
let values = fmt. get_values ( ) ;
396
396
total += row;
397
397
398
- for ( i, value) in values. iter ( ) . enumerate ( ) {
399
- if UnicodeWidthStr :: width ( value. as_str ( ) ) > widths[ i] {
400
- widths[ i] = UnicodeWidthStr :: width ( value. as_str ( ) ) ;
401
- }
402
- }
403
-
404
398
rows. push ( values) ;
405
399
}
406
400
}
@@ -410,6 +404,16 @@ impl Table {
410
404
rows. push ( total_row. get_values ( ) ) ;
411
405
}
412
406
407
+ // extend the column widths (in chars) for long values in rows
408
+ // do it here, after total row was added to the list of rows
409
+ for row in & rows {
410
+ for ( i, value) in row. iter ( ) . enumerate ( ) {
411
+ if UnicodeWidthStr :: width ( value. as_str ( ) ) > widths[ i] {
412
+ widths[ i] = UnicodeWidthStr :: width ( value. as_str ( ) ) ;
413
+ }
414
+ }
415
+ }
416
+
413
417
Self {
414
418
rows,
415
419
widths,
@@ -466,9 +470,11 @@ impl fmt::Display for Table {
466
470
#[ cfg( test) ]
467
471
mod tests {
468
472
473
+ use std:: vec;
474
+
469
475
use crate :: blocks:: HumanReadable ;
470
476
use crate :: columns:: Column ;
471
- use crate :: table:: { Header , HeaderMode , Row , RowFormatter } ;
477
+ use crate :: table:: { Header , HeaderMode , Row , RowFormatter , Table } ;
472
478
use crate :: { BlockSize , Options } ;
473
479
474
480
const COLUMNS_WITH_FS_TYPE : [ Column ; 7 ] = [
@@ -848,4 +854,89 @@ mod tests {
848
854
849
855
assert_eq ! ( row. inodes_used, 0 ) ;
850
856
}
857
+
858
+ #[ test]
859
+ fn test_table_column_width_computation_include_total_row ( ) {
860
+ let d1 = crate :: Filesystem {
861
+ file : None ,
862
+ mount_info : crate :: MountInfo {
863
+ dev_id : "28" . to_string ( ) ,
864
+ dev_name : "none" . to_string ( ) ,
865
+ fs_type : "9p" . to_string ( ) ,
866
+ mount_dir : "/usr/lib/wsl/drivers" . to_string ( ) ,
867
+ mount_option : "ro,nosuid,nodev,noatime" . to_string ( ) ,
868
+ mount_root : "/" . to_string ( ) ,
869
+ remote : false ,
870
+ dummy : false ,
871
+ } ,
872
+ usage : crate :: table:: FsUsage {
873
+ blocksize : 4096 ,
874
+ blocks : 244029695 ,
875
+ bfree : 125085030 ,
876
+ bavail : 125085030 ,
877
+ bavail_top_bit_set : false ,
878
+ files : 99999999999 ,
879
+ ffree : 999999 ,
880
+ } ,
881
+ } ;
882
+
883
+ let filesystems = vec ! [ d1. clone( ) , d1] ;
884
+
885
+ let mut options = Options {
886
+ show_total : true ,
887
+ columns : vec ! [
888
+ Column :: Source ,
889
+ Column :: Itotal ,
890
+ Column :: Iused ,
891
+ Column :: Iavail ,
892
+ ] ,
893
+ ..Default :: default ( )
894
+ } ;
895
+
896
+ let table_w_total = Table :: new ( & options, filesystems. clone ( ) ) ;
897
+ assert_eq ! (
898
+ table_w_total. to_string( ) ,
899
+ "Filesystem Inodes IUsed IFree\n \
900
+ none 99999999999 99999000000 999999\n \
901
+ none 99999999999 99999000000 999999\n \
902
+ total 199999999998 199998000000 1999998"
903
+ ) ;
904
+
905
+ options. show_total = false ;
906
+
907
+ let table_w_o_total = Table :: new ( & options, filesystems) ;
908
+ assert_eq ! (
909
+ table_w_o_total. to_string( ) ,
910
+ "Filesystem Inodes IUsed IFree\n \
911
+ none 99999999999 99999000000 999999\n \
912
+ none 99999999999 99999000000 999999"
913
+ ) ;
914
+ }
915
+
916
+ #[ test]
917
+ fn test_row_accumulation_u64_overflow ( ) {
918
+ let total = u64:: MAX as u128 ;
919
+ let used1 = 3000u128 ;
920
+ let used2 = 50000u128 ;
921
+
922
+ let mut row1 = Row {
923
+ inodes : total,
924
+ inodes_used : used1,
925
+ inodes_free : total - used1,
926
+ ..Default :: default ( )
927
+ } ;
928
+
929
+ let row2 = Row {
930
+ inodes : total,
931
+ inodes_used : used2,
932
+ inodes_free : total - used2,
933
+ ..Default :: default ( )
934
+ } ;
935
+
936
+ row1 += row2;
937
+
938
+ assert_eq ! ( row1. inodes, total * 2 ) ;
939
+ assert_eq ! ( row1. inodes_used, used1 + used2) ;
940
+ assert_eq ! ( row1. inodes_free, total * 2 - used1 - used2) ;
941
+ }
851
942
}
0 commit comments