Skip to content

Commit

Permalink
* Added warning for sector size that are not multiple of 512
Browse files Browse the repository at this point in the history
* Errors are printed as red
  • Loading branch information
CKingX committed May 7, 2022
1 parent afdf0ae commit 7e7e59b
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 76 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "ddr-mount"
license = "AGPL-3.0-only"
version = "1.0.0-beta.4"
version = "1.0.0"
edition = "2021"
authors = ["CKingX"]
description = "ddr-mount allows you to mount image files while passing bad sectors"
Expand Down
2 changes: 1 addition & 1 deletion package/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: ddr-mount
Version: 1.0.0-beta.4
Version: 1.0.0
Architecture: amd64
Depends: mount (>= 2.31), dmsetup (>= 2:1.02)
Recommends: bash
Expand Down
63 changes: 43 additions & 20 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::{env, io::ErrorKind};
use std::{env, io::ErrorKind, process};
use crate::unmount::*;
use atty::{self, Stream};
use termcolor::{StandardStream, self, ColorChoice, Color, WriteColor, ColorSpec};
use std::io::Write;

#[repr(i32)]
pub enum ExitCode {
Expand All @@ -11,6 +14,8 @@ pub enum ExitCode {
OOMError = 6,
ParseError = 7,
UnmountError = 8,
/// Sector Size not a multiple of 512
SectorSizeError = 9,
UnknownError = 10,
}

Expand All @@ -36,65 +41,83 @@ pub const OOM_ERROR: &str = "Out of memory error!";
pub const MOUNT_ERROR: &str = "Unable to mount image";
pub const NO_DEVICE_UNMOUNT_ERROR: &str = "Unmount error: Unable to find device";
pub const UNMOUNT_ERROR: &str = "Unable to unmount device";
pub const FILE_NOT_FOUND_ERROR: &str = "Unable to find";
pub const SECTOR_SIZE_ERROR: &str = "Sector size is not a multiple of 512";

pub fn file_not_found(filetype: FileType) -> String {
format!("Unable to find {}", filetype.to_string())
format!("{FILE_NOT_FOUND_ERROR} {}", filetype.to_string())
}

pub fn sector_error() -> ! {
print_error(format!("{}", SECTOR_SIZE_ERROR));
process::exit(ExitCode::SectorSizeError as i32);
}

fn print_error(error: String) {
if atty::is(Stream::Stderr) {
let mut stderr = StandardStream::stderr(ColorChoice::Always);
let _ = stderr.set_color(ColorSpec::new().set_fg(Some(Color::Red)));
let _ = writeln!(&mut stderr, "{}", error);

} else {
eprintln!("{}", error);
}
}

pub fn set_config_error() -> ! {
eprintln!("{}", SET_CONFIG_ERROR);
std::process::exit(ExitCode::ConfigError as i32);
print_error(format!("{}", SET_CONFIG_ERROR));
process::exit(ExitCode::ConfigError as i32);
}

pub fn handle_string_write(result: Result<(), std::fmt::Error>) {
if result.is_err() {
eprintln!("{OOM_ERROR}");
std::process::exit(ExitCode::OOMError as i32);
print_error(format!("{OOM_ERROR}"));
process::exit(ExitCode::OOMError as i32);
}
}

pub fn read_config_error() -> ! {
eprintln!("{}", READ_CONFIG_ERROR);
std::process::exit(ExitCode::ConfigError as i32);
print_error(format!("{}", READ_CONFIG_ERROR));
process::exit(ExitCode::ConfigError as i32);
}

pub fn check_root() {
let env_vars = env::vars().filter(|n| n.0 == "USER").next();
if let Some((_, user)) = env_vars {
if user != "root"{
let arguments = env::args().reduce(|a,b| format!("{a} {b}")).unwrap();
eprintln!("You must run as root.\nTry sudo {arguments}");
std::process::exit(ExitCode::NonRoot as i32);
print_error(format!("You must run as root.\nTry sudo {arguments}"));
process::exit(ExitCode::NonRoot as i32);
}
}
}

pub fn check_io_error(error: std::io::Error, filename: String, filetype: FileType) -> ! {
match error.kind() {
ErrorKind::NotFound => {
eprintln!("{} {}", file_not_found(filetype), filename);
std::process::exit(ExitCode::FileError as i32);
print_error(format!("{} {}", file_not_found(filetype), filename));
process::exit(ExitCode::FileError as i32);
}
error => {
eprintln!("Unknown error while reading {filename} {}", error.to_string());
std::process::exit(ExitCode::UnknownError as i32);
print_error(format!("Unknown error while reading {filename} {}", error.to_string()));
process::exit(ExitCode::UnknownError as i32);
}
}
}

pub fn mount_error() -> ! {
eprintln!("{MOUNT_ERROR}");
std::process::exit(ExitCode::MountError as i32);
print_error(format!("{MOUNT_ERROR}"));
process::exit(ExitCode::MountError as i32);
}

pub fn no_unmount_device(device: String) -> ! {
eprintln!("{NO_DEVICE_UNMOUNT_ERROR} {device}");
std::process::exit(ExitCode::UnmountError as i32);
print_error(format!("{NO_DEVICE_UNMOUNT_ERROR} {device}"));
process::exit(ExitCode::UnmountError as i32);
}

pub fn unmount_error() -> ! {
eprintln!("{UNMOUNT_ERROR}");
std::process::exit(ExitCode::UnmountError as i32);
print_error(format!("{UNMOUNT_ERROR}"));
process::exit(ExitCode::UnmountError as i32);
}

pub fn mount_error_clean(device: &str) -> ! {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod mount;
mod config;
mod unmount;
mod arguments;
mod parser;

use mount::*;
use config::list_devices;
Expand Down
59 changes: 6 additions & 53 deletions src/mount.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use std::{ffi::{OsString}, fs, fmt::Write, process::{self, Command}, io::{ErrorKind, Write as IoWrite}};
use std::{ffi::{OsString}, process::{self, Command}, io::{ErrorKind, Write as IoWrite}};

use crate::error::{self, FileType};
use crate::config::{self, DM_LOCATION};
use std::path::Path;
use std::io::Error as IOError;
use crate::parser::parse_map;

pub fn mount(image: OsString, map: OsString, block_size: u32) {

if block_size % 512 != 0 {
error::sector_error();
}

let image = absolute_image_path(image);

// mount the image
Expand All @@ -26,58 +31,6 @@ pub fn mount(image: OsString, map: OsString, block_size: u32) {
}
}

fn parse_map(map_path: &OsString, device_name: &str) -> String {
let mut output = String::new();
let contents= fs::read_to_string(map_path.clone())
.unwrap_or_else(|error| error::check_io_error(error,
map_path.clone().into_string().unwrap_or_default(),
crate::error::FileType::MapFile));

let mut file_line = contents.lines()
.map(|s| s.trim())
.filter(|s| !s.is_empty() && !s.contains("#"))
.skip(1);

while let Some(line) = file_line.next() {
let pos_string: String;
let pos: u64;
let size: u64;
let size_string: String;
let status: char;

let mut map_line = line.split_ascii_whitespace();
pos_string = map_line.next().expect(error::PARSE_ERROR).to_string();
size_string = map_line.next().expect(error::PARSE_ERROR).to_string();
status = map_line.next().expect(error::PARSE_ERROR).chars().nth(0)
.unwrap();

pos = u64::from_str_radix(pos_string.trim_start_matches("0x"),16)
.expect(error::CONVERT_ERROR);
size = u64::from_str_radix(size_string.trim_start_matches("0x"),16)
.expect(error::CONVERT_ERROR);

if status == '+' {
error::handle_string_write(writeln!(output,"{}",
create_linear(pos,size, &device_name)));
} else {
error::handle_string_write(writeln!(output, "{}",
create_error(pos, size)));
}
}

output
}

/// Creates dmtable for error device
fn create_error(pos: u64, size: u64) -> String {
format!("{} {} error", pos/512, size/512)
}

/// Creates dmtable for linear device
fn create_linear(pos: u64, size: u64, device: &str) -> String {
format!("{} {} linear {device} {}", pos/512, size/512, pos/512)
}

/// Gets the absolute path of the image
fn absolute_image_path(path: OsString) -> OsString {
let path: &Path = path.as_ref();
Expand Down
63 changes: 63 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::{ffi::OsString, fs, fmt::Write};
use crate::error;


pub fn parse_map(map_path: &OsString, device_name: &str) -> String {
let mut output = String::new();
let contents= fs::read_to_string(map_path.clone())
.unwrap_or_else(|error| error::check_io_error(error,
map_path.clone().into_string().unwrap_or_default(),
crate::error::FileType::MapFile));

let mut file_line = contents.lines()
.map(|s| s.trim())
.filter(|s| !s.is_empty() && !s.contains("#"))
.skip(1);

while let Some(line) = file_line.next() {
let pos_string: String;
let pos: u64;
let size: u64;
let size_string: String;
let status: char;

let mut map_line = line.split_ascii_whitespace();
pos_string = map_line.next().expect(error::PARSE_ERROR).to_string();
size_string = map_line.next().expect(error::PARSE_ERROR).to_string();
status = map_line.next().expect(error::PARSE_ERROR).chars().nth(0)
.unwrap();

pos = u64::from_str_radix(pos_string.trim_start_matches("0x"),16)
.expect(error::CONVERT_ERROR);
size = u64::from_str_radix(size_string.trim_start_matches("0x"),16)
.expect(error::CONVERT_ERROR);

if status == '+' {
error::handle_string_write(writeln!(output,"{}",
create_linear(pos,size, &device_name)));
} else {
error::handle_string_write(writeln!(output, "{}",
create_error(pos, size)));
}
}

output
}

/// Creates dmtable for error device
fn create_error(pos: u64, size: u64) -> String {
format!("{} {} error", sector(pos), sector(size))
}

/// Creates dmtable for linear device
fn create_linear(pos: u64, size: u64, device: &str) -> String {
format!("{} {} linear {device} {}", sector(pos), sector(size), sector(pos))
}

fn sector(size: u64) -> u64 {
if size % 512 != 0 {
error::sector_error();
} else {
size/512
}
}

0 comments on commit 7e7e59b

Please sign in to comment.