| // Copyright 2023 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use std::fmt; |
| use std::path::Path; |
| |
| use anyhow::Result; |
| use log::{error, info}; |
| use nix::mount::{mount, umount, MsFlags}; |
| use tempfile::TempDir; |
| |
| pub enum FsType { |
| EXT4, |
| Vfat, |
| } |
| |
| impl fmt::Display for FsType { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| match self { |
| Self::EXT4 => f.write_str("ext4"), |
| Self::Vfat => f.write_str("vfat"), |
| } |
| } |
| } |
| |
| /// Mounts a disk to a tempdir and unmounts it on destruction. |
| pub struct Mount { |
| tempdir: TempDir, |
| } |
| |
| impl Mount { |
| pub fn mount_by_path(disk_path: &Path, fs_type: FsType) -> Result<Self> { |
| let tempdir = TempDir::new()?; |
| let flags = MsFlags::MS_NODEV | MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID; |
| let fs_str = fs_type.to_string(); |
| let data: Option<&Path> = None; |
| |
| info!( |
| "Mounting {} to {}", |
| disk_path.display(), |
| tempdir.path().display() |
| ); |
| mount( |
| Some(disk_path), |
| tempdir.path(), |
| Some(Path::new(&fs_str)), |
| flags, |
| data, |
| )?; |
| |
| Ok(Self { tempdir }) |
| } |
| |
| pub fn mount_path(&self) -> &Path { |
| self.tempdir.path() |
| } |
| |
| fn umount(&self) -> Result<()> { |
| info!("Unmounting {}", self.tempdir.path().display()); |
| umount(self.tempdir.path())?; |
| |
| Ok(()) |
| } |
| } |
| |
| impl Drop for Mount { |
| fn drop(&mut self) { |
| if let Err(err) = self.umount() { |
| error!( |
| "Error unmounting temp directory at {}: {}", |
| self.tempdir.path().display(), |
| err |
| ); |
| } |
| } |
| } |