btrfs_cli/filesystem/
df.rs1use super::UnitMode;
2use crate::{
3 Format, RunContext, Runnable,
4 util::{fmt_size, open_path, print_json},
5};
6use anyhow::{Context, Result};
7use btrfs_uapi::space::space_info;
8use clap::Parser;
9use cols::Cols;
10use serde::Serialize;
11use std::{os::unix::io::AsFd, path::PathBuf};
12
13#[derive(Parser, Debug)]
15pub struct FilesystemDfCommand {
16 #[clap(flatten)]
17 pub units: UnitMode,
18
19 pub path: PathBuf,
20}
21
22#[derive(Serialize)]
23struct SpaceEntryJson {
24 #[serde(rename = "type")]
25 bg_type: String,
26 profile: String,
27 total: u64,
28 used: u64,
29}
30
31impl Runnable for FilesystemDfCommand {
32 fn supported_formats(&self) -> &[Format] {
33 &[Format::Text, Format::Json, Format::Modern]
34 }
35
36 fn run(&self, ctx: &RunContext) -> Result<()> {
37 let mode = self.units.resolve();
38 let file = open_path(&self.path)?;
39 let entries = space_info(file.as_fd()).with_context(|| {
40 format!("failed to get space info for '{}'", self.path.display())
41 })?;
42
43 match ctx.format {
44 Format::Modern => {
45 let rows: Vec<DfRow> = entries
46 .iter()
47 .map(|e| DfRow {
48 bg_type: e.flags.type_name().to_string(),
49 profile: e.flags.profile_name().to_string(),
50 total: fmt_size(e.total_bytes, &mode),
51 used: fmt_size(e.used_bytes, &mode),
52 })
53 .collect();
54 let mut out = std::io::stdout().lock();
55 let _ = DfRow::print_table(&rows, &mut out);
56 }
57 Format::Text => {
58 for entry in &entries {
59 println!(
60 "{}, {}: total={}, used={}",
61 entry.flags.type_name(),
62 entry.flags.profile_name(),
63 fmt_size(entry.total_bytes, &mode),
64 fmt_size(entry.used_bytes, &mode),
65 );
66 }
67 }
68 Format::Json => {
69 let json: Vec<SpaceEntryJson> = entries
70 .iter()
71 .map(|e| SpaceEntryJson {
72 bg_type: e.flags.type_name().to_string(),
73 profile: e.flags.profile_name().to_string(),
74 total: e.total_bytes,
75 used: e.used_bytes,
76 })
77 .collect();
78 print_json("filesystem-df", &json)?;
79 }
80 }
81
82 Ok(())
83 }
84}
85
86#[derive(Cols)]
87struct DfRow {
88 #[column(header = "TYPE")]
89 bg_type: String,
90 #[column(header = "PROFILE")]
91 profile: String,
92 #[column(header = "TOTAL", right)]
93 total: String,
94 #[column(header = "USED", right)]
95 used: String,
96}