#[cfg(test)]
use std::io::Cursor;
use std::{
cmp::min,
fs::{File, OpenOptions},
io::{self, BufWriter, Seek, SeekFrom, Write},
path::Path,
};
use devicemapper::{Sectors, IEC, SECTOR_SIZE};
use crate::stratis::StratisResult;
pub trait SyncAll: Write {
fn sync_all(&mut self) -> io::Result<()>;
}
impl SyncAll for File {
fn sync_all(&mut self) -> io::Result<()> {
File::sync_all(self)
}
}
#[cfg(test)]
impl<T> SyncAll for Cursor<T>
where
Cursor<T>: Write,
{
fn sync_all(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<T> SyncAll for BufWriter<T>
where
T: SyncAll,
{
fn sync_all(&mut self) -> io::Result<()> {
self.flush()?;
self.get_mut().sync_all()
}
}
fn write_sectors<P: AsRef<Path>>(
path: P,
offset: Sectors,
length: Sectors,
buf: &[u8; SECTOR_SIZE],
) -> StratisResult<()> {
let mut f = BufWriter::with_capacity(
convert_const!(min(u128::from(IEC::Mi), *(length.bytes())), u128, usize),
OpenOptions::new().write(true).open(path)?,
);
f.seek(SeekFrom::Start(convert_int!(*offset.bytes(), u128, u64)?))?;
for _ in 0..*length {
f.write_all(buf)?;
}
f.sync_all()?;
Ok(())
}
pub fn wipe_sectors<P: AsRef<Path>>(
path: P,
offset: Sectors,
length: Sectors,
) -> StratisResult<()> {
write_sectors(path, offset, length, &[0u8; SECTOR_SIZE])
}