1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright 2022 System76 <info@system76.com>
// SPDX-License-Identifier: MIT

use crate::*;

/// Builder API for mounting devices
///
/// ```no_run
/// use sys_mount::*;
///
/// fn main() -> std::io::Result<()> {
///     let _mount = Mount::builder()
///         .fstype("btrfs")
///         .data("subvol=@home")
///         .mount("/dev/sda1", "/home")?;
///     Ok(())
/// }
/// ```
#[derive(smart_default::SmartDefault)]
pub struct MountBuilder<'a> {
    #[default(MountFlags::empty())]
    flags: MountFlags,
    fstype: Option<FilesystemType<'a>>,
    data: Option<&'a str>,
}

impl<'a> MountBuilder<'a> {
    /// Options to apply for the file system on mount.
    pub fn data(mut self, data: &'a str) -> Self {
        self.data = Some(data);
        self
    }

    /// The file system that is to be mounted.
    pub fn fstype(mut self, fs: impl Into<FilesystemType<'a>>) -> Self {
        self.fstype = Some(fs.into());
        self
    }

    /// Mount flags for the mount syscall.
    pub fn flags(mut self, flags: MountFlags) -> Self {
        self.flags = flags;
        self
    }

    /// Mount the `source` to the `target`.
    pub fn mount(self, source: impl AsRef<Path>, target: impl AsRef<Path>) -> io::Result<Mount> {
        let MountBuilder {
            data,
            fstype,
            flags,
        } = self;

        let supported;

        let fstype = match fstype {
            Some(fstype) => fstype,
            None => {
                supported = SupportedFilesystems::new()?;
                FilesystemType::Auto(&supported)
            }
        };

        Mount::new(source, target, fstype, flags, data)
    }

    /// Perform a mount which auto-unmounts on drop.
    pub fn mount_autodrop(
        self,
        source: impl AsRef<Path>,
        target: impl AsRef<Path>,
        unmount_flags: UnmountFlags,
    ) -> io::Result<UnmountDrop<Mount>> {
        self.mount(source, target)
            .map(|m| m.into_unmount_drop(unmount_flags))
    }
}