use guff_sharefiles::*;
use clap::{Arg, App};
use std::io;
use std::io::prelude::*;
use std::io::ErrorKind::*;
use std::fs::{File};
use std::fs::metadata;
use std::convert::TryInto;
use guff::*;
use guff_matrix::*;
use guff_ida::*;
const INFILE : &str = "16m";
fn main() -> io::Result<()> {
let matches = App::new("ida-split")
.version("1.0")
.author("Declan Malone <idablack@users.sourceforge.net>")
.about("Rabin IDA split")
.args_from_usage(
"-r 'Use reference matrix mul'
-f 'Slurp in full 16m + 8 byte file'
-k=[int] 'quorum value'
-n=[int] 'number of shares'
-s 'Use SIMD matrix mul (default)'")
.arg(Arg::with_name("INFILE")
.help("Sets the input file to use")
.required(false)
.index(1))
.get_matches();
let infile = match matches.value_of("INFILE") {
Some(f) => { println!("Using input file: {}", f); f },
_ => { println!("Using default file\n"); INFILE }
};
let k : usize = if let Some(num) = matches.value_of("k") {
num.parse().unwrap()
} else {
8
};
let n : usize = if let Some(num) = matches.value_of("n") {
num.parse().unwrap()
} else {
16
};
let use_ref = matches.is_present("r");
if ! matches.is_present("f") {
eprintln!("Doing block-wise split");
return blockwise_split(infile, k, n, 8192, use_ref)
}
eprintln!("Doing full slurp");
let mut input = File::open(infile)?;
let mut buffer = vec![0; (16384*1024) + 8];
let got = input.read(&mut buffer.as_mut_slice())?;
if got < (16384*1024) + 8 {
eprintln!("Didn't read all of file");
return Ok(())
}
let key = vec![ 1, 2, 3, 4, 5, 6, 7, 8,
9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24];
let field = new_gf8(0x11b, 0x1b);
let cauchy_data = cauchy_matrix(&field, &key, 16, 8);
let mut xform = Matrix
::new(16,8,true);
xform.fill(&cauchy_data);
let mut input = Matrix
::new(8,2048 * 1024 + 1 ,false);
input.fill(&buffer);
let mut output = Matrix
::new(16,2048 * 1024 + 1,true);
if use_ref {
reference_matrix_multiply(&mut xform, &mut input,
&mut output, &field);
} else {
unsafe {
simd_warm_multiply(&mut xform, &mut input, &mut output);
}
}
let data = output.as_slice().chunks(2048 * 1024 + 1);
for (ext, chunk) in data.enumerate() {
let outfile = format!("{}-full.{}", infile, ext + 1);
let mut f = File::create(outfile)?;
f.write(chunk)?;
}
Ok(())
}
fn blockwise_split(infile : &str, k : usize, n : usize,
mut cols : usize, use_ref : bool)
-> io::Result<()> {
let key_range = 1..;
let key = key_range.take(n+k).collect();
let field = new_gf8(0x11b, 0x1b);
let cauchy_data = cauchy_matrix(&field, &key, n, k);
let want_cols = cols; let mut gcd_padding = 0;
if cols % k == 0 {
cols += 1; gcd_padding = k;
}
let mut read_handle = File::open(infile)?;
let file_size = metadata(infile)?.len();
let mut xform = Matrix
::new(n,k,true);
xform.fill(&cauchy_data);
let mut input = Matrix
::new(k,cols ,false);
let mut output = Matrix
::new(n,cols,true);
let cauchy_clone = cauchy_data.clone();
let mut transform_chunks = cauchy_clone.chunks(k);
let mut handles = Vec::with_capacity(n);
for ext in 1..=n {
let outfile = format!("{}-block.{}", infile, ext);
let mut f = File::create(outfile)?;
let w = 1;
let chunk_start = 0;
let chunk_next = file_size.try_into().unwrap();
let large_k = false;
let large_w = false;
let is_final = true;
let xform = true;
let xform_data = transform_chunks.next().unwrap().to_vec();
let header = HeaderV1 {
k, w, chunk_start, chunk_next, large_k, large_w,
is_final, xform, xform_data };
write_sharefile_header(&mut f, &header)?;
handles.push(f);
}
let mut at_eof = false;
loop {
let want_bytes = want_cols * k;
let mut have_bytes = 0;
let mut slice = input.as_mut_slice();
if gcd_padding > 0 {
slice = &mut slice[..want_bytes]
}
while have_bytes < want_bytes {
let result = read_handle.read(&mut slice);
match result {
Err(e) => {
if e.kind() == Interrupted {
continue
} else {
panic!("Some kind of I/O error: {}", e);
}
},
Ok(0) => { at_eof = true; break },
Ok(n) => {
have_bytes += n;
slice = &mut slice[n..];
},
}
}
if use_ref {
reference_matrix_multiply(&mut xform, &mut input,
&mut output, &field);
} else {
unsafe {
simd_warm_multiply(&mut xform, &mut input, &mut output);
}
}
if have_bytes == 0 && at_eof {
eprintln!("File EOF found at even bufsize boundary");
return Ok(())
}
let mut output_cols = want_cols;
if have_bytes > 0 && at_eof {
eprintln!("File EOF with {} bytes in final partial block",
have_bytes);
if have_bytes % k != 0 {
have_bytes += k - 1;
}
output_cols = have_bytes / k;
}
let data = output.as_slice().chunks(cols);
for (ext, chunk) in data.enumerate() {
handles[ext].write(&chunk[..output_cols])?;
}
if at_eof { return Ok(()) }
}
}