mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-07-26 23:19:29 +02:00
Add a flag for non-removable devices (fix #24)
This commit is contained in:
parent
25cdc44c7c
commit
750653c222
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -13,6 +13,7 @@ name = "alma"
|
|||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byte-unit 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byte-unit 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dialoguer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dialoguer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -17,3 +17,4 @@ nix = "0.15.0"
|
|||||||
env_logger = "0.6.2"
|
env_logger = "0.6.2"
|
||||||
pretty_env_logger = "0.3.0"
|
pretty_env_logger = "0.3.0"
|
||||||
dialoguer = "0.4.0"
|
dialoguer = "0.4.0"
|
||||||
|
console = "0.7.7"
|
||||||
|
13
src/args.rs
13
src/args.rs
@ -60,9 +60,16 @@ pub struct CreateCommand {
|
|||||||
)]
|
)]
|
||||||
pub image: Option<Byte>,
|
pub image: Option<Byte>,
|
||||||
|
|
||||||
/// Overwrite existing image files. Use with caution
|
/// Overwrite existing image files. Use with caution!
|
||||||
#[structopt(long = "overwrite")]
|
#[structopt(long = "overwrite")]
|
||||||
pub overwrite: bool,
|
pub overwrite: bool,
|
||||||
|
|
||||||
|
/// Allow installation on non-removable devices. Use with extreme caution!
|
||||||
|
///
|
||||||
|
/// If no device is specified in the command line, the device selection menu will
|
||||||
|
/// show non-removable devices
|
||||||
|
#[structopt(long = "allow-non-removable")]
|
||||||
|
pub allow_non_removable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
@ -71,6 +78,10 @@ pub struct ChrootCommand {
|
|||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
pub block_device: PathBuf,
|
pub block_device: PathBuf,
|
||||||
|
|
||||||
|
/// Allow installation on non-removable devices. Use with extreme caution!
|
||||||
|
#[structopt(long = "allow-non-removable")]
|
||||||
|
pub allow_non_removable: bool,
|
||||||
|
|
||||||
/// Optional command to run
|
/// Optional command to run
|
||||||
#[structopt()]
|
#[structopt()]
|
||||||
pub command: Vec<String>,
|
pub command: Vec<String>,
|
||||||
|
@ -92,8 +92,8 @@ pub enum ErrorKind {
|
|||||||
#[fail(display = "Error setting up a loop device: {}", _0)]
|
#[fail(display = "Error setting up a loop device: {}", _0)]
|
||||||
Losetup(String),
|
Losetup(String),
|
||||||
|
|
||||||
#[fail(display = "Error querying removeable devices")]
|
#[fail(display = "Error querying storage devices")]
|
||||||
RemoveableDevicesQuery,
|
StorageDevicesQuery,
|
||||||
|
|
||||||
#[fail(display = "There are no removable devices")]
|
#[fail(display = "There are no removable devices")]
|
||||||
NoRemovableDevices,
|
NoRemovableDevices,
|
||||||
|
36
src/main.rs
36
src/main.rs
@ -12,6 +12,7 @@ use crate::process::CommandExt;
|
|||||||
use crate::storage::*;
|
use crate::storage::*;
|
||||||
use crate::tool::Tool;
|
use crate::tool::Tool;
|
||||||
use byte_unit::Byte;
|
use byte_unit::Byte;
|
||||||
|
use console::style;
|
||||||
use dialoguer::{theme::ColorfulTheme, Select};
|
use dialoguer::{theme::ColorfulTheme, Select};
|
||||||
use failure::{Fail, ResultExt};
|
use failure::{Fail, ResultExt};
|
||||||
use log::{debug, error, info, log_enabled, Level, LevelFilter};
|
use log::{debug, error, info, log_enabled, Level, LevelFilter};
|
||||||
@ -91,13 +92,22 @@ fn create_image(path: &Path, size: Byte, overwrite: bool) -> Result<LoopDevice,
|
|||||||
LoopDevice::create(path)
|
LoopDevice::create(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_block_device() -> Result<PathBuf, Error> {
|
fn select_block_device(allow_non_removable: bool) -> Result<PathBuf, Error> {
|
||||||
let devices = get_removable_devices()?;
|
let devices = get_storage_devices(allow_non_removable)?;
|
||||||
|
|
||||||
if devices.is_empty() {
|
if devices.is_empty() {
|
||||||
Err(ErrorKind::NoRemovableDevices)?
|
Err(ErrorKind::NoRemovableDevices)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if allow_non_removable {
|
||||||
|
println!(
|
||||||
|
"{}\n",
|
||||||
|
style("Showing non-removable devices. Make sure you select the correct device.")
|
||||||
|
.red()
|
||||||
|
.bold()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||||
.with_prompt("Select a removable device")
|
.with_prompt("Select a removable device")
|
||||||
.default(0)
|
.default(0)
|
||||||
@ -132,7 +142,7 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
let storage_device_path = if let Some(path) = command.path {
|
let storage_device_path = if let Some(path) = command.path {
|
||||||
path
|
path
|
||||||
} else {
|
} else {
|
||||||
select_block_device()?
|
select_block_device(command.allow_non_removable)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let image_loop = if let Some(size) = command.image {
|
let image_loop = if let Some(size) = command.image {
|
||||||
@ -149,6 +159,7 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
loop_dev.path()
|
loop_dev.path()
|
||||||
})
|
})
|
||||||
.unwrap_or(&storage_device_path),
|
.unwrap_or(&storage_device_path),
|
||||||
|
command.allow_non_removable,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||||
@ -373,13 +384,18 @@ fn chroot(command: ChrootCommand) -> Result<(), Error> {
|
|||||||
let mut cryptsetup;
|
let mut cryptsetup;
|
||||||
|
|
||||||
let mut loop_device: Option<LoopDevice>;
|
let mut loop_device: Option<LoopDevice>;
|
||||||
let storage_device = match storage::StorageDevice::from_path(&command.block_device) {
|
let storage_device =
|
||||||
Ok(b) => b,
|
match storage::StorageDevice::from_path(&command.block_device, command.allow_non_removable)
|
||||||
Err(_) => {
|
{
|
||||||
loop_device = Some(LoopDevice::create(&command.block_device)?);
|
Ok(b) => b,
|
||||||
storage::StorageDevice::from_path(loop_device.as_ref().unwrap().path())?
|
Err(_) => {
|
||||||
}
|
loop_device = Some(LoopDevice::create(&command.block_device)?);
|
||||||
};
|
storage::StorageDevice::from_path(
|
||||||
|
loop_device.as_ref().unwrap().path(),
|
||||||
|
command.allow_non_removable,
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
};
|
||||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||||
|
|
||||||
let boot_partition = storage_device.get_partition(BOOT_PARTITION_INDEX)?;
|
let boot_partition = storage_device.get_partition(BOOT_PARTITION_INDEX)?;
|
||||||
|
@ -12,5 +12,5 @@ pub use filesystem::{Filesystem, FilesystemType};
|
|||||||
pub use loop_device::LoopDevice;
|
pub use loop_device::LoopDevice;
|
||||||
pub use markers::BlockDevice;
|
pub use markers::BlockDevice;
|
||||||
pub use mount_stack::MountStack;
|
pub use mount_stack::MountStack;
|
||||||
pub use removeable_devices::get_removable_devices;
|
pub use removeable_devices::get_storage_devices;
|
||||||
pub use storage_device::StorageDevice;
|
pub use storage_device::StorageDevice;
|
||||||
|
@ -27,22 +27,24 @@ fn trimmed(source: String) -> String {
|
|||||||
String::from(source.trim_end())
|
String::from(source.trim_end())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_removable_devices() -> Result<Vec<Device>, Error> {
|
pub fn get_storage_devices(allow_non_removable: bool) -> Result<Vec<Device>, Error> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
for entry in fs::read_dir("/sys/block").context(ErrorKind::RemoveableDevicesQuery)? {
|
for entry in fs::read_dir("/sys/block").context(ErrorKind::StorageDevicesQuery)? {
|
||||||
let entry = entry.context(ErrorKind::RemoveableDevicesQuery)?;
|
let entry = entry.context(ErrorKind::StorageDevicesQuery)?;
|
||||||
|
|
||||||
let removable = fs::read_to_string(entry.path().join("removable"))
|
let removable = allow_non_removable
|
||||||
.context(ErrorKind::RemoveableDevicesQuery)?;
|
|| fs::read_to_string(entry.path().join("removable"))
|
||||||
|
.map(|v| v == "1\n")
|
||||||
|
.context(ErrorKind::StorageDevicesQuery)?;
|
||||||
|
|
||||||
if removable != "1\n" {
|
if !removable {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let model = fs::read_to_string(entry.path().join("device/model"))
|
let model = fs::read_to_string(entry.path().join("device/model"))
|
||||||
.map(trimmed)
|
.map(trimmed)
|
||||||
.context(ErrorKind::RemoveableDevicesQuery)?;
|
.context(ErrorKind::StorageDevicesQuery)?;
|
||||||
|
|
||||||
if model == "CD-ROM" {
|
if model == "CD-ROM" {
|
||||||
continue;
|
continue;
|
||||||
@ -58,10 +60,10 @@ pub fn get_removable_devices() -> Result<Vec<Device>, Error> {
|
|||||||
model,
|
model,
|
||||||
vendor: fs::read_to_string(entry.path().join("device/vendor"))
|
vendor: fs::read_to_string(entry.path().join("device/vendor"))
|
||||||
.map(trimmed)
|
.map(trimmed)
|
||||||
.context(ErrorKind::RemoveableDevicesQuery)?,
|
.context(ErrorKind::StorageDevicesQuery)?,
|
||||||
size: Byte::from_bytes(
|
size: Byte::from_bytes(
|
||||||
fs::read_to_string(entry.path().join("size"))
|
fs::read_to_string(entry.path().join("size"))
|
||||||
.context(ErrorKind::RemoveableDevicesQuery)?
|
.context(ErrorKind::StorageDevicesQuery)?
|
||||||
.trim()
|
.trim()
|
||||||
.parse::<u128>()
|
.parse::<u128>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -15,7 +15,7 @@ pub struct StorageDevice<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StorageDevice<'a> {
|
impl<'a> StorageDevice<'a> {
|
||||||
pub fn from_path(path: &'a Path) -> Result<Self, Error> {
|
pub fn from_path(path: &'a Path, allow_non_removable: bool) -> Result<Self, Error> {
|
||||||
debug!("path: {:?}", path);
|
debug!("path: {:?}", path);
|
||||||
let path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
|
let path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
|
||||||
let device_name = path
|
let device_name = path
|
||||||
@ -31,7 +31,7 @@ impl<'a> StorageDevice<'a> {
|
|||||||
path,
|
path,
|
||||||
origin: PhantomData,
|
origin: PhantomData,
|
||||||
};
|
};
|
||||||
if !(_self.is_removable_device()? || _self.is_loop_device()) {
|
if !allow_non_removable && (!(_self.is_removable_device()? || _self.is_loop_device())) {
|
||||||
return Err(ErrorKind::DangerousDevice)?;
|
return Err(ErrorKind::DangerousDevice)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user