Skip to content

Commit 78cc14d

Browse files
committedMay 9, 2022
Can detect malformed ddrescue files where the disk map is not contiguous or is overlapping
1 parent 97d2bf9 commit 78cc14d

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed
 

‎src/error.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::io::Write;
55
use std::{env, io::ErrorKind, process};
66
use termcolor::{self, Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
77

8+
/// Represents all the exit codes of the program with 0 being success and the rest being errors
89
#[repr(i32)]
910
pub enum ExitCode {
1011
FileError = 1,
@@ -15,7 +16,6 @@ pub enum ExitCode {
1516
OOMError = 6,
1617
ParseError = 7,
1718
UnmountError = 8,
18-
/// Sector Size not a multiple of 512
1919
SectorSizeError = 9,
2020
UnknownError = 10,
2121
}
@@ -44,6 +44,12 @@ pub const NO_DEVICE_UNMOUNT_ERROR: &str = "Unmount error: Unable to find device"
4444
pub const UNMOUNT_ERROR: &str = "Unable to unmount device";
4545
pub const FILE_NOT_FOUND_ERROR: &str = "Unable to find";
4646
pub const SECTOR_SIZE_ERROR: &str = "Sector size is not a multiple of 512";
47+
pub const CONTIGUOUS_ERROR: &str = "ddrescue map of disk is not contiguous";
48+
49+
pub fn contiguous_error() -> ! {
50+
print_error(CONTIGUOUS_ERROR);
51+
process::exit(ExitCode::ParseError as i32);
52+
}
4753

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

‎src/parser.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::error;
22
use std::{ffi::OsString, fmt::Write, fs};
33

44
/// Parses ddrescue map file to dmsetup table
5+
/// Structure of map file can be found [here](https://www.gnu.org/software/ddrescue/manual/ddrescue_manual.html#Mapfile-structure)
56
pub fn parse_map(map_path: &OsString, device_name: &str) -> String {
67
let mut output = String::new();
78
let contents = fs::read_to_string(map_path.clone()).unwrap_or_else(|error| {
@@ -18,6 +19,8 @@ pub fn parse_map(map_path: &OsString, device_name: &str) -> String {
1819
.filter(|s| !s.is_empty() && !s.contains('#'))
1920
.skip(1);
2021

22+
let mut prev_entry = 0;
23+
2124
for line in file_line {
2225
let mut map_line = line.split_ascii_whitespace();
2326
let pos_string = map_line.next().expect(error::PARSE_ERROR).to_string();
@@ -41,6 +44,13 @@ pub fn parse_map(map_path: &OsString, device_name: &str) -> String {
4144
} else {
4245
error::handle_string_write(writeln!(output, "{}", create_error(pos, size)));
4346
}
47+
48+
// Check if sector is contiguous
49+
if pos != prev_entry {
50+
error::contiguous_error();
51+
} else {
52+
prev_entry = pos + size;
53+
}
4454
}
4555

4656
output

0 commit comments

Comments
 (0)
Please sign in to comment.