From 71da5e610f0a2c77af00f18604e9efc1958d3996 Mon Sep 17 00:00:00 2001 From: Avril Date: Wed, 2 Nov 2022 18:21:48 +0000 Subject: [PATCH] Added io::Read/Write impls for `ManagedFD` and `MemoryFile`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for mapped-file's current commit: Small blessing − 小吉 --- Cargo.toml | 2 +- src/file/managed.rs | 4 +- src/file/memory.rs | 4 +- src/file/raw.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a99239f..84b2673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "mapped-file" description = "Construct a memory mapping over any file object" keywords = ["unix", "mmap", "generic", "file", "fd"] -version = "0.0.4" +version = "0.0.5" edition = "2021" repository="https://github.com/notflan/mapped-file" license="MIT" diff --git a/src/file/managed.rs b/src/file/managed.rs index 2b1071b..b9bdb86 100644 --- a/src/file/managed.rs +++ b/src/file/managed.rs @@ -24,8 +24,6 @@ impl Clone for ManagedFD { } } -//TODO: io::Read/io::Write impls for ManagedFD - impl ManagedFD { #[inline] @@ -115,3 +113,5 @@ impl From for std::fs::File } } } + +raw::impl_io_for_fd!(ManagedFD => .0.get()); diff --git a/src/file/memory.rs b/src/file/memory.rs index 8702a8c..9dfbba2 100644 --- a/src/file/memory.rs +++ b/src/file/memory.rs @@ -79,7 +79,7 @@ impl ops::Deref for NamedMemoryFile } } -//TODO: impl `MemoryFile` (memfd_create() fd wrapper) +//impl `MemoryFile` (memfd_create() fd wrapper) impl MemoryFile { /// Create a new, empty, memory file with no name and no flags. @@ -234,4 +234,4 @@ impl From for std::fs::File } } -//TODO: io::Read/io::Write impls for MemoryFile +raw::impl_io_for_fd!(MemoryFile => .0.as_raw_fd()); diff --git a/src/file/raw.rs b/src/file/raw.rs index 3e0f32a..0aa1c0c 100644 --- a/src/file/raw.rs +++ b/src/file/raw.rs @@ -117,3 +117,93 @@ impl From for NonNegativeI32 } } +/// Implements `io::Read` and `io::Write` for a type that implements an accessor for a raw file-descriptor. +/// +/// Usage: +/// ```no_compile +/// struct HasFd(UnmanagedFD); +/// impl_io_for_fd(HasFd => .0); +/// ``` +macro_rules! impl_io_for_fd { + ($type:ty => .$($fd_path:tt)+) => { + const _:() = { + use std::io; + #[inline(always)] + fn check_error() -> bool + { + use libc::{ + EINTR, + __errno_location, + }; + match unsafe { *__errno_location() } { + EINTR => true, + _ => false, + } + } + + impl io::Write for $type + { + fn write(&mut self, buf: &[u8]) -> io::Result { + match unsafe { libc::write(self.$($fd_path)+, buf.as_ptr() as *const _, buf.len()) } { + -1 => Err(io::Error::last_os_error()), + n => Ok(n as usize) + } + } + fn write_all(&mut self, mut buf: &[u8]) -> io::Result<()> { + + loop { + buf = match buf { + [] => break Ok(()), + buf => { + match unsafe{ libc::write(self.$($fd_path)+, buf.as_ptr() as *const _, buf.len()) } { + -1 if check_error() => { + return Err(io::Error::last_os_error()); + }, + -1 => continue, + 0 => return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "write returned 0")), + n => &buf[(n as usize)..], + } + }, + }; + } + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + impl io::Read for $type + { + fn read(&mut self, buf: &mut [u8]) -> io::Result + { + match unsafe { libc::read(self.$($fd_path)+, buf.as_mut_ptr() as *mut _, buf.len()) } { + -1 => Err(io::Error::last_os_error()), + n => Ok(n as usize), + } + } + fn read_exact(&mut self, mut buf: &mut [u8]) -> io::Result<()> + { + loop { + let n = match &mut buf { + [] => break Ok(()), + buf => { + match unsafe { libc::read(self.$($fd_path)+, (**buf).as_mut_ptr() as *mut libc::c_void, buf.len()) } { + -1 if check_error() => { + return Err(io::Error::last_os_error()); + }, + -1 => continue, + 0 => return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "read returned 0")), + n => n as usize, + } + } + }; + buf = &mut buf[n..]; + } + } + } + }; + }; +} +pub(super) use impl_io_for_fd;