Skip to content

Commit c98d61e

Browse files
committed
df: Output format
1 parent 287c485 commit c98d61e

File tree

1 file changed

+75
-87
lines changed

1 file changed

+75
-87
lines changed

fs/df.rs

Lines changed: 75 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
352333
fn 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

Comments
 (0)