Loop device support
This commit is contained in:
52
src/storage/loop_device.rs
Normal file
52
src/storage/loop_device.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::tool::Tool;
|
||||
use failure::ResultExt;
|
||||
use log::info;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LoopDevice {
|
||||
path: PathBuf,
|
||||
losetup: Tool,
|
||||
}
|
||||
|
||||
impl LoopDevice {
|
||||
pub fn create(file: &Path) -> Result<Self, Error> {
|
||||
let losetup = Tool::find("losetup")?;
|
||||
let output = losetup
|
||||
.execute()
|
||||
.args(&["--find", "-P", "--show"])
|
||||
.arg(file)
|
||||
.output()
|
||||
.context(ErrorKind::Image)?;
|
||||
|
||||
if !output.status.success() {
|
||||
Err(ErrorKind::Losetup(
|
||||
String::from_utf8(output.stderr).unwrap(),
|
||||
))?
|
||||
}
|
||||
|
||||
Ok(LoopDevice {
|
||||
path: PathBuf::from(String::from_utf8(output.stdout).unwrap().trim()),
|
||||
losetup,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LoopDevice {
|
||||
fn drop(&mut self) {
|
||||
info!("Detaching loop device {}", self.path.display());
|
||||
self.losetup
|
||||
.execute()
|
||||
.arg("-d")
|
||||
.arg(&self.path)
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod crypt;
|
||||
mod filesystem;
|
||||
mod loop_device;
|
||||
mod markers;
|
||||
mod mount_stack;
|
||||
mod partition;
|
||||
@@ -7,6 +8,7 @@ mod storage_device;
|
||||
|
||||
pub use crypt::EncryptedDevice;
|
||||
pub use filesystem::{Filesystem, FilesystemType};
|
||||
pub use loop_device::LoopDevice;
|
||||
pub use markers::BlockDevice;
|
||||
pub use mount_stack::MountStack;
|
||||
pub use storage_device::StorageDevice;
|
||||
|
||||
@@ -4,16 +4,18 @@ use crate::error::{Error, ErrorKind};
|
||||
use failure::ResultExt;
|
||||
use log::debug;
|
||||
use std::fs::read_to_string;
|
||||
use std::marker::PhantomData;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StorageDevice {
|
||||
pub struct StorageDevice<'a> {
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
origin: PhantomData<&'a Origin>,
|
||||
}
|
||||
|
||||
impl StorageDevice {
|
||||
pub fn from_path(path: PathBuf) -> Result<Self, Error> {
|
||||
impl<'a> StorageDevice<'a> {
|
||||
pub fn from_path(path: &'a Path) -> Result<Self, Error> {
|
||||
let real_path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
|
||||
let device_name = real_path
|
||||
.file_name()
|
||||
@@ -30,6 +32,7 @@ impl StorageDevice {
|
||||
let _self = Self {
|
||||
name: device_name,
|
||||
path: real_path,
|
||||
origin: PhantomData,
|
||||
};
|
||||
if !(_self.is_removable_device()? || _self.is_loop_device()) {
|
||||
return Err(ErrorKind::DangerousDevice)?;
|
||||
@@ -78,10 +81,10 @@ impl StorageDevice {
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for StorageDevice {
|
||||
impl<'a> BlockDevice for StorageDevice<'a> {
|
||||
fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Origin for StorageDevice {}
|
||||
impl<'a> Origin for StorageDevice<'a> {}
|
||||
|
||||
Reference in New Issue
Block a user