1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
use bmap_parser::{Bmap, Discarder, SeekForward};
use flate2::read::GzDecoder;
use sha2::{Digest, Sha256};
use std::env;
use std::fs::File;
use std::io::Result as IOResult;
use std::io::{Error, ErrorKind, Read, Write};
use std::path::PathBuf;
#[derive(Clone, Debug)]
struct OutputMockRange {
offset: u64,
data: Vec<u8>,
}
impl OutputMockRange {
fn new(offset: u64) -> Self {
Self {
offset,
data: Vec::new(),
}
}
fn write(&mut self, data: &[u8]) {
self.data.extend_from_slice(data);
}
fn sha256(&self) -> [u8; 32] {
Sha256::digest(&self.data).into()
}
}
#[derive(Clone, Debug)]
struct OutputMock {
size: u64,
offset: u64,
ranges: Vec<OutputMockRange>,
}
impl OutputMock {
fn new(size: u64) -> Self {
Self {
size,
offset: 0,
ranges: Vec::new(),
}
}
fn add_range(&mut self, offset: u64) -> &mut OutputMockRange {
self.ranges.push(OutputMockRange::new(offset));
self.ranges.last_mut().unwrap()
}
fn sha256(&mut self) -> [u8; 32] {
fn pad(hasher: &mut Sha256, mut topad: u64) {
const ZEROES: [u8; 4096] = [0; 4096];
while topad > 0 {
let len = ZEROES.len() as u64;
let len = len.min(topad);
hasher.update(&ZEROES[0..len as usize]);
topad -= len;
}
}
let mut hasher = Sha256::new();
let mut offset = 0;
for range in self.ranges.iter() {
if offset < range.offset {
pad(&mut hasher, range.offset - offset);
offset = range.offset;
}
hasher.update(&range.data);
offset += range.data.len() as u64;
}
pad(&mut hasher, self.size - offset);
hasher.finalize().into()
}
}
impl Write for OutputMock {
fn write(&mut self, data: &[u8]) -> IOResult<usize> {
let maxsize = self.size as usize;
let range = match self.ranges.last_mut() {
Some(last) if last.offset == self.offset => last,
_ => self.add_range(self.offset),
};
if range.offset as usize + range.data.len() + data.len() > maxsize {
return Err(Error::new(ErrorKind::Other, "Writing outside of space"));
}
range.write(data);
Ok(data.len())
}
fn flush(&mut self) -> IOResult<()> {
Ok(())
}
}
impl SeekForward for OutputMock {
fn seek_forward(&mut self, forward: u64) -> IOResult<()> {
self.offset += if let Some(last) = self.ranges.last() {
last.data.len() as u64 + forward
} else {
forward
};
Ok(())
}
}
fn setup_data(basename: &str) -> (Bmap, impl Read + SeekForward) {
let mut datadir = PathBuf::new();
datadir.push(env::var("CARGO_MANIFEST_DIR").unwrap());
datadir.push("tests/data");
let mut bmapfile = datadir.clone();
bmapfile.push(format!("{}.bmap", basename));
let mut b =
File::open(&bmapfile).unwrap_or_else(|_| panic!("Failed to open bmap file:{:?}", bmapfile));
let mut xml = String::new();
b.read_to_string(&mut xml).unwrap();
let bmap = Bmap::from_xml(&xml).unwrap();
let mut datafile = datadir.clone();
datafile.push(format!("{}.gz", basename));
let g =
File::open(&datafile).unwrap_or_else(|_| panic!("Failed to open data file:{:?}", datafile));
let gz = GzDecoder::new(g);
let gz = Discarder::new(gz);
(bmap, gz)
}
fn sha256_reader<R: Read>(mut reader: R) -> [u8; 32] {
let mut buffer = [0; 4096];
let mut hasher = Sha256::new();
loop {
let r = reader.read(&mut buffer).unwrap();
if r == 0 {
break;
}
hasher.update(&buffer[0..r]);
}
hasher.finalize().into()
}
#[test]
fn copy() {
let (bmap, mut input) = setup_data("test.img");
let mut output = OutputMock::new(bmap.image_size());
}
|