btrfs_cli/subvolume/
set_default.rs1use crate::{Format, Runnable};
2use anyhow::{Context, Result, anyhow};
3use btrfs_uapi::subvolume::{
4 FS_TREE_OBJECTID, subvolume_default_set, subvolume_info,
5};
6use clap::Parser;
7use std::{fs::File, os::unix::io::AsFd, path::PathBuf};
8
9#[derive(Parser, Debug)]
14pub struct SubvolumeSetDefaultCommand {
15 #[clap(required = true)]
17 subvol_or_id: String,
18
19 path: Option<PathBuf>,
21}
22
23impl Runnable for SubvolumeSetDefaultCommand {
24 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
25 match self.subvol_or_id.parse::<u64>() {
26 Ok(id) => {
27 let mount = self.path.as_ref().ok_or_else(|| {
28 anyhow!("a filesystem path is required when specifying a subvolume ID")
29 })?;
30
31 let file = File::open(mount).with_context(|| {
32 format!("failed to open '{}'", mount.display())
33 })?;
34
35 let id_to_use = if id == 0 { FS_TREE_OBJECTID } else { id };
36
37 subvolume_default_set(file.as_fd(), id_to_use).with_context(
38 || {
39 format!(
40 "failed to set default subvolume to ID {} on '{}'",
41 id_to_use,
42 mount.display()
43 )
44 },
45 )?;
46
47 println!("Set default subvolume to ID {id_to_use}");
48 }
49 Err(_) => {
50 let subvol_path = PathBuf::from(&self.subvol_or_id);
51
52 let file = File::open(&subvol_path).with_context(|| {
53 format!("failed to open '{}'", subvol_path.display())
54 })?;
55
56 let info = subvolume_info(file.as_fd()).with_context(|| {
57 format!(
58 "failed to get subvolume info for '{}'",
59 subvol_path.display()
60 )
61 })?;
62
63 subvolume_default_set(file.as_fd(), info.id).with_context(
64 || {
65 format!(
66 "failed to set default subvolume to '{}' (ID {})",
67 subvol_path.display(),
68 info.id
69 )
70 },
71 )?;
72
73 println!(
74 "Set default subvolume to '{}' (ID {})",
75 subvol_path.display(),
76 info.id
77 );
78 }
79 }
80
81 Ok(())
82 }
83}