Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Commit

Permalink
Add a flag for non-removable devices (fix #24)
Browse files Browse the repository at this point in the history
  • Loading branch information
r-darwish committed Aug 13, 2019
1 parent 25cdc44 commit 750653c
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 25 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ nix = "0.15.0"
env_logger = "0.6.2"
pretty_env_logger = "0.3.0"
dialoguer = "0.4.0"
console = "0.7.7"
13 changes: 12 additions & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,16 @@ pub struct CreateCommand {
)]
pub image: Option<Byte>,

/// Overwrite existing image files. Use with caution
/// Overwrite existing image files. Use with caution!
#[structopt(long = "overwrite")]
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)]
Expand All @@ -71,6 +78,10 @@ pub struct ChrootCommand {
#[structopt(parse(from_os_str))]
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
#[structopt()]
pub command: Vec<String>,
Expand Down
4 changes: 2 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ pub enum ErrorKind {
#[fail(display = "Error setting up a loop device: {}", _0)]
Losetup(String),

#[fail(display = "Error querying removeable devices")]
RemoveableDevicesQuery,
#[fail(display = "Error querying storage devices")]
StorageDevicesQuery,

#[fail(display = "There are no removable devices")]
NoRemovableDevices,
Expand Down
36 changes: 26 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::process::CommandExt;
use crate::storage::*;
use crate::tool::Tool;
use byte_unit::Byte;
use console::style;
use dialoguer::{theme::ColorfulTheme, Select};
use failure::{Fail, ResultExt};
use log::{debug, error, info, log_enabled, Level, LevelFilter};
Expand Down Expand Up @@ -91,13 +92,22 @@ fn create_image(path: &Path, size: Byte, overwrite: bool) -> Result<LoopDevice,
LoopDevice::create(path)
}

fn select_block_device() -> Result<PathBuf, Error> {
let devices = get_removable_devices()?;
fn select_block_device(allow_non_removable: bool) -> Result<PathBuf, Error> {
let devices = get_storage_devices(allow_non_removable)?;

if devices.is_empty() {
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())
.with_prompt("Select a removable device")
.default(0)
Expand Down Expand Up @@ -132,7 +142,7 @@ fn create(command: CreateCommand) -> Result<(), Error> {
let storage_device_path = if let Some(path) = command.path {
path
} else {
select_block_device()?
select_block_device(command.allow_non_removable)?
};

let image_loop = if let Some(size) = command.image {
Expand All @@ -149,6 +159,7 @@ fn create(command: CreateCommand) -> Result<(), Error> {
loop_dev.path()
})
.unwrap_or(&storage_device_path),
command.allow_non_removable,
)?;

let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
Expand Down Expand Up @@ -373,13 +384,18 @@ fn chroot(command: ChrootCommand) -> Result<(), Error> {
let mut cryptsetup;

let mut loop_device: Option<LoopDevice>;
let storage_device = match storage::StorageDevice::from_path(&command.block_device) {
Ok(b) => b,
Err(_) => {
loop_device = Some(LoopDevice::create(&command.block_device)?);
storage::StorageDevice::from_path(loop_device.as_ref().unwrap().path())?
}
};
let storage_device =
match storage::StorageDevice::from_path(&command.block_device, command.allow_non_removable)
{
Ok(b) => b,
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 boot_partition = storage_device.get_partition(BOOT_PARTITION_INDEX)?;
Expand Down
2 changes: 1 addition & 1 deletion src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ pub use filesystem::{Filesystem, FilesystemType};
pub use loop_device::LoopDevice;
pub use markers::BlockDevice;
pub use mount_stack::MountStack;
pub use removeable_devices::get_removable_devices;
pub use removeable_devices::get_storage_devices;
pub use storage_device::StorageDevice;
20 changes: 11 additions & 9 deletions src/storage/removeable_devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ fn trimmed(source: String) -> String {
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();

for entry in fs::read_dir("/sys/block").context(ErrorKind::RemoveableDevicesQuery)? {
let entry = entry.context(ErrorKind::RemoveableDevicesQuery)?;
for entry in fs::read_dir("/sys/block").context(ErrorKind::StorageDevicesQuery)? {
let entry = entry.context(ErrorKind::StorageDevicesQuery)?;

let removable = fs::read_to_string(entry.path().join("removable"))
.context(ErrorKind::RemoveableDevicesQuery)?;
let removable = allow_non_removable
|| fs::read_to_string(entry.path().join("removable"))
.map(|v| v == "1\n")
.context(ErrorKind::StorageDevicesQuery)?;

if removable != "1\n" {
if !removable {
continue;
}

let model = fs::read_to_string(entry.path().join("device/model"))
.map(trimmed)
.context(ErrorKind::RemoveableDevicesQuery)?;
.context(ErrorKind::StorageDevicesQuery)?;

if model == "CD-ROM" {
continue;
Expand All @@ -58,10 +60,10 @@ pub fn get_removable_devices() -> Result<Vec<Device>, Error> {
model,
vendor: fs::read_to_string(entry.path().join("device/vendor"))
.map(trimmed)
.context(ErrorKind::RemoveableDevicesQuery)?,
.context(ErrorKind::StorageDevicesQuery)?,
size: Byte::from_bytes(
fs::read_to_string(entry.path().join("size"))
.context(ErrorKind::RemoveableDevicesQuery)?
.context(ErrorKind::StorageDevicesQuery)?
.trim()
.parse::<u128>()
.unwrap()
Expand Down
4 changes: 2 additions & 2 deletions src/storage/storage_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct 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);
let path = path.canonicalize().context(ErrorKind::DeviceQuery)?;
let device_name = path
Expand All @@ -31,7 +31,7 @@ impl<'a> StorageDevice<'a> {
path,
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)?;
}

Expand Down

0 comments on commit 750653c

Please sign in to comment.