Skip to main content

btrfs_cli/filesystem/
label.rs

1use crate::{RunContext, Runnable, util::open_path};
2use anyhow::{Context, Result};
3use btrfs_uapi::filesystem::{label_get, label_set};
4use clap::Parser;
5use std::{
6    ffi::CString,
7    os::unix::{ffi::OsStrExt, io::AsFd},
8    path::PathBuf,
9};
10
11/// Get or set the label of a btrfs filesystem
12#[derive(Parser, Debug)]
13pub struct FilesystemLabelCommand {
14    /// The device or mount point to operate on
15    pub path: PathBuf,
16
17    /// The new label to set (if omitted, the current label is printed)
18    pub new_label: Option<std::ffi::OsString>,
19}
20
21impl Runnable for FilesystemLabelCommand {
22    fn run(&self, _ctx: &RunContext) -> Result<()> {
23        let file = open_path(&self.path)?;
24        match &self.new_label {
25            None => {
26                let label = label_get(file.as_fd()).with_context(|| {
27                    format!("failed to get label for '{}'", self.path.display())
28                })?;
29                println!("{}", label.to_bytes().escape_ascii());
30            }
31            Some(new_label) => {
32                let cstring = CString::new(new_label.as_bytes())
33                    .context("label must not contain null bytes")?;
34                label_set(file.as_fd(), &cstring).with_context(|| {
35                    format!("failed to set label for '{}'", self.path.display())
36                })?;
37            }
38        }
39        Ok(())
40    }
41}