1 //! A cross-platform Rust API for memory mapped buffers.
3 #![doc(html_root_url = "https://docs.rs/memmap2/0.2.1")]
8 use windows
::MmapInner
;
13 use crate::unix
::MmapInner
;
17 use std
::io
::{Error, ErrorKind, Result}
;
18 use std
::ops
::{Deref, DerefMut}
;
22 /// A memory map builder, providing advanced options and flags for specifying memory map behavior.
24 /// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a
25 /// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`],
26 /// [`map_copy()`], or [`map_copy_read_only()`].
30 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
31 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
32 /// out of process. Applications must consider the risk and take appropriate precautions when
33 /// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g.
34 /// unlinked) files exist but are platform specific and limited.
36 /// [`map_anon()`]: MmapOptions::map_anon()
37 /// [`map()`]: MmapOptions::map()
38 /// [`map_mut()`]: MmapOptions::map_mut()
39 /// [`map_exec()`]: MmapOptions::map_exec()
40 /// [`map_copy()`]: MmapOptions::map_copy()
41 /// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only()
42 #[derive(Clone, Debug, Default)]
43 pub struct MmapOptions
{
50 /// Creates a new set of options for configuring and creating a memory map.
55 /// use memmap2::{MmapMut, MmapOptions};
56 /// # use std::io::Result;
58 /// # fn main() -> Result<()> {
59 /// // Create a new memory map builder.
60 /// let mut mmap_options = MmapOptions::new();
62 /// // Configure the memory map builder using option setters, then create
63 /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`,
64 /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`:
65 /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?;
67 /// // Use the memory map:
68 /// mmap.copy_from_slice(b"...data to copy to the memory map...");
72 pub fn new() -> MmapOptions
{
73 MmapOptions
::default()
76 /// Configures the memory map to start at byte `offset` from the beginning of the file.
78 /// This option has no effect on anonymous memory maps.
80 /// By default, the offset is 0.
85 /// use memmap2::MmapOptions;
86 /// use std::fs::File;
88 /// # fn main() -> std::io::Result<()> {
89 /// let mmap = unsafe {
90 /// MmapOptions::new()
92 /// .map(&File::open("LICENSE-APACHE")?)?
94 /// assert_eq!(&b"Apache License"[..],
99 pub fn offset(&mut self, offset
: u64) -> &mut Self {
100 self.offset
= offset
;
104 /// Configures the created memory mapped buffer to be `len` bytes long.
106 /// This option is mandatory for anonymous memory maps.
108 /// For file-backed memory maps, the length will default to the file length.
113 /// use memmap2::MmapOptions;
114 /// use std::fs::File;
116 /// # fn main() -> std::io::Result<()> {
117 /// let mmap = unsafe {
118 /// MmapOptions::new()
120 /// .map(&File::open("README.md")?)?
122 /// assert_eq!(&b"# memmap2"[..], &mmap[..]);
126 pub fn len(&mut self, len
: usize) -> &mut Self {
127 self.len
= Some(len
);
131 /// Returns the configured length, or the length of the provided file.
132 fn get_len(&self, file
: &File
) -> Result
<usize> {
133 self.len
.map(Ok
).unwrap_or_else(|| {
134 let len
= file
.metadata()?
.len() - self.offset
;
135 if len
> (usize::MAX
as u64) {
136 return Err(Error
::new(
137 ErrorKind
::InvalidData
,
138 "memory map length overflows usize",
145 /// Configures the anonymous memory map to be suitable for a process or thread stack.
147 /// This option corresponds to the `MAP_STACK` flag on Linux.
149 /// This option has no effect on file-backed memory maps.
154 /// use memmap2::MmapOptions;
156 /// # fn main() -> std::io::Result<()> {
157 /// let stack = MmapOptions::new().stack().len(4096).map_anon();
161 pub fn stack(&mut self) -> &mut Self {
166 /// Creates a read-only memory map backed by a file.
170 /// This method returns an error when the underlying system call fails, which can happen for a
171 /// variety of reasons, such as when the file is not open with read permissions.
176 /// use memmap2::MmapOptions;
177 /// use std::fs::File;
178 /// use std::io::Read;
180 /// # fn main() -> std::io::Result<()> {
181 /// let mut file = File::open("LICENSE-APACHE")?;
183 /// let mut contents = Vec::new();
184 /// file.read_to_end(&mut contents)?;
186 /// let mmap = unsafe {
187 /// MmapOptions::new().map(&file)?
190 /// assert_eq!(&contents[..], &mmap[..]);
194 pub unsafe fn map(&self, file
: &File
) -> Result
<Mmap
> {
195 MmapInner
::map(self.get_len(file
)?
, file
, self.offset
).map(|inner
| Mmap { inner: inner }
)
198 /// Creates a readable and executable memory map backed by a file.
202 /// This method returns an error when the underlying system call fails, which can happen for a
203 /// variety of reasons, such as when the file is not open with read permissions.
204 pub unsafe fn map_exec(&self, file
: &File
) -> Result
<Mmap
> {
205 MmapInner
::map_exec(self.get_len(file
)?
, file
, self.offset
)
206 .map(|inner
| Mmap { inner: inner }
)
209 /// Creates a writeable memory map backed by a file.
213 /// This method returns an error when the underlying system call fails, which can happen for a
214 /// variety of reasons, such as when the file is not open with read and write permissions.
219 /// # extern crate memmap2;
220 /// # extern crate tempdir;
222 /// use std::fs::OpenOptions;
223 /// use std::path::PathBuf;
225 /// use memmap2::MmapOptions;
227 /// # fn main() -> std::io::Result<()> {
228 /// # let tempdir = tempdir::TempDir::new("mmap")?;
229 /// let path: PathBuf = /* path to file */
230 /// # tempdir.path().join("map_mut");
231 /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
232 /// file.set_len(13)?;
234 /// let mut mmap = unsafe {
235 /// MmapOptions::new().map_mut(&file)?
238 /// mmap.copy_from_slice(b"Hello, world!");
242 pub unsafe fn map_mut(&self, file
: &File
) -> Result
<MmapMut
> {
243 MmapInner
::map_mut(self.get_len(file
)?
, file
, self.offset
)
244 .map(|inner
| MmapMut { inner: inner }
)
247 /// Creates a copy-on-write memory map backed by a file.
249 /// Data written to the memory map will not be visible by other processes,
250 /// and will not be carried through to the underlying file.
254 /// This method returns an error when the underlying system call fails, which can happen for a
255 /// variety of reasons, such as when the file is not open with writable permissions.
260 /// use memmap2::MmapOptions;
261 /// use std::fs::File;
262 /// use std::io::Write;
264 /// # fn main() -> std::io::Result<()> {
265 /// let file = File::open("LICENSE-APACHE")?;
266 /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? };
267 /// (&mut mmap[..]).write_all(b"Hello, world!")?;
271 pub unsafe fn map_copy(&self, file
: &File
) -> Result
<MmapMut
> {
272 MmapInner
::map_copy(self.get_len(file
)?
, file
, self.offset
)
273 .map(|inner
| MmapMut { inner: inner }
)
276 /// Creates a copy-on-write read-only memory map backed by a file.
280 /// This method returns an error when the underlying system call fails, which can happen for a
281 /// variety of reasons, such as when the file is not open with read permissions.
286 /// use memmap2::MmapOptions;
287 /// use std::fs::File;
288 /// use std::io::Read;
290 /// # fn main() -> std::io::Result<()> {
291 /// let mut file = File::open("README.md")?;
293 /// let mut contents = Vec::new();
294 /// file.read_to_end(&mut contents)?;
296 /// let mmap = unsafe {
297 /// MmapOptions::new().map_copy_read_only(&file)?
300 /// assert_eq!(&contents[..], &mmap[..]);
304 pub unsafe fn map_copy_read_only(&self, file
: &File
) -> Result
<Mmap
> {
305 MmapInner
::map_copy_read_only(self.get_len(file
)?
, file
, self.offset
)
306 .map(|inner
| Mmap { inner: inner }
)
309 /// Creates an anonymous memory map.
311 /// Note: the memory map length must be configured to be greater than 0 before creating an
312 /// anonymous memory map using `MmapOptions::len()`.
316 /// This method returns an error when the underlying system call fails.
317 pub fn map_anon(&self) -> Result
<MmapMut
> {
318 MmapInner
::map_anon(self.len
.unwrap_or(0), self.stack
).map(|inner
| MmapMut { inner: inner }
)
321 /// Creates a raw memory map.
325 /// This method returns an error when the underlying system call fails, which can happen for a
326 /// variety of reasons, such as when the file is not open with read and write permissions.
327 pub fn map_raw(&self, file
: &File
) -> Result
<MmapRaw
> {
328 MmapInner
::map_mut(self.get_len(file
)?
, file
, self.offset
)
329 .map(|inner
| MmapRaw { inner: inner }
)
333 /// A handle to an immutable memory mapped buffer.
335 /// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use
336 /// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable
337 /// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable
338 /// with [`MmapMut::make_read_only()`].
340 /// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the
341 /// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File`
342 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
343 /// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped.
345 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
346 /// the mapped pages into physical memory) though the details of this are platform specific.
348 /// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
352 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
353 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
354 /// out of process. Applications must consider the risk and take appropriate precautions when using
355 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
356 /// files exist but are platform specific and limited.
361 /// use memmap2::MmapOptions;
362 /// use std::io::Write;
363 /// use std::fs::File;
365 /// # fn main() -> std::io::Result<()> {
366 /// let file = File::open("README.md")?;
367 /// let mmap = unsafe { MmapOptions::new().map(&file)? };
368 /// assert_eq!(b"# memmap2", &mmap[0..9]);
373 /// See [`MmapMut`] for the mutable version.
375 /// [`map()`]: Mmap::map()
381 /// Creates a read-only memory map backed by a file.
383 /// This is equivalent to calling `MmapOptions::new().map(file)`.
387 /// This method returns an error when the underlying system call fails, which can happen for a
388 /// variety of reasons, such as when the file is not open with read permissions.
393 /// use std::fs::File;
394 /// use std::io::Read;
396 /// use memmap2::Mmap;
398 /// # fn main() -> std::io::Result<()> {
399 /// let mut file = File::open("LICENSE-APACHE")?;
401 /// let mut contents = Vec::new();
402 /// file.read_to_end(&mut contents)?;
404 /// let mmap = unsafe { Mmap::map(&file)? };
406 /// assert_eq!(&contents[..], &mmap[..]);
410 pub unsafe fn map(file
: &File
) -> Result
<Mmap
> {
411 MmapOptions
::new().map(file
)
414 /// Transition the memory map to be writable.
416 /// If the memory map is file-backed, the file must have been opened with write permissions.
420 /// This method returns an error when the underlying system call fails, which can happen for a
421 /// variety of reasons, such as when the file is not open with writable permissions.
426 /// # extern crate memmap2;
427 /// # extern crate tempdir;
429 /// use memmap2::Mmap;
430 /// use std::ops::DerefMut;
431 /// use std::io::Write;
432 /// # use std::fs::OpenOptions;
434 /// # fn main() -> std::io::Result<()> {
435 /// # let tempdir = tempdir::TempDir::new("mmap")?;
436 /// let file = /* file opened with write permissions */
437 /// # OpenOptions::new()
441 /// # .open(tempdir.path()
442 /// # .join("make_mut"))?;
443 /// # file.set_len(128)?;
444 /// let mmap = unsafe { Mmap::map(&file)? };
445 /// // ... use the read-only memory map ...
446 /// let mut mut_mmap = mmap.make_mut()?;
447 /// mut_mmap.deref_mut().write_all(b"hello, world!")?;
451 pub fn make_mut(mut self) -> Result
<MmapMut
> {
452 self.inner
.make_mut()?
;
453 Ok(MmapMut { inner: self.inner }
)
457 impl Deref
for Mmap
{
461 fn deref(&self) -> &[u8] {
462 unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
466 impl AsRef
<[u8]> for Mmap
{
468 fn as_ref(&self) -> &[u8] {
473 impl fmt
::Debug
for Mmap
{
474 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
475 fmt
.debug_struct("Mmap")
476 .field("ptr", &self.as_ptr())
477 .field("len", &self.len())
482 /// A handle to a raw memory mapped buffer.
484 /// This struct never hands out references to its interior, only raw pointers.
485 /// This can be helpful when creating shared memory maps between untrusted processes.
491 /// Creates a writeable memory map backed by a file.
493 /// This is equivalent to calling `MmapOptions::new().map_raw(file)`.
497 /// This method returns an error when the underlying system call fails, which can happen for a
498 /// variety of reasons, such as when the file is not open with read and write permissions.
499 pub fn map_raw(file
: &File
) -> Result
<MmapRaw
> {
500 MmapOptions
::new().map_raw(file
)
503 /// Returns a raw pointer to the memory mapped file.
507 /// To safely dereference this pointer, you need to make sure that the file has not been
508 /// truncated since the memory map was created.
510 pub fn as_ptr(&self) -> *const u8 { self.inner.ptr() }
512 /// Returns an unsafe mutable pointer to the memory mapped file.
516 /// To safely dereference this pointer, you need to make sure that the file has not been
517 /// truncated since the memory map was created.
519 pub fn as_mut_ptr(&self) -> *mut u8 { self.inner.ptr() as _ }
521 /// Returns the length in bytes of the memory map.
523 /// Note that truncating the file can cause the length to change (and render this value unusable).
525 pub fn len(&self) -> usize { self.inner.len() }
528 impl fmt
::Debug
for MmapRaw
{
529 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
530 fmt
.debug_struct("MmapRaw")
531 .field("ptr", &self.as_ptr())
532 .field("len", &self.len())
537 /// A handle to a mutable memory mapped buffer.
539 /// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous
540 /// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use
541 /// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the
542 /// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default
543 /// options are required.
545 /// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the
546 /// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File`
547 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
548 /// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped.
550 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
551 /// the mapped pages into physical memory) though the details of this are platform specific.
553 /// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
555 /// See [`Mmap`] for the immutable version.
559 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
560 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
561 /// out of process. Applications must consider the risk and take appropriate precautions when using
562 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
563 /// files exist but are platform specific and limited.
569 /// Creates a writeable memory map backed by a file.
571 /// This is equivalent to calling `MmapOptions::new().map_mut(file)`.
575 /// This method returns an error when the underlying system call fails, which can happen for a
576 /// variety of reasons, such as when the file is not open with read and write permissions.
581 /// # extern crate memmap2;
582 /// # extern crate tempdir;
584 /// use std::fs::OpenOptions;
585 /// use std::path::PathBuf;
587 /// use memmap2::MmapMut;
589 /// # fn main() -> std::io::Result<()> {
590 /// # let tempdir = tempdir::TempDir::new("mmap")?;
591 /// let path: PathBuf = /* path to file */
592 /// # tempdir.path().join("map_mut");
593 /// let file = OpenOptions::new()
598 /// file.set_len(13)?;
600 /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
602 /// mmap.copy_from_slice(b"Hello, world!");
606 pub unsafe fn map_mut(file
: &File
) -> Result
<MmapMut
> {
607 MmapOptions
::new().map_mut(file
)
610 /// Creates an anonymous memory map.
612 /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`.
616 /// This method returns an error when the underlying system call fails.
617 pub fn map_anon(length
: usize) -> Result
<MmapMut
> {
618 MmapOptions
::new().len(length
).map_anon()
621 /// Flushes outstanding memory map modifications to disk.
623 /// When this method returns with a non-error result, all outstanding changes to a file-backed
624 /// memory map are guaranteed to be durably stored. The file's metadata (including last
625 /// modification timestamp) may not be updated.
630 /// # extern crate memmap2;
631 /// # extern crate tempdir;
633 /// use std::fs::OpenOptions;
634 /// use std::io::Write;
635 /// use std::path::PathBuf;
637 /// use memmap2::MmapMut;
639 /// # fn main() -> std::io::Result<()> {
640 /// # let tempdir = tempdir::TempDir::new("mmap")?;
641 /// let path: PathBuf = /* path to file */
642 /// # tempdir.path().join("flush");
643 /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
644 /// file.set_len(128)?;
646 /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
648 /// (&mut mmap[..]).write_all(b"Hello, world!")?;
653 pub fn flush(&self) -> Result
<()> {
654 let len
= self.len();
655 self.inner
.flush(0, len
)
658 /// Asynchronously flushes outstanding memory map modifications to disk.
660 /// This method initiates flushing modified pages to durable storage, but it will not wait for
661 /// the operation to complete before returning. The file's metadata (including last
662 /// modification timestamp) may not be updated.
663 pub fn flush_async(&self) -> Result
<()> {
664 let len
= self.len();
665 self.inner
.flush_async(0, len
)
668 /// Flushes outstanding memory map modifications in the range to disk.
670 /// The offset and length must be in the bounds of the memory map.
672 /// When this method returns with a non-error result, all outstanding changes to a file-backed
673 /// memory in the range are guaranteed to be durable stored. The file's metadata (including
674 /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
675 /// in the specified range are flushed; other outstanding changes to the memory map may be
677 pub fn flush_range(&self, offset
: usize, len
: usize) -> Result
<()> {
678 self.inner
.flush(offset
, len
)
681 /// Asynchronously flushes outstanding memory map modifications in the range to disk.
683 /// The offset and length must be in the bounds of the memory map.
685 /// This method initiates flushing modified pages to durable storage, but it will not wait for
686 /// the operation to complete before returning. The file's metadata (including last
687 /// modification timestamp) may not be updated. It is not guaranteed that the only changes
688 /// flushed are those in the specified range; other outstanding changes to the memory map may
689 /// be flushed as well.
690 pub fn flush_async_range(&self, offset
: usize, len
: usize) -> Result
<()> {
691 self.inner
.flush_async(offset
, len
)
694 /// Returns an immutable version of this memory mapped buffer.
696 /// If the memory map is file-backed, the file must have been opened with read permissions.
700 /// This method returns an error when the underlying system call fails, which can happen for a
701 /// variety of reasons, such as when the file has not been opened with read permissions.
706 /// # extern crate memmap2;
708 /// use std::io::Write;
709 /// use std::path::PathBuf;
711 /// use memmap2::{Mmap, MmapMut};
713 /// # fn main() -> std::io::Result<()> {
714 /// let mut mmap = MmapMut::map_anon(128)?;
716 /// (&mut mmap[..]).write(b"Hello, world!")?;
718 /// let mmap: Mmap = mmap.make_read_only()?;
722 pub fn make_read_only(mut self) -> Result
<Mmap
> {
723 self.inner
.make_read_only()?
;
724 Ok(Mmap { inner: self.inner }
)
727 /// Transition the memory map to be readable and executable.
729 /// If the memory map is file-backed, the file must have been opened with execute permissions.
733 /// This method returns an error when the underlying system call fails, which can happen for a
734 /// variety of reasons, such as when the file has not been opened with execute permissions.
735 pub fn make_exec(mut self) -> Result
<Mmap
> {
736 self.inner
.make_exec()?
;
737 Ok(Mmap { inner: self.inner }
)
741 impl Deref
for MmapMut
{
745 fn deref(&self) -> &[u8] {
746 unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
750 impl DerefMut
for MmapMut
{
752 fn deref_mut(&mut self) -> &mut [u8] {
753 unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) }
757 impl AsRef
<[u8]> for MmapMut
{
759 fn as_ref(&self) -> &[u8] {
764 impl AsMut
<[u8]> for MmapMut
{
766 fn as_mut(&mut self) -> &mut [u8] {
771 impl fmt
::Debug
for MmapMut
{
772 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
773 fmt
.debug_struct("MmapMut")
774 .field("ptr", &self.as_ptr())
775 .field("len", &self.len())
782 extern crate tempdir
;
784 use std
::fs
::OpenOptions
;
785 use std
::io
::{Read, Write}
;
787 use std
::os
::windows
::fs
::OpenOptionsExt
;
792 const GENERIC_ALL
: u32 = 0x10000000;
794 use super::{Mmap, MmapMut, MmapOptions}
;
798 let expected_len
= 128;
799 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
800 let path
= tempdir
.path().join("mmap");
802 let file
= OpenOptions
::new()
809 file
.set_len(expected_len
as u64).unwrap();
811 let mut mmap
= unsafe { MmapMut::map_mut(&file).unwrap() }
;
812 let len
= mmap
.len();
813 assert_eq
!(expected_len
, len
);
815 let zeros
= vec
![0; len
];
816 let incr
: Vec
<u8> = (0..len
as u8).collect();
818 // check that the mmap is empty
819 assert_eq
!(&zeros
[..], &mmap
[..]);
821 // write values into the mmap
822 (&mut mmap
[..]).write_all(&incr
[..]).unwrap();
825 assert_eq
!(&incr
[..], &mmap
[..]);
828 /// Checks that a 0-length file will not be mapped.
830 fn map_empty_file() {
831 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
832 let path
= tempdir
.path().join("mmap");
834 let file
= OpenOptions
::new()
840 let mmap
= unsafe { Mmap::map(&file) }
;
841 assert
!(mmap
.is_err());
846 let expected_len
= 128;
847 let mut mmap
= MmapMut
::map_anon(expected_len
).unwrap();
848 let len
= mmap
.len();
849 assert_eq
!(expected_len
, len
);
851 let zeros
= vec
![0; len
];
852 let incr
: Vec
<u8> = (0..len
as u8).collect();
854 // check that the mmap is empty
855 assert_eq
!(&zeros
[..], &mmap
[..]);
857 // write values into the mmap
858 (&mut mmap
[..]).write_all(&incr
[..]).unwrap();
861 assert_eq
!(&incr
[..], &mmap
[..]);
865 fn map_anon_zero_len() {
866 assert
!(MmapOptions
::new().map_anon().is_err())
871 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
872 let path
= tempdir
.path().join("mmap");
874 let mut file
= OpenOptions
::new()
880 file
.set_len(128).unwrap();
882 let write
= b
"abc123";
883 let mut read
= [0u8; 6];
885 let mut mmap
= unsafe { MmapMut::map_mut(&file).unwrap() }
;
886 (&mut mmap
[..]).write_all(write
).unwrap();
887 mmap
.flush().unwrap();
889 file
.read(&mut read
).unwrap();
890 assert_eq
!(write
, &read
);
895 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
896 let path
= tempdir
.path().join("mmap");
898 let file
= OpenOptions
::new()
904 file
.set_len(128).unwrap();
905 let write
= b
"abc123";
907 let mut mmap
= unsafe {
914 (&mut mmap
[..]).write_all(write
).unwrap();
915 mmap
.flush_range(0, write
.len()).unwrap();
920 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
921 let path
= tempdir
.path().join("mmap");
923 let mut file
= OpenOptions
::new()
929 file
.set_len(128).unwrap();
931 let nulls
= b
"\0\0\0\0\0\0";
932 let write
= b
"abc123";
933 let mut read
= [0u8; 6];
935 let mut mmap
= unsafe { MmapOptions::new().map_copy(&file).unwrap() }
;
937 (&mut mmap
[..]).write(write
).unwrap();
938 mmap
.flush().unwrap();
940 // The mmap contains the write
941 (&mmap
[..]).read(&mut read
).unwrap();
942 assert_eq
!(write
, &read
);
944 // The file does not contain the write
945 file
.read(&mut read
).unwrap();
946 assert_eq
!(nulls
, &read
);
948 // another mmap does not contain the write
949 let mmap2
= unsafe { MmapOptions::new().map(&file).unwrap() }
;
950 (&mmap2
[..]).read(&mut read
).unwrap();
951 assert_eq
!(nulls
, &read
);
955 fn map_copy_read_only() {
956 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
957 let path
= tempdir
.path().join("mmap");
959 let file
= OpenOptions
::new()
965 file
.set_len(128).unwrap();
967 let nulls
= b
"\0\0\0\0\0\0";
968 let mut read
= [0u8; 6];
970 let mmap
= unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() }
;
971 (&mmap
[..]).read(&mut read
).unwrap();
972 assert_eq
!(nulls
, &read
);
974 let mmap2
= unsafe { MmapOptions::new().map(&file).unwrap() }
;
975 (&mmap2
[..]).read(&mut read
).unwrap();
976 assert_eq
!(nulls
, &read
);
981 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
982 let path
= tempdir
.path().join("mmap");
984 let file
= OpenOptions
::new()
991 let offset
= u32::max_value() as u64 + 2;
993 file
.set_len(offset
+ len
as u64).unwrap();
995 // Check inferred length mmap.
996 let mmap
= unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() }
;
997 assert_eq
!(len
, mmap
.len());
999 // Check explicit length mmap.
1000 let mut mmap
= unsafe {
1007 assert_eq
!(len
, mmap
.len());
1009 let zeros
= vec
![0; len
];
1010 let incr
: Vec
<_
> = (0..len
).map(|i
| i
as u8).collect();
1012 // check that the mmap is empty
1013 assert_eq
!(&zeros
[..], &mmap
[..]);
1015 // write values into the mmap
1016 (&mut mmap
[..]).write_all(&incr
[..]).unwrap();
1019 assert_eq
!(&incr
[..], &mmap
[..]);
1024 let mut mmap
= MmapMut
::map_anon(128).unwrap();
1026 assert_eq
!(42, mmap
[0]);
1031 let mmap
= Arc
::new(MmapMut
::map_anon(129).unwrap());
1032 thread
::spawn(move || {
1037 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1038 fn jit_x86(mut mmap
: MmapMut
) {
1040 mmap
[0] = 0xB8; // mov eax, 0xAB
1045 mmap
[5] = 0xC3; // ret
1047 let mmap
= mmap
.make_exec().expect("make_exec");
1049 let jitfn
: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) }
;
1050 assert_eq
!(jitfn(), 0xab);
1054 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1056 jit_x86(MmapMut
::map_anon(4096).unwrap());
1060 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1062 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
1063 let mut options
= OpenOptions
::new();
1065 options
.access_mode(GENERIC_ALL
);
1071 .open(&tempdir
.path().join("jit_x86"))
1074 file
.set_len(4096).expect("set_len");
1075 jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") }
);
1079 fn mprotect_file() {
1080 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
1081 let path
= tempdir
.path().join("mmap");
1083 let mut options
= OpenOptions
::new();
1085 options
.access_mode(GENERIC_ALL
);
1087 let mut file
= options
1093 file
.set_len(256 as u64).expect("set_len");
1095 let mmap
= unsafe { MmapMut::map_mut(&file).expect("map_mut") }
;
1097 let mmap
= mmap
.make_read_only().expect("make_read_only");
1098 let mut mmap
= mmap
.make_mut().expect("make_mut");
1100 let write
= b
"abc123";
1101 let mut read
= [0u8; 6];
1103 (&mut mmap
[..]).write(write
).unwrap();
1104 mmap
.flush().unwrap();
1106 // The mmap contains the write
1107 (&mmap
[..]).read(&mut read
).unwrap();
1108 assert_eq
!(write
, &read
);
1110 // The file should contain the write
1111 file
.read(&mut read
).unwrap();
1112 assert_eq
!(write
, &read
);
1114 // another mmap should contain the write
1115 let mmap2
= unsafe { MmapOptions::new().map(&file).unwrap() }
;
1116 (&mmap2
[..]).read(&mut read
).unwrap();
1117 assert_eq
!(write
, &read
);
1119 let mmap
= mmap
.make_exec().expect("make_exec");
1125 fn mprotect_copy() {
1126 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
1127 let path
= tempdir
.path().join("mmap");
1129 let mut options
= OpenOptions
::new();
1131 options
.access_mode(GENERIC_ALL
);
1133 let mut file
= options
1139 file
.set_len(256 as u64).expect("set_len");
1141 let mmap
= unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") }
;
1143 let mmap
= mmap
.make_read_only().expect("make_read_only");
1144 let mut mmap
= mmap
.make_mut().expect("make_mut");
1146 let nulls
= b
"\0\0\0\0\0\0";
1147 let write
= b
"abc123";
1148 let mut read
= [0u8; 6];
1150 (&mut mmap
[..]).write(write
).unwrap();
1151 mmap
.flush().unwrap();
1153 // The mmap contains the write
1154 (&mmap
[..]).read(&mut read
).unwrap();
1155 assert_eq
!(write
, &read
);
1157 // The file does not contain the write
1158 file
.read(&mut read
).unwrap();
1159 assert_eq
!(nulls
, &read
);
1161 // another mmap does not contain the write
1162 let mmap2
= unsafe { MmapOptions::new().map(&file).unwrap() }
;
1163 (&mmap2
[..]).read(&mut read
).unwrap();
1164 assert_eq
!(nulls
, &read
);
1166 let mmap
= mmap
.make_exec().expect("make_exec");
1172 fn mprotect_anon() {
1173 let mmap
= MmapMut
::map_anon(256).expect("map_mut");
1175 let mmap
= mmap
.make_read_only().expect("make_read_only");
1176 let mmap
= mmap
.make_mut().expect("make_mut");
1177 let mmap
= mmap
.make_exec().expect("make_exec");
1183 let tempdir
= tempdir
::TempDir
::new("mmap").unwrap();
1184 let path
= tempdir
.path().join("mmapraw");
1186 let mut options
= OpenOptions
::new();
1187 let mut file
= options
1193 file
.write(b
"abc123").unwrap();
1194 let mmap
= MmapOptions
::new().map_raw(&file
).unwrap();
1195 assert_eq
!(mmap
.len(), 6);
1196 assert
!(!mmap
.as_ptr().is_null());
1197 assert_eq
!(unsafe { std::ptr::read(mmap.as_ptr()) }
, b'a'
);