@@ -51,28 +51,30 @@ struct Args {
5151}
5252
5353/// Display modes
54- pub enum HeaderMode {
54+ pub enum OutputMode {
5555 /// When both the -k and -P options are specified
5656 Posix ,
5757 /// When the -P option is specified without the -k option
5858 PosixLegacy ,
59- Inodes ,
59+ /// The format of the default output from df is unspecified,
60+ /// but all space figures are reported in 512-byte units
61+ Unspecified ,
6062}
6163
62- impl HeaderMode {
64+ impl OutputMode {
6365 pub fn new ( kilo : bool , portable : bool ) -> Self {
6466 match ( kilo, portable) {
6567 ( true , true ) => Self :: Posix ,
6668 ( false , true ) => Self :: PosixLegacy ,
67- _ => Self :: Inodes ,
69+ _ => Self :: Unspecified ,
6870 }
6971 }
7072
7173 pub fn get_block_size ( & self ) -> u64 {
7274 match self {
73- HeaderMode :: Posix => 1024 ,
74- HeaderMode :: PosixLegacy => 512 ,
75- HeaderMode :: Inodes => 0 ,
75+ OutputMode :: Posix => 1024 ,
76+ OutputMode :: PosixLegacy => 512 ,
77+ OutputMode :: Unspecified => 512 ,
7678 }
7779 }
7880}
@@ -95,10 +97,22 @@ impl Field {
9597 pub fn print_header_align_right ( & self ) {
9698 print ! ( "{: >width$} " , self . caption, width = self . width) ;
9799 }
100+
101+ pub fn print_string ( & self , value : & String ) {
102+ print ! ( "{: <width$} " , value, width = self . width) ;
103+ }
104+
105+ pub fn print_u64 ( & self , value : u64 ) {
106+ print ! ( "{: >width$} " , value, width = self . width) ;
107+ }
108+
109+ pub fn print_percentage ( & self , value : u32 ) {
110+ print ! ( "{: >width$}% " , value, width = self . width - 1 ) ;
111+ }
98112}
99113
100- pub struct Header {
101- pub mode : HeaderMode ,
114+ pub struct Fields {
115+ pub mode : OutputMode ,
102116 /// file system
103117 pub source : Field ,
104118 /// FS size
@@ -109,56 +123,69 @@ pub struct Header {
109123 pub avail : Field ,
110124 /// percent used
111125 pub pcent : Field ,
112- /// inode total
113- pub itotal : Field ,
114- /// inodes used
115- pub iused : Field ,
116- /// inodes available
117- pub iavail : Field ,
118- /// inodes used in percent
119- pub ipcent : Field ,
120126 /// mount point
121127 pub target : Field ,
122128 // /// specified file name
123129 // file: Field,
124130}
125131
126- impl Header {
127- pub fn new ( mode : HeaderMode ) -> Self {
132+ impl Fields {
133+ pub fn new ( mode : OutputMode ) -> Self {
128134 let size_caption = format ! ( "{}-{}" , mode. get_block_size( ) , gettext( "blocks" ) ) ;
129135 Self {
130136 mode,
131137 source : Field :: new ( gettext ( "Filesystem" ) , 14 ) ,
132138 size : Field :: new ( size_caption, 0 ) ,
133- used : Field :: new ( gettext ( "Used" ) , 5 ) ,
134- avail : Field :: new ( gettext ( "Available" ) , 5 ) ,
139+ used : Field :: new ( gettext ( "Used" ) , 9 ) ,
140+ avail : Field :: new ( gettext ( "Available" ) , 9 ) ,
135141 pcent : Field :: new ( gettext ( "Capacity" ) , 5 ) ,
136- itotal : Field :: new ( gettext ( "Inodes" ) , 5 ) ,
137- iused : Field :: new ( gettext ( "IUsed" ) , 5 ) ,
138- iavail : Field :: new ( gettext ( "IFree" ) , 5 ) ,
139- ipcent : Field :: new ( gettext ( "IUse%" ) , 5 ) ,
140142 target : Field :: new ( gettext ( "Mounted on" ) , 0 ) ,
141143 }
142144 }
143145
144146 pub fn print_header ( & self ) {
145147 self . source . print_header ( ) ;
146- match self . mode {
147- HeaderMode :: Posix | HeaderMode :: PosixLegacy => {
148- self . size . print_header_align_right ( ) ;
149- self . used . print_header_align_right ( ) ;
150- self . avail . print_header_align_right ( ) ;
151- self . pcent . print_header_align_right ( ) ;
152- }
153- HeaderMode :: Inodes => {
154- self . itotal . print_header_align_right ( ) ;
155- self . iused . print_header_align_right ( ) ;
156- self . iavail . print_header_align_right ( ) ;
157- self . ipcent . print_header_align_right ( ) ;
158- }
159- }
148+ self . size . print_header_align_right ( ) ;
149+ self . used . print_header_align_right ( ) ;
150+ self . avail . print_header_align_right ( ) ;
151+ self . pcent . print_header_align_right ( ) ;
160152 self . target . print_header ( ) ;
161- print ! ( "\n " ) ;
153+ println ! ( ) ;
154+ }
155+
156+ fn print_row ( & self , mount : & Mount ) {
157+ if !mount. masked {
158+ return ;
159+ }
160+
161+ let sf = & mount. cached_statfs ;
162+
163+ let block_size = self . mode . get_block_size ( ) ;
164+ let blksz = sf. f_bsize as u64 ;
165+
166+ let total = ( sf. f_blocks * blksz) / block_size;
167+ let avail = ( sf. f_bavail * blksz) / block_size;
168+ let free = ( sf. f_bfree * blksz) / block_size;
169+ let used = total - free;
170+
171+ // The percentage value shall be expressed as a positive integer,
172+ // with any fractional result causing it to be rounded to the next highest integer.
173+ let percentage_used = f64:: from ( used as u32 ) / f64:: from ( ( used + free) as u32 ) ;
174+ let percentage_used = percentage_used * 100.0 ;
175+ let percentage_used = percentage_used. ceil ( ) as u32 ;
176+
177+ // The remaining output with -P shall consist of one line of information
178+ // for each specified file system. These lines shall be formatted as follows:
179+ // "%s %d %d %d %d%% %s\n", <file system name>, <total space>,
180+ // <space used>, <space free>, <percentage used>,
181+ // <file system root>
182+ self . source . print_string ( & mount. devname ) ;
183+ self . size . print_u64 ( total) ;
184+ self . used . print_u64 ( used) ;
185+ self . avail . print_u64 ( avail) ;
186+ self . pcent . print_percentage ( percentage_used) ;
187+ self . target . print_string ( & mount. dir ) ;
188+ println ! ( ) ;
162189 }
163190}
164191
@@ -303,52 +330,6 @@ fn mask_fs_by_file(info: &mut MountList, filename: &str) -> io::Result<()> {
303330 Ok ( ( ) )
304331}
305332
306- fn show_mount ( args : & Args , block_size : u64 , mount : & Mount ) {
307- let sf = & mount. cached_statfs ;
308-
309- let blksz = sf. f_bsize as u64 ;
310-
311- let total = ( sf. f_blocks * blksz) / block_size;
312- let avail = ( sf. f_bavail * blksz) / block_size;
313- let free = ( sf. f_bfree * blksz) / block_size;
314- let used = total - free;
315-
316- if total == 0 {
317- return ;
318- }
319-
320- let pct = ( ( total - avail) * 100 ) / total;
321-
322- if args. portable {
323- println ! (
324- "{:>20} {:>9} {:>9} {:>9} {:>7} {}" ,
325- mount. devname, total, used, avail, pct, mount. dir
326- ) ;
327- } else {
328- println ! (
329- "{:>20} {:>9} {:>9} {:>9} {:>3} {}" ,
330- mount. devname, total, used, avail, pct, mount. dir
331- ) ;
332- }
333- }
334-
335- fn show_info ( args : & Args , info : & MountList ) {
336- let mode = HeaderMode :: new ( args. kilo , args. portable ) ;
337- let header = Header :: new ( mode) ;
338- header. print_header ( ) ;
339-
340- let block_size: u64 = match args. kilo {
341- true => 1024 ,
342- false => 512 ,
343- } ;
344-
345- for mount in & info. mounts {
346- if mount. masked {
347- show_mount ( args, block_size, mount) ;
348- }
349- }
350- }
351-
352333fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
353334 // parse command line arguments
354335 let args = Args :: parse ( ) ;
@@ -368,7 +349,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
368349 }
369350
370351 info. ensure_masked ( ) ;
371- show_info ( & args, & info) ;
352+
353+ let mode = OutputMode :: new ( args. kilo , args. portable ) ;
354+ let fields = Fields :: new ( mode) ;
355+ fields. print_header ( ) ;
356+
357+ for mount in & info. mounts {
358+ fields. print_row ( mount) ;
359+ }
372360
373361 Ok ( ( ) )
374362}
0 commit comments