diff options
author | Omer Ben-Amram <omerbenamram@gmail.com> | 2019-06-04 00:00:14 +0300 |
---|---|---|
committer | Omer Ben-Amram <omerbenamram@gmail.com> | 2019-06-04 00:00:14 +0300 |
commit | 32cdab569d4d14df589a0e5123b134ea1a16e010 (patch) | |
tree | bb2fec0a8cb740362e3cc4082860c5386eea0150 | |
parent | b3ea99a193d4d7ad9a31a4e188371c867510bb84 (diff) |
fix collisions
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/bin/mft_dump.rs | 42 | ||||
-rw-r--r-- | tests/test_cli.rs | 2 |
4 files changed, 37 insertions, 9 deletions
@@ -5,3 +5,4 @@ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock Cargo.lock +*.rmeta
\ No newline at end of file @@ -26,6 +26,7 @@ num-derive = "0.2" winstructs = "0.2.0" lru = "0.1.15" itertools = "0.8.0" +rand = "0.6.5" # `mft_dump` dependencies simplelog = "0.5.3" diff --git a/src/bin/mft_dump.rs b/src/bin/mft_dump.rs index 28829e3..d24db4f 100644 --- a/src/bin/mft_dump.rs +++ b/src/bin/mft_dump.rs @@ -12,10 +12,12 @@ use mft::csv::FlatMftEntryWithName; use snafu::ErrorCompat; use std::fs::File; +use std::io::Read; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::exit; +use std::fmt::Write as FmtWrite; use std::{fs, io, path}; /// Simple error macro for use inside of internal errors in `MftDump` @@ -242,18 +244,29 @@ impl MftDump { let orig_path_component: String = data_streams_dir .join(&sanitized_path) .to_string_lossy() - .to_string() - .chars() - .take(150) - .collect(); + .to_string(); + // Add some random bits to prevent collisions + let random: [u8; 6] = rand::random(); + let rando_string: String = to_hex_string(&random); + + let truncated: String = orig_path_component.chars().take(150).collect(); let data_stream_path = format!( - "{parent_name}__{stream_number}_{stream_name}.dontrun", - parent_name = orig_path_component, + "{path}__{random}_{stream_number}_{stream_name}.dontrun", + path = truncated, + random = rando_string, stream_number = i, stream_name = name ); + if PathBuf::from(&data_stream_path).exists() { + return err!( + "Tried to override an existing stream {} already exists!\ + This is a bug, please report to github!", + data_stream_path + ); + } + let mut f = File::create(&data_stream_path)?; f.write_all(stream.data())?; } @@ -320,6 +333,18 @@ impl MftDump { } } +fn to_hex_string(bytes: &[u8]) -> String { + let len = bytes.len(); + // Each byte is represented by 2 ascii bytes. + let mut s = String::with_capacity(len * 2); + + for byte in bytes { + write!(s, "{:02X}", byte).expect("Writing to an allocated string cannot fail"); + } + + s +} + // adapter from python version // https://github.com/pallets/werkzeug/blob/9394af646038abf8b59d6f866a1ea5189f6d46b8/src/werkzeug/utils.py#L414 pub fn sanitized(component: &str) -> String { @@ -365,8 +390,9 @@ fn main() { .long("--extract-resident-streams") .short("-e") .takes_value(true) - .help(indoc!("Writes resident data streams to the given directory, resident streams will be named\ - <original_file_path>_<stream_number>/<stream_name>.norun")), + .help(indoc!("Writes resident data streams to the given directory. + Resident streams will be named like - `{path}__<random_bytes>_{stream_number}_{stream_name}.dontrun` + random is added to prevent collisions.")), ) .arg( Arg::with_name("no-confirm-overwrite") diff --git a/tests/test_cli.rs b/tests/test_cli.rs index 0e093b4..b247ad5 100644 --- a/tests/test_cli.rs +++ b/tests/test_cli.rs @@ -58,5 +58,5 @@ fn test_it_exports_resident_streams() { cmd.assert().success(); - assert_eq!(fs::read_dir(d.path()).unwrap().count(), 2146) + assert_eq!(fs::read_dir(d.path()).unwrap().count(), 2142) } |