Fortune for chacha20's current commit: Small blessing − 小吉mmap-feature
parent
38dcccd001
commit
e707df9a12
@ -0,0 +1,110 @@
|
||||
//! Use memory mapping to process the entire stream at once
|
||||
use super::*;
|
||||
|
||||
use std::os::unix::prelude::*;
|
||||
use std::{
|
||||
io,
|
||||
fs,
|
||||
ptr,
|
||||
ops,
|
||||
mem::{
|
||||
self,
|
||||
MaybeUninit,
|
||||
},
|
||||
borrow::BorrowMut,
|
||||
convert::{TryFrom, TryInto,},
|
||||
};
|
||||
use libc::{
|
||||
mmap, munmap, madvise, MAP_FAILED,
|
||||
};
|
||||
use openssl::symm::Crypter;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MapInner
|
||||
{
|
||||
mem: ptr::NonNull<u8>,
|
||||
size: usize
|
||||
}
|
||||
|
||||
impl ops::Drop for MapInner
|
||||
{
|
||||
#[inline]
|
||||
fn drop(&mut self)
|
||||
{
|
||||
unsafe {
|
||||
munmap(self.mem.as_ptr() as *mut _, self.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn raw_file_size(fd: &(impl AsRawFd + ?Sized)) -> io::Result<u64>
|
||||
{
|
||||
use libc::fstat;
|
||||
let mut stat = MaybeUninit::uninit();
|
||||
match unsafe { fstat(fd.as_raw_fd(), stat.as_mut_ptr()) } {
|
||||
0 => match unsafe {stat.assume_init()}.st_size {
|
||||
x if x < 0 => Err(io::Error::new(io::ErrorKind::InvalidInput, format!("File from {} is too large", fd.as_raw_fd()))),
|
||||
x => Ok(x as u64),
|
||||
},
|
||||
_ => Err(io::Error::last_os_error()),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mapped<T: ?Sized>
|
||||
{
|
||||
mem: MapInner,
|
||||
file: T
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)]
|
||||
pub enum MapMode
|
||||
{
|
||||
ReadOnly,
|
||||
ReadWrite,
|
||||
WriteOnly,
|
||||
}
|
||||
//TODO: impl MapMode -> fn as_prot() -> c_int, fn as_flags() -> c_int
|
||||
|
||||
impl<T: AsRawFd> Mapped<T>
|
||||
{
|
||||
pub fn try_new_sized(file: T, size: u64, rw: MapMode) -> io::Result<Self>
|
||||
{
|
||||
todo!("mem: mmap(0, size, rw.prot(), MAP_SHARED (For rw: *Write*), MAP_PRIVATE [TODO: add support for| MAP_HUGE_] (For rw: ReadOnly), file.as_raw_fd(), 0) != MAP_FAILED (TODO: maybe madvise?)")
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn try_new(file: T, rw: MapMode) -> io::Result<Self>
|
||||
{
|
||||
let size = raw_file_size(&file)?;
|
||||
Self::try_new_sized(file, size, rw)
|
||||
}
|
||||
}
|
||||
/*
|
||||
impl<T: AsRawFd> TryFrom<T> for Mapped<T>
|
||||
{
|
||||
type Error = io::Error;
|
||||
|
||||
fn try_from(from: T) -> Result<Self, Self::Error>
|
||||
{
|
||||
Self::try_new(from, raw_file_size(&from)?)
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
fn process_mapped_files<T, U>(mode: &mut Crypter, input: &mut Mapped<T>, output: &mut Mapped<U>) -> io::Result<()>
|
||||
where T: AsRawFd + ?Sized,
|
||||
U: AsRawFd + ?Sized
|
||||
{
|
||||
todo!("mode.update(input.slice(), output.slice()); /* unneeded: mode.finalize(input.slice(), output.slice()) */ ");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_process(mut mode: impl BorrowMut<Crypter>) -> io::Result<io::Result<()>>
|
||||
{
|
||||
let mode = mode.borrow_mut();
|
||||
/*let mstdin = Mapped::try_new(input)?;
|
||||
let mstdout = Mapped::try_new(output)?;*/ //TODO: if failed to map output, but input is successful (TODO: XXX: implement other way around), we can fall back to wrapping output in `Sink`.
|
||||
todo!("Try to map the stdin and stdout streams, if that fails, return Err(last_os_err).");
|
||||
todo!("return Ok(process_mapped_files(mode, mstdin, mstdout, key, iv))")
|
||||
}
|
Loading…
Reference in new issue