2020-06-25 19:58:45 +05:30
|
|
|
use anyhow::Result;
|
2020-06-25 21:20:11 +05:30
|
|
|
use std::fs::OpenOptions;
|
2021-05-04 13:40:20 +05:30
|
|
|
use std::io::{Read, Seek, SeekFrom, Write};
|
2020-06-29 15:19:40 +05:30
|
|
|
use std::path::Path;
|
2020-06-26 12:30:53 +05:30
|
|
|
//use std::os::unix::fs::OpenOptionsExt;
|
2020-06-25 19:58:45 +05:30
|
|
|
|
|
|
|
pub type Sector = u64;
|
|
|
|
|
2020-06-25 21:20:11 +05:30
|
|
|
#[derive(Debug)]
|
2020-06-25 19:58:45 +05:30
|
|
|
pub struct Region {
|
2020-06-25 21:20:11 +05:30
|
|
|
pub src: Sector,
|
|
|
|
pub dest: Sector,
|
|
|
|
pub len: Sector,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn copy_step<W>(file: &mut W, src_byte: u64, dest_byte: u64, len: usize) -> Result<()>
|
|
|
|
where
|
|
|
|
W: Write + Seek + Read,
|
|
|
|
{
|
|
|
|
let mut buf = vec![0; len];
|
|
|
|
file.seek(SeekFrom::Start(src_byte))?;
|
2020-06-30 13:02:04 +05:30
|
|
|
file.read_exact(&mut buf)?;
|
2020-06-25 21:20:11 +05:30
|
|
|
file.seek(SeekFrom::Start(dest_byte))?;
|
|
|
|
file.write_all(&buf)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn copy_region<W>(file: &mut W, r: &Region) -> Result<()>
|
|
|
|
where
|
|
|
|
W: Write + Seek + Read,
|
|
|
|
{
|
|
|
|
const MAX_BYTES: Sector = 1024 * 1024 * 64;
|
|
|
|
|
|
|
|
let src_bytes = r.src * 512;
|
|
|
|
let dest_bytes = r.dest * 512;
|
|
|
|
let len_bytes = r.len * 512;
|
|
|
|
let mut written = 0;
|
|
|
|
while written != len_bytes {
|
|
|
|
let step = u64::min(len_bytes - written, MAX_BYTES);
|
2021-05-04 13:40:20 +05:30
|
|
|
copy_step(
|
|
|
|
file,
|
|
|
|
src_bytes + written,
|
|
|
|
dest_bytes + written,
|
|
|
|
step as usize,
|
|
|
|
)?;
|
2020-06-25 21:20:11 +05:30
|
|
|
written += step;
|
|
|
|
}
|
|
|
|
Ok(())
|
2020-06-25 19:58:45 +05:30
|
|
|
}
|
|
|
|
|
2020-06-29 15:19:40 +05:30
|
|
|
pub fn copy(path: &Path, regions: &[Region]) -> Result<()> {
|
2020-06-25 21:20:11 +05:30
|
|
|
let mut input = OpenOptions::new()
|
|
|
|
.read(true)
|
|
|
|
.write(true)
|
|
|
|
//.custom_flags(libc::O_DIRECT)
|
|
|
|
.open(path)?;
|
|
|
|
|
|
|
|
for r in regions {
|
|
|
|
eprintln!("copying {:?}", r);
|
|
|
|
copy_region(&mut input, r)?;
|
|
|
|
}
|
2020-06-30 13:02:04 +05:30
|
|
|
input.flush()?;
|
2020-06-25 21:20:11 +05:30
|
|
|
|
2020-06-25 19:58:45 +05:30
|
|
|
Ok(())
|
|
|
|
}
|