From 7e7e59b487600ca557d942184cfdceb108ba2410 Mon Sep 17 00:00:00 2001 From: Chiragroop Date: Fri, 6 May 2022 23:29:38 -0700 Subject: [PATCH] * Added warning for sector size that are not multiple of 512 * Errors are printed as red --- Cargo.lock | 2 +- Cargo.toml | 2 +- package/DEBIAN/control | 2 +- src/error.rs | 63 ++++++++++++++++++++++++++++-------------- src/main.rs | 1 + src/mount.rs | 59 ++++----------------------------------- src/parser.rs | 63 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 76 deletions(-) create mode 100644 src/parser.rs diff --git a/Cargo.lock b/Cargo.lock index 54c86e4..918be89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ dependencies = [ [[package]] name = "ddr-mount" -version = "1.0.0-beta.4" +version = "1.0.0" dependencies = [ "atty", "clap", diff --git a/Cargo.toml b/Cargo.toml index 9a9647a..fb64ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/package/DEBIAN/control b/package/DEBIAN/control index 504b1f1..da1a43e 100644 --- a/package/DEBIAN/control +++ b/package/DEBIAN/control @@ -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 diff --git a/src/error.rs b/src/error.rs index 82cc119..fd6de1b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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 { @@ -11,6 +14,8 @@ pub enum ExitCode { OOMError = 6, ParseError = 7, UnmountError = 8, + /// Sector Size not a multiple of 512 + SectorSizeError = 9, UnknownError = 10, } @@ -36,26 +41,44 @@ 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() { @@ -63,8 +86,8 @@ pub fn check_root() { 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); } } } @@ -72,29 +95,29 @@ pub fn check_root() { 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) -> ! { diff --git a/src/main.rs b/src/main.rs index ebe1fc5..30e4535 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod mount; mod config; mod unmount; mod arguments; +mod parser; use mount::*; use config::list_devices; diff --git a/src/mount.rs b/src/mount.rs index a065762..9751169 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -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 @@ -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(); diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..8b8a6b3 --- /dev/null +++ b/src/parser.rs @@ -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 + } +} \ No newline at end of file