mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-07-26 23:19:29 +02:00
Uber refactoring
This commit is contained in:
parent
1182c96a08
commit
bb7567e72b
54
src/alma.rs
54
src/alma.rs
@ -1,54 +0,0 @@
|
|||||||
use super::block::BlockDevice;
|
|
||||||
use super::cryptsetup::EncryptedDevice;
|
|
||||||
use super::error::{Error, ErrorKind};
|
|
||||||
use super::mountstack::{Filesystem, MountStack};
|
|
||||||
use failure::ResultExt;
|
|
||||||
use log::{debug, info};
|
|
||||||
use std::fs;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
pub struct ALMA<'a> {
|
|
||||||
block: BlockDevice,
|
|
||||||
encrypted_root: Option<EncryptedDevice<'a>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ALMA<'a> {
|
|
||||||
pub fn new(block: BlockDevice, encrypted_root: Option<EncryptedDevice<'a>>) -> Self {
|
|
||||||
Self {
|
|
||||||
block,
|
|
||||||
encrypted_root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mount<'b>(&self, path: &'b Path) -> Result<MountStack<'b>, Error> {
|
|
||||||
let mut mount_stack = MountStack::new();
|
|
||||||
|
|
||||||
let root_device = if let Some(encrypted_root) = &self.encrypted_root {
|
|
||||||
PathBuf::from(encrypted_root.path())
|
|
||||||
} else {
|
|
||||||
self.block.partition_device_path(3)?
|
|
||||||
};
|
|
||||||
debug!("Root partition: {}", root_device.display());
|
|
||||||
|
|
||||||
info!("Mounting filesystems to {}", path.display());
|
|
||||||
mount_stack
|
|
||||||
.mount(&root_device, path, Filesystem::Ext4, None)
|
|
||||||
.context(ErrorKind::Mounting)?;
|
|
||||||
|
|
||||||
let boot_point = path.join("boot");
|
|
||||||
if !boot_point.exists() {
|
|
||||||
fs::create_dir(&boot_point).context(ErrorKind::CreateBoot)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
mount_stack
|
|
||||||
.mount(
|
|
||||||
&self.block.partition_device_path(1)?,
|
|
||||||
boot_point,
|
|
||||||
Filesystem::Vfat,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.context(ErrorKind::Mounting)?;
|
|
||||||
|
|
||||||
Ok(mount_stack)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
use super::error::{Error, ErrorKind};
|
|
||||||
use super::process::CommandExt;
|
|
||||||
use super::tool::Tool;
|
|
||||||
use log::{debug, warn};
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
pub struct EncryptedDevice<'a> {
|
|
||||||
cryptsetup: &'a Tool,
|
|
||||||
name: &'a str,
|
|
||||||
path: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> EncryptedDevice<'a> {
|
|
||||||
pub fn prepare(cryptsetup: &Tool, device: &Path) -> Result<(), Error> {
|
|
||||||
debug!("Preparing encrypted device in {}", device.display());
|
|
||||||
cryptsetup
|
|
||||||
.execute()
|
|
||||||
.arg("luksFormat")
|
|
||||||
.arg("-q")
|
|
||||||
.arg(device)
|
|
||||||
.run(ErrorKind::LuksSetup)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open(
|
|
||||||
cryptsetup: &'a Tool,
|
|
||||||
device: &Path,
|
|
||||||
name: &'a str,
|
|
||||||
) -> Result<EncryptedDevice<'a>, Error> {
|
|
||||||
debug!("Opening encrypted device {} as {}", device.display(), name);
|
|
||||||
cryptsetup
|
|
||||||
.execute()
|
|
||||||
.arg("open")
|
|
||||||
.arg(device)
|
|
||||||
.arg(name)
|
|
||||||
.run(ErrorKind::LuksOpen)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
cryptsetup,
|
|
||||||
name,
|
|
||||||
path: PathBuf::from("/dev/mapper").join(name),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _close(&mut self) -> Result<(), Error> {
|
|
||||||
debug!("Closing encrypted device {}", self.name);
|
|
||||||
self.cryptsetup
|
|
||||||
.execute()
|
|
||||||
.arg("close")
|
|
||||||
.arg(self.name)
|
|
||||||
.run(ErrorKind::LuksClose)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(&self) -> &Path {
|
|
||||||
&self.path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for EncryptedDevice<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self._close().is_err() {
|
|
||||||
warn!("Error closing {}", self.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
102
src/main.rs
102
src/main.rs
@ -1,15 +1,11 @@
|
|||||||
mod alma;
|
|
||||||
mod block;
|
|
||||||
mod cryptsetup;
|
|
||||||
mod error;
|
mod error;
|
||||||
mod mountstack;
|
|
||||||
mod process;
|
mod process;
|
||||||
|
mod storage;
|
||||||
mod tool;
|
mod tool;
|
||||||
|
|
||||||
use crate::alma::ALMA;
|
|
||||||
use crate::cryptsetup::EncryptedDevice;
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::process::CommandExt;
|
use crate::process::CommandExt;
|
||||||
|
use crate::storage::*;
|
||||||
use crate::tool::Tool;
|
use crate::tool::Tool;
|
||||||
use failure::{Fail, ResultExt};
|
use failure::{Fail, ResultExt};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
@ -17,7 +13,7 @@ use nix::sys::signal;
|
|||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -89,6 +85,34 @@ struct ChrootCommand {
|
|||||||
command: Vec<String>,
|
command: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mount<'a>(
|
||||||
|
mount_path: &Path,
|
||||||
|
boot_filesystem: &'a Filesystem,
|
||||||
|
root_filesystem: &'a Filesystem,
|
||||||
|
) -> Result<MountStack<'a>, Error> {
|
||||||
|
let mut mount_stack = MountStack::new();
|
||||||
|
debug!(
|
||||||
|
"Root partition: {}",
|
||||||
|
root_filesystem.block().path().display()
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("Mounting filesystems to {}", mount_path.display());
|
||||||
|
mount_stack
|
||||||
|
.mount(&root_filesystem, mount_path.into(), None)
|
||||||
|
.context(ErrorKind::Mounting)?;
|
||||||
|
|
||||||
|
let boot_point = mount_path.join("boot");
|
||||||
|
if !boot_point.exists() {
|
||||||
|
fs::create_dir(&boot_point).context(ErrorKind::CreateBoot)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
mount_stack
|
||||||
|
.mount(&boot_filesystem, boot_point, None)
|
||||||
|
.context(ErrorKind::Mounting)?;
|
||||||
|
|
||||||
|
Ok(mount_stack)
|
||||||
|
}
|
||||||
|
|
||||||
fn fix_fstab(fstab: &str) -> String {
|
fn fix_fstab(fstab: &str) -> String {
|
||||||
fstab
|
fstab
|
||||||
.lines()
|
.lines()
|
||||||
@ -115,11 +139,9 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
let storage_device = storage::StorageDevice::from_path(command.block_device)?;
|
||||||
|
|
||||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||||
|
let disk_path = storage_device.path();
|
||||||
let disk_path = block_device.device_path();
|
|
||||||
|
|
||||||
info!("Partitioning the block device");
|
info!("Partitioning the block device");
|
||||||
debug!("{:?}", disk_path);
|
debug!("{:?}", disk_path);
|
||||||
@ -141,38 +163,31 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
thread::sleep(Duration::from_millis(1000));
|
thread::sleep(Duration::from_millis(1000));
|
||||||
|
|
||||||
info!("Formatting filesystems");
|
info!("Formatting filesystems");
|
||||||
let boot_partition = block_device.partition_device_path(1)?;
|
let boot_partition = storage_device.get_partition(1)?;
|
||||||
mkfat
|
let boot_filesystem = Filesystem::format(&boot_partition, FilesystemType::Vfat, &mkfat)?;
|
||||||
.execute()
|
|
||||||
.arg("-F32")
|
|
||||||
.arg(&boot_partition)
|
|
||||||
.run(ErrorKind::Formatting)?;
|
|
||||||
|
|
||||||
let root_partition = block_device.partition_device_path(3)?;
|
let root_partition_base = storage_device.get_partition(3)?;
|
||||||
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
||||||
info!("Encrypting the root filesystem");
|
info!("Encrypting the root filesystem");
|
||||||
EncryptedDevice::prepare(&cryptsetup, &root_partition)?;
|
EncryptedDevice::prepare(&cryptsetup, &root_partition_base)?;
|
||||||
Some(EncryptedDevice::open(
|
Some(EncryptedDevice::open(
|
||||||
cryptsetup,
|
cryptsetup,
|
||||||
&root_partition,
|
&root_partition_base,
|
||||||
"alma_root",
|
"alma_root".into(),
|
||||||
)?)
|
)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
mkext4
|
let root_partition = if let Some(e) = encrypted_root.as_ref() {
|
||||||
.execute()
|
e as &BlockDevice
|
||||||
.arg("-F")
|
|
||||||
.arg(if let Some(device) = &encrypted_root {
|
|
||||||
device.path()
|
|
||||||
} else {
|
} else {
|
||||||
&root_partition
|
&root_partition_base as &BlockDevice
|
||||||
})
|
};
|
||||||
.run(ErrorKind::Formatting)?;
|
|
||||||
|
|
||||||
let alma = ALMA::new(block_device, encrypted_root);
|
let root_filesystem = Filesystem::format(root_partition, FilesystemType::Ext4, &mkext4)?;
|
||||||
let mount_stack = alma.mount(mount_point.path())?;
|
|
||||||
|
let mount_stack = mount(mount_point.path(), &boot_filesystem, &root_filesystem)?;
|
||||||
|
|
||||||
info!("Bootstrapping system");
|
info!("Bootstrapping system");
|
||||||
pacstrap
|
pacstrap
|
||||||
@ -246,7 +261,7 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
let uuid = blkid
|
let uuid = blkid
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute()
|
.execute()
|
||||||
.arg(root_partition)
|
.arg(root_partition.path())
|
||||||
.args(&["-o", "value", "-s", "UUID"])
|
.args(&["-o", "value", "-s", "UUID"])
|
||||||
.run_text_output(ErrorKind::Partitioning)?;
|
.run_text_output(ErrorKind::Partitioning)?;
|
||||||
let trimmed = uuid.trim();
|
let trimmed = uuid.trim();
|
||||||
@ -295,22 +310,31 @@ fn chroot(command: ChrootCommand) -> Result<(), Error> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
let storage_device = storage::StorageDevice::from_path(command.block_device)?;
|
||||||
|
|
||||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||||
let root_partition = block_device.partition_device_path(3)?;
|
|
||||||
|
let boot_partition = storage_device.get_partition(1)?;
|
||||||
|
let boot_filesystem = Filesystem::from_partition(&boot_partition, FilesystemType::Vfat);
|
||||||
|
|
||||||
|
let root_partition_base = storage_device.get_partition(3)?;
|
||||||
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
||||||
Some(EncryptedDevice::open(
|
Some(EncryptedDevice::open(
|
||||||
cryptsetup,
|
cryptsetup,
|
||||||
&root_partition,
|
&root_partition_base,
|
||||||
"alma_root",
|
"alma_root".into(),
|
||||||
)?)
|
)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let alma = ALMA::new(block_device, encrypted_root);
|
let root_partition = if let Some(e) = encrypted_root.as_ref() {
|
||||||
let mount_stack = alma.mount(mount_point.path())?;
|
e as &BlockDevice
|
||||||
|
} else {
|
||||||
|
&root_partition_base as &BlockDevice
|
||||||
|
};
|
||||||
|
let root_filesystem = Filesystem::from_partition(root_partition, FilesystemType::Ext4);
|
||||||
|
|
||||||
|
let mount_stack = mount(mount_point.path(), &boot_filesystem, &root_filesystem)?;
|
||||||
|
|
||||||
arch_chroot
|
arch_chroot
|
||||||
.execute()
|
.execute()
|
||||||
|
80
src/storage/crypt.rs
Normal file
80
src/storage/crypt.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use super::markers::BlockDevice;
|
||||||
|
use crate::error::{Error, ErrorKind};
|
||||||
|
use crate::process::CommandExt;
|
||||||
|
use crate::tool::Tool;
|
||||||
|
use log::{debug, warn};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EncryptedDevice<'t, 'o> {
|
||||||
|
cryptsetup: &'t Tool,
|
||||||
|
name: String,
|
||||||
|
path: PathBuf,
|
||||||
|
origin: PhantomData<&'o BlockDevice>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, 'o> EncryptedDevice<'t, 'o> {
|
||||||
|
pub fn prepare(cryptsetup: &Tool, device: &BlockDevice) -> Result<(), Error> {
|
||||||
|
debug!("Preparing encrypted device in {}", device.path().display());
|
||||||
|
cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("luksFormat")
|
||||||
|
.arg("-q")
|
||||||
|
.arg(device.path())
|
||||||
|
.run(ErrorKind::LuksSetup)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(
|
||||||
|
cryptsetup: &'t Tool,
|
||||||
|
device: &'o BlockDevice,
|
||||||
|
name: String,
|
||||||
|
) -> Result<EncryptedDevice<'t, 'o>, Error> {
|
||||||
|
debug!(
|
||||||
|
"Opening encrypted device {} as {}",
|
||||||
|
device.path().display(),
|
||||||
|
name
|
||||||
|
);
|
||||||
|
cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("open")
|
||||||
|
.arg(device.path())
|
||||||
|
.arg(&name)
|
||||||
|
.run(ErrorKind::LuksOpen)?;
|
||||||
|
|
||||||
|
let path = PathBuf::from("/dev/mapper").join(&name);
|
||||||
|
Ok(Self {
|
||||||
|
cryptsetup,
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
origin: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _close(&mut self) -> Result<(), Error> {
|
||||||
|
debug!("Closing encrypted device {}", self.name);
|
||||||
|
self.cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("close")
|
||||||
|
.arg(&self.name)
|
||||||
|
.run(ErrorKind::LuksClose)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, 'o> Drop for EncryptedDevice<'t, 'o> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self._close().is_err() {
|
||||||
|
warn!("Error closing {}", self.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, 'o> BlockDevice for EncryptedDevice<'t, 'o> {
|
||||||
|
fn path(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
57
src/storage/filesystem.rs
Normal file
57
src/storage/filesystem.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use super::markers::BlockDevice;
|
||||||
|
use crate::{
|
||||||
|
error::{Error, ErrorKind},
|
||||||
|
process::CommandExt,
|
||||||
|
tool::Tool,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum FilesystemType {
|
||||||
|
Ext4,
|
||||||
|
Vfat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilesystemType {
|
||||||
|
pub fn to_mount_type(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
FilesystemType::Ext4 => "ext4",
|
||||||
|
FilesystemType::Vfat => "vfat",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Filesystem<'a> {
|
||||||
|
fs_type: FilesystemType,
|
||||||
|
block: &'a BlockDevice,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Filesystem<'a> {
|
||||||
|
pub fn format(
|
||||||
|
block: &'a BlockDevice,
|
||||||
|
fs_type: FilesystemType,
|
||||||
|
mkfs: &Tool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let mut command = mkfs.execute();
|
||||||
|
match fs_type {
|
||||||
|
FilesystemType::Ext4 => command.arg("-F").arg(block.path()),
|
||||||
|
FilesystemType::Vfat => command.arg("-F32").arg(block.path()),
|
||||||
|
};
|
||||||
|
|
||||||
|
command.run(ErrorKind::Formatting)?;
|
||||||
|
|
||||||
|
Ok(Self { fs_type, block })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_partition(block: &'a BlockDevice, fs_type: FilesystemType) -> Self {
|
||||||
|
Self { fs_type, block }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block(&self) -> &BlockDevice {
|
||||||
|
self.block
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fs_type(&self) -> FilesystemType {
|
||||||
|
self.fs_type
|
||||||
|
}
|
||||||
|
}
|
7
src/storage/markers.rs
Normal file
7
src/storage/markers.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub trait BlockDevice: std::fmt::Debug {
|
||||||
|
fn path(&self) -> &Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Origin {}
|
12
src/storage/mod.rs
Normal file
12
src/storage/mod.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
mod crypt;
|
||||||
|
mod filesystem;
|
||||||
|
mod markers;
|
||||||
|
mod mount_stack;
|
||||||
|
mod partition;
|
||||||
|
mod storage_device;
|
||||||
|
|
||||||
|
pub use crypt::EncryptedDevice;
|
||||||
|
pub use filesystem::{Filesystem, FilesystemType};
|
||||||
|
pub use markers::BlockDevice;
|
||||||
|
pub use mount_stack::MountStack;
|
||||||
|
pub use storage_device::StorageDevice;
|
@ -1,52 +1,38 @@
|
|||||||
use super::error::{Error, ErrorKind};
|
use super::Filesystem;
|
||||||
|
use crate::error::{Error, ErrorKind};
|
||||||
use failure::Fail;
|
use failure::Fail;
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
use nix;
|
use nix;
|
||||||
use nix::mount::{mount, umount, MsFlags};
|
use nix::mount::{mount, umount, MsFlags};
|
||||||
use std::borrow::Cow;
|
use std::marker::PhantomData;
|
||||||
use std::path::Path;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum Filesystem {
|
|
||||||
Ext4,
|
|
||||||
Vfat,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Filesystem {
|
|
||||||
fn to_type(self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
Filesystem::Ext4 => "ext4",
|
|
||||||
Filesystem::Vfat => "vfat",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MountStack<'a> {
|
pub struct MountStack<'a> {
|
||||||
targets: Vec<Cow<'a, Path>>,
|
targets: Vec<PathBuf>,
|
||||||
|
filesystems: PhantomData<Filesystem<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MountStack<'a> {
|
impl<'a> MountStack<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MountStack {
|
MountStack {
|
||||||
targets: Vec::new(),
|
targets: Vec::new(),
|
||||||
|
filesystems: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn mount<T: Into<Cow<'a, Path>>>(
|
pub fn mount(
|
||||||
&mut self,
|
&mut self,
|
||||||
source: &Path,
|
filesystem: &'a Filesystem,
|
||||||
target: T,
|
target: PathBuf,
|
||||||
filesystem: Filesystem,
|
|
||||||
options: Option<&str>,
|
options: Option<&str>,
|
||||||
) -> nix::Result<()> {
|
) -> nix::Result<()> {
|
||||||
let target = target.into();
|
let source = filesystem.block().path();
|
||||||
|
debug!("Mounting {:?} to {:?}", filesystem, target);
|
||||||
debug!("Mounting {:?} ({:?}) to {:?}", source, filesystem, target);
|
|
||||||
mount(
|
mount(
|
||||||
Some(source),
|
Some(source),
|
||||||
target.as_ref(),
|
&target,
|
||||||
Some(filesystem.to_type()),
|
Some(filesystem.fs_type().to_mount_type()),
|
||||||
MsFlags::MS_NOATIME,
|
MsFlags::MS_NOATIME,
|
||||||
options,
|
options,
|
||||||
)?;
|
)?;
|
||||||
@ -59,7 +45,7 @@ impl<'a> MountStack<'a> {
|
|||||||
|
|
||||||
while let Some(target) = self.targets.pop() {
|
while let Some(target) = self.targets.pop() {
|
||||||
debug!("Unmounting {}", target.display());
|
debug!("Unmounting {}", target.display());
|
||||||
if let Err(e) = umount(target.as_ref()) {
|
if let Err(e) = umount(&target) {
|
||||||
warn!("Unable to umount {}: {}", target.display(), e);
|
warn!("Unable to umount {}: {}", target.display(), e);
|
||||||
result = Err(Error::from(e.context(ErrorKind::UmountFailure)));
|
result = Err(Error::from(e.context(ErrorKind::UmountFailure)));
|
||||||
};
|
};
|
24
src/storage/partition.rs
Normal file
24
src/storage/partition.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use super::markers::{BlockDevice, Origin};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Partition<'a> {
|
||||||
|
path: PathBuf,
|
||||||
|
origin: PhantomData<&'a Origin>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Partition<'a> {
|
||||||
|
pub fn new<T: Origin + 'a>(path: PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
path,
|
||||||
|
origin: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BlockDevice for Partition<'a> {
|
||||||
|
fn path(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,18 @@
|
|||||||
use super::error::{Error, ErrorKind};
|
use super::markers::{BlockDevice, Origin};
|
||||||
|
use super::partition::Partition;
|
||||||
|
use crate::error::{Error, ErrorKind};
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BlockDevice {
|
pub struct StorageDevice {
|
||||||
name: String,
|
name: String,
|
||||||
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDevice {
|
impl StorageDevice {
|
||||||
pub fn from_path(path: PathBuf) -> Result<Self, Error> {
|
pub fn from_path(path: PathBuf) -> Result<Self, Error> {
|
||||||
let real_path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
|
let real_path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
|
||||||
let device_name = real_path
|
let device_name = real_path
|
||||||
@ -24,8 +27,11 @@ impl BlockDevice {
|
|||||||
);
|
);
|
||||||
|
|
||||||
drop(path);
|
drop(path);
|
||||||
let _self = Self { name: device_name };
|
let _self = Self {
|
||||||
if !(_self.is_removable()? || _self.is_loop_device()) {
|
name: device_name,
|
||||||
|
path: real_path,
|
||||||
|
};
|
||||||
|
if !(_self.is_removable_device()? || _self.is_loop_device()) {
|
||||||
return Err(ErrorKind::DangerousDevice)?;
|
return Err(ErrorKind::DangerousDevice)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +44,7 @@ impl BlockDevice {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_removable(&self) -> Result<bool, Error> {
|
fn is_removable_device(&self) -> Result<bool, Error> {
|
||||||
let mut path = self.sys_path();
|
let mut path = self.sys_path();
|
||||||
path.push("removable");
|
path.push("removable");
|
||||||
|
|
||||||
@ -55,13 +61,7 @@ impl BlockDevice {
|
|||||||
path.exists()
|
path.exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_path(&self) -> PathBuf {
|
pub fn get_partition(&self, index: u8) -> Result<Partition, Error> {
|
||||||
let mut path = PathBuf::from("/dev");
|
|
||||||
path.push(self.name.clone());
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn partition_device_path(&self, index: u8) -> Result<PathBuf, Error> {
|
|
||||||
let name = if self.name.chars().rev().next().unwrap().is_digit(10) {
|
let name = if self.name.chars().rev().next().unwrap().is_digit(10) {
|
||||||
format!("{}p{}", self.name, index)
|
format!("{}p{}", self.name, index)
|
||||||
} else {
|
} else {
|
||||||
@ -74,6 +74,14 @@ impl BlockDevice {
|
|||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Err(ErrorKind::NoSuchPartition(index).into());
|
return Err(ErrorKind::NoSuchPartition(index).into());
|
||||||
}
|
}
|
||||||
Ok(path)
|
Ok(Partition::new::<Self>(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockDevice for StorageDevice {
|
||||||
|
fn path(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Origin for StorageDevice {}
|
Loading…
x
Reference in New Issue
Block a user