1 //! Memory mapping helpers.
3 use std
::convert
::TryFrom
;
4 use std
::mem
::MaybeUninit
;
5 use std
::os
::unix
::io
::RawFd
;
6 use std
::{io, mem, ptr}
;
10 use proxmox_lang
::error
::io_err_other
;
12 use crate::error
::{SysError}
;
19 unsafe impl<T
> Send
for Mmap
<T
> where T
: Send {}
20 unsafe impl<T
> Sync
for Mmap
<T
> where T
: Sync {}
23 /// Map a file into memory.
27 /// `fd` must refer to a valid file descriptor.
32 prot
: mman
::ProtFlags
,
33 flags
: mman
::MapFlags
,
34 ) -> io
::Result
<Self> {
35 let byte_len
= count
* mem
::size_of
::<T
>();
36 // libc::size_t vs usize
37 #[allow(clippy::useless_conversion)]
38 let data
= mman
::mmap(
40 libc
::size_t
::try_from(byte_len
).map_err(io_err_other
)?
,
44 libc
::off_t
::try_from(ofs
).map_err(io_err_other
)?
,
46 .map_err(SysError
::into_io_error
)?
;
55 impl<T
> std
::ops
::Deref
for Mmap
<T
> {
59 fn deref(&self) -> &[T
] {
60 unsafe { std::slice::from_raw_parts(self.data, self.len) }
64 impl<T
> std
::ops
::DerefMut
for Mmap
<T
> {
66 fn deref_mut(&mut self) -> &mut [T
] {
67 unsafe { std::slice::from_raw_parts_mut(self.data, self.len) }
71 impl<T
> Drop
for Mmap
<T
> {
74 // In theory this can fail if too many memory mappings are already present and
75 // unmapping a smaller region inside a bigger one, causing it to become split into 2
76 // regions. But then we have bigger problems already anyway, so we'll just ignore this.
78 self.data
as *mut libc
::c_void
,
79 self.len
* mem
::size_of
::<T
>(),
85 impl<'a
, T
> IntoIterator
for &'a Mmap
<T
> {
87 type IntoIter
= <&'a
[T
] as IntoIterator
>::IntoIter
;
89 fn into_iter(self) -> Self::IntoIter
{
90 <&'a
[T
] as IntoIterator
>::into_iter(self)
94 impl<T
> Mmap
<MaybeUninit
<T
>> {
95 /// Converts to `Mmap<T>`.
99 /// It is up to the caller to ensure this is safe, see
100 /// [`MaybeUninit::assume_init`](std::mem::MaybeUninit::assume_init).
101 pub unsafe fn assume_init(self) -> Mmap
<T
> {
103 data
: self.data
as *mut T
,
106 std
::mem
::forget(self);