1 //! A cross-platform Rust API for memory mapped buffers.
2 
3 #[cfg(windows)]
4 mod windows;
5 #[cfg(windows)]
6 use crate::windows::file_len;
7 #[cfg(windows)]
8 use crate::windows::MmapInner;
9 
10 #[cfg(unix)]
11 mod unix;
12 #[cfg(unix)]
13 use crate::unix::file_len;
14 #[cfg(unix)]
15 use crate::unix::MmapInner;
16 
17 #[cfg(not(any(unix, windows)))]
18 mod stub;
19 #[cfg(not(any(unix, windows)))]
20 use crate::stub::file_len;
21 #[cfg(not(any(unix, windows)))]
22 use crate::stub::MmapInner;
23 
24 use std::fmt;
25 #[cfg(not(any(unix, windows)))]
26 use std::fs::File;
27 use std::io::{Error, ErrorKind, Result};
28 use std::ops::{Deref, DerefMut};
29 #[cfg(unix)]
30 use std::os::unix::io::{AsRawFd, RawFd};
31 #[cfg(windows)]
32 use std::os::windows::io::{AsRawHandle, RawHandle};
33 use std::slice;
34 use std::usize;
35 
36 #[cfg(not(any(unix, windows)))]
37 pub struct MmapRawDescriptor<'a>(&'a File);
38 
39 #[cfg(unix)]
40 pub struct MmapRawDescriptor(RawFd);
41 
42 #[cfg(windows)]
43 pub struct MmapRawDescriptor(RawHandle);
44 
45 pub trait MmapAsRawDesc {
as_raw_desc(&self) -> MmapRawDescriptor46     fn as_raw_desc(&self) -> MmapRawDescriptor;
47 }
48 
49 #[cfg(not(any(unix, windows)))]
50 impl MmapAsRawDesc for &File {
as_raw_desc(&self) -> MmapRawDescriptor51     fn as_raw_desc(&self) -> MmapRawDescriptor {
52         MmapRawDescriptor(self)
53     }
54 }
55 
56 #[cfg(unix)]
57 impl MmapAsRawDesc for RawFd {
as_raw_desc(&self) -> MmapRawDescriptor58     fn as_raw_desc(&self) -> MmapRawDescriptor {
59         MmapRawDescriptor(*self)
60     }
61 }
62 
63 #[cfg(unix)]
64 impl<'a, T> MmapAsRawDesc for &'a T
65 where
66     T: AsRawFd,
67 {
as_raw_desc(&self) -> MmapRawDescriptor68     fn as_raw_desc(&self) -> MmapRawDescriptor {
69         MmapRawDescriptor(self.as_raw_fd())
70     }
71 }
72 
73 #[cfg(windows)]
74 impl MmapAsRawDesc for RawHandle {
as_raw_desc(&self) -> MmapRawDescriptor75     fn as_raw_desc(&self) -> MmapRawDescriptor {
76         MmapRawDescriptor(*self)
77     }
78 }
79 
80 #[cfg(windows)]
81 impl<'a, T> MmapAsRawDesc for &'a T
82 where
83     T: AsRawHandle,
84 {
as_raw_desc(&self) -> MmapRawDescriptor85     fn as_raw_desc(&self) -> MmapRawDescriptor {
86         MmapRawDescriptor(self.as_raw_handle())
87     }
88 }
89 
90 /// A memory map builder, providing advanced options and flags for specifying memory map behavior.
91 ///
92 /// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a
93 /// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`],
94 /// [`map_copy()`], or [`map_copy_read_only()`].
95 ///
96 /// ## Safety
97 ///
98 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
99 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
100 /// out of process. Applications must consider the risk and take appropriate precautions when
101 /// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g.
102 /// unlinked) files exist but are platform specific and limited.
103 ///
104 /// [`map_anon()`]: MmapOptions::map_anon()
105 /// [`map()`]: MmapOptions::map()
106 /// [`map_mut()`]: MmapOptions::map_mut()
107 /// [`map_exec()`]: MmapOptions::map_exec()
108 /// [`map_copy()`]: MmapOptions::map_copy()
109 /// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only()
110 #[derive(Clone, Debug, Default)]
111 pub struct MmapOptions {
112     offset: u64,
113     len: Option<usize>,
114     stack: bool,
115     populate: bool,
116 }
117 
118 impl MmapOptions {
119     /// Creates a new set of options for configuring and creating a memory map.
120     ///
121     /// # Example
122     ///
123     /// ```
124     /// use memmap2::{MmapMut, MmapOptions};
125     /// # use std::io::Result;
126     ///
127     /// # fn main() -> Result<()> {
128     /// // Create a new memory map builder.
129     /// let mut mmap_options = MmapOptions::new();
130     ///
131     /// // Configure the memory map builder using option setters, then create
132     /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`,
133     /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`:
134     /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?;
135     ///
136     /// // Use the memory map:
137     /// mmap.copy_from_slice(b"...data to copy to the memory map...");
138     /// # Ok(())
139     /// # }
140     /// ```
new() -> MmapOptions141     pub fn new() -> MmapOptions {
142         MmapOptions::default()
143     }
144 
145     /// Configures the memory map to start at byte `offset` from the beginning of the file.
146     ///
147     /// This option has no effect on anonymous memory maps.
148     ///
149     /// By default, the offset is 0.
150     ///
151     /// # Example
152     ///
153     /// ```
154     /// use memmap2::MmapOptions;
155     /// use std::fs::File;
156     ///
157     /// # fn main() -> std::io::Result<()> {
158     /// let mmap = unsafe {
159     ///     MmapOptions::new()
160     ///                 .offset(30)
161     ///                 .map(&File::open("LICENSE-APACHE")?)?
162     /// };
163     /// assert_eq!(&b"Apache License"[..],
164     ///            &mmap[..14]);
165     /// # Ok(())
166     /// # }
167     /// ```
offset(&mut self, offset: u64) -> &mut Self168     pub fn offset(&mut self, offset: u64) -> &mut Self {
169         self.offset = offset;
170         self
171     }
172 
173     /// Configures the created memory mapped buffer to be `len` bytes long.
174     ///
175     /// This option is mandatory for anonymous memory maps.
176     ///
177     /// For file-backed memory maps, the length will default to the file length.
178     ///
179     /// # Example
180     ///
181     /// ```
182     /// use memmap2::MmapOptions;
183     /// use std::fs::File;
184     ///
185     /// # fn main() -> std::io::Result<()> {
186     /// let mmap = unsafe {
187     ///     MmapOptions::new()
188     ///                 .len(9)
189     ///                 .map(&File::open("README.md")?)?
190     /// };
191     /// assert_eq!(&b"# memmap2"[..], &mmap[..]);
192     /// # Ok(())
193     /// # }
194     /// ```
len(&mut self, len: usize) -> &mut Self195     pub fn len(&mut self, len: usize) -> &mut Self {
196         self.len = Some(len);
197         self
198     }
199 
200     /// Returns the configured length, or the length of the provided file.
get_len<T: MmapAsRawDesc>(&self, file: &T) -> Result<usize>201     fn get_len<T: MmapAsRawDesc>(&self, file: &T) -> Result<usize> {
202         self.len.map(Ok).unwrap_or_else(|| {
203             let desc = file.as_raw_desc();
204             let file_len = file_len(desc.0)?;
205 
206             if file_len < self.offset {
207                 return Err(Error::new(
208                     ErrorKind::InvalidData,
209                     "memory map offset is larger than length",
210                 ));
211             }
212             let len = file_len - self.offset;
213 
214             // This check it not relevant on 64bit targets, because usize == u64
215             #[cfg(not(target_pointer_width = "64"))]
216             {
217                 if len > (usize::MAX as u64) {
218                     return Err(Error::new(
219                         ErrorKind::InvalidData,
220                         "memory map length overflows usize",
221                     ));
222                 }
223             }
224 
225             Ok(len as usize)
226         })
227     }
228 
229     /// Configures the anonymous memory map to be suitable for a process or thread stack.
230     ///
231     /// This option corresponds to the `MAP_STACK` flag on Linux. It has no effect on Windows.
232     ///
233     /// This option has no effect on file-backed memory maps.
234     ///
235     /// # Example
236     ///
237     /// ```
238     /// use memmap2::MmapOptions;
239     ///
240     /// # fn main() -> std::io::Result<()> {
241     /// let stack = MmapOptions::new().stack().len(4096).map_anon();
242     /// # Ok(())
243     /// # }
244     /// ```
stack(&mut self) -> &mut Self245     pub fn stack(&mut self) -> &mut Self {
246         self.stack = true;
247         self
248     }
249 
250     /// Populate (prefault) page tables for a mapping.
251     ///
252     /// For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later.
253     ///
254     /// This option corresponds to the `MAP_POPULATE` flag on Linux. It has no effect on Windows.
255     ///
256     /// # Example
257     ///
258     /// ```
259     /// use memmap2::MmapOptions;
260     /// use std::fs::File;
261     ///
262     /// # fn main() -> std::io::Result<()> {
263     /// let file = File::open("LICENSE-MIT")?;
264     ///
265     /// let mmap = unsafe {
266     ///     MmapOptions::new().populate().map(&file)?
267     /// };
268     ///
269     /// assert_eq!(&b"Copyright"[..], &mmap[..9]);
270     /// # Ok(())
271     /// # }
272     /// ```
populate(&mut self) -> &mut Self273     pub fn populate(&mut self) -> &mut Self {
274         self.populate = true;
275         self
276     }
277 
278     /// Creates a read-only memory map backed by a file.
279     ///
280     /// # Errors
281     ///
282     /// This method returns an error when the underlying system call fails, which can happen for a
283     /// variety of reasons, such as when the file is not open with read permissions.
284     ///
285     /// # Example
286     ///
287     /// ```
288     /// use memmap2::MmapOptions;
289     /// use std::fs::File;
290     /// use std::io::Read;
291     ///
292     /// # fn main() -> std::io::Result<()> {
293     /// let mut file = File::open("LICENSE-APACHE")?;
294     ///
295     /// let mut contents = Vec::new();
296     /// file.read_to_end(&mut contents)?;
297     ///
298     /// let mmap = unsafe {
299     ///     MmapOptions::new().map(&file)?
300     /// };
301     ///
302     /// assert_eq!(&contents[..], &mmap[..]);
303     /// # Ok(())
304     /// # }
305     /// ```
map<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>306     pub unsafe fn map<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
307         let desc = file.as_raw_desc();
308 
309         MmapInner::map(self.get_len(&file)?, desc.0, self.offset, self.populate)
310             .map(|inner| Mmap { inner })
311     }
312 
313     /// Creates a readable and executable memory map backed by a file.
314     ///
315     /// # Errors
316     ///
317     /// This method returns an error when the underlying system call fails, which can happen for a
318     /// variety of reasons, such as when the file is not open with read permissions.
map_exec<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>319     pub unsafe fn map_exec<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
320         let desc = file.as_raw_desc();
321 
322         MmapInner::map_exec(self.get_len(&file)?, desc.0, self.offset, self.populate)
323             .map(|inner| Mmap { inner })
324     }
325 
326     /// Creates a writeable memory map backed by a file.
327     ///
328     /// # Errors
329     ///
330     /// This method returns an error when the underlying system call fails, which can happen for a
331     /// variety of reasons, such as when the file is not open with read and write permissions.
332     ///
333     /// # Example
334     ///
335     /// ```
336     /// # extern crate memmap2;
337     /// # extern crate tempdir;
338     /// #
339     /// use std::fs::OpenOptions;
340     /// use std::path::PathBuf;
341     ///
342     /// use memmap2::MmapOptions;
343     /// #
344     /// # fn main() -> std::io::Result<()> {
345     /// # let tempdir = tempdir::TempDir::new("mmap")?;
346     /// let path: PathBuf = /* path to file */
347     /// #   tempdir.path().join("map_mut");
348     /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
349     /// file.set_len(13)?;
350     ///
351     /// let mut mmap = unsafe {
352     ///     MmapOptions::new().map_mut(&file)?
353     /// };
354     ///
355     /// mmap.copy_from_slice(b"Hello, world!");
356     /// # Ok(())
357     /// # }
358     /// ```
map_mut<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut>359     pub unsafe fn map_mut<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut> {
360         let desc = file.as_raw_desc();
361 
362         MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
363             .map(|inner| MmapMut { inner })
364     }
365 
366     /// Creates a copy-on-write memory map backed by a file.
367     ///
368     /// Data written to the memory map will not be visible by other processes,
369     /// and will not be carried through to the underlying file.
370     ///
371     /// # Errors
372     ///
373     /// This method returns an error when the underlying system call fails, which can happen for a
374     /// variety of reasons, such as when the file is not open with writable permissions.
375     ///
376     /// # Example
377     ///
378     /// ```
379     /// use memmap2::MmapOptions;
380     /// use std::fs::File;
381     /// use std::io::Write;
382     ///
383     /// # fn main() -> std::io::Result<()> {
384     /// let file = File::open("LICENSE-APACHE")?;
385     /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? };
386     /// (&mut mmap[..]).write_all(b"Hello, world!")?;
387     /// # Ok(())
388     /// # }
389     /// ```
map_copy<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut>390     pub unsafe fn map_copy<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut> {
391         let desc = file.as_raw_desc();
392 
393         MmapInner::map_copy(self.get_len(&file)?, desc.0, self.offset, self.populate)
394             .map(|inner| MmapMut { inner })
395     }
396 
397     /// Creates a copy-on-write read-only memory map backed by a file.
398     ///
399     /// # Errors
400     ///
401     /// This method returns an error when the underlying system call fails, which can happen for a
402     /// variety of reasons, such as when the file is not open with read permissions.
403     ///
404     /// # Example
405     ///
406     /// ```
407     /// use memmap2::MmapOptions;
408     /// use std::fs::File;
409     /// use std::io::Read;
410     ///
411     /// # fn main() -> std::io::Result<()> {
412     /// let mut file = File::open("README.md")?;
413     ///
414     /// let mut contents = Vec::new();
415     /// file.read_to_end(&mut contents)?;
416     ///
417     /// let mmap = unsafe {
418     ///     MmapOptions::new().map_copy_read_only(&file)?
419     /// };
420     ///
421     /// assert_eq!(&contents[..], &mmap[..]);
422     /// # Ok(())
423     /// # }
424     /// ```
map_copy_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>425     pub unsafe fn map_copy_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
426         let desc = file.as_raw_desc();
427 
428         MmapInner::map_copy_read_only(self.get_len(&file)?, desc.0, self.offset, self.populate)
429             .map(|inner| Mmap { inner })
430     }
431 
432     /// Creates an anonymous memory map.
433     ///
434     /// Note: the memory map length must be configured to be greater than 0 before creating an
435     /// anonymous memory map using `MmapOptions::len()`.
436     ///
437     /// # Errors
438     ///
439     /// This method returns an error when the underlying system call fails.
map_anon(&self) -> Result<MmapMut>440     pub fn map_anon(&self) -> Result<MmapMut> {
441         MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner })
442     }
443 
444     /// Creates a raw memory map.
445     ///
446     /// # Errors
447     ///
448     /// This method returns an error when the underlying system call fails, which can happen for a
449     /// variety of reasons, such as when the file is not open with read and write permissions.
map_raw<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw>450     pub fn map_raw<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw> {
451         let desc = file.as_raw_desc();
452 
453         MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
454             .map(|inner| MmapRaw { inner })
455     }
456 }
457 
458 /// A handle to an immutable memory mapped buffer.
459 ///
460 /// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use
461 /// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable
462 /// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable
463 /// with [`MmapMut::make_read_only()`].
464 ///
465 /// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the
466 /// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File`
467 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
468 /// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped.
469 ///
470 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
471 /// the mapped pages into physical memory) though the details of this are platform specific.
472 ///
473 /// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
474 ///
475 /// ## Safety
476 ///
477 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
478 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
479 /// out of process. Applications must consider the risk and take appropriate precautions when using
480 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
481 /// files exist but are platform specific and limited.
482 ///
483 /// ## Example
484 ///
485 /// ```
486 /// use memmap2::MmapOptions;
487 /// use std::io::Write;
488 /// use std::fs::File;
489 ///
490 /// # fn main() -> std::io::Result<()> {
491 /// let file = File::open("README.md")?;
492 /// let mmap = unsafe { MmapOptions::new().map(&file)? };
493 /// assert_eq!(b"# memmap2", &mmap[0..9]);
494 /// # Ok(())
495 /// # }
496 /// ```
497 ///
498 /// See [`MmapMut`] for the mutable version.
499 ///
500 /// [`map()`]: Mmap::map()
501 pub struct Mmap {
502     inner: MmapInner,
503 }
504 
505 impl Mmap {
506     /// Creates a read-only memory map backed by a file.
507     ///
508     /// This is equivalent to calling `MmapOptions::new().map(file)`.
509     ///
510     /// # Errors
511     ///
512     /// This method returns an error when the underlying system call fails, which can happen for a
513     /// variety of reasons, such as when the file is not open with read permissions.
514     ///
515     /// # Example
516     ///
517     /// ```
518     /// use std::fs::File;
519     /// use std::io::Read;
520     ///
521     /// use memmap2::Mmap;
522     ///
523     /// # fn main() -> std::io::Result<()> {
524     /// let mut file = File::open("LICENSE-APACHE")?;
525     ///
526     /// let mut contents = Vec::new();
527     /// file.read_to_end(&mut contents)?;
528     ///
529     /// let mmap = unsafe { Mmap::map(&file)?  };
530     ///
531     /// assert_eq!(&contents[..], &mmap[..]);
532     /// # Ok(())
533     /// # }
534     /// ```
map<T: MmapAsRawDesc>(file: T) -> Result<Mmap>535     pub unsafe fn map<T: MmapAsRawDesc>(file: T) -> Result<Mmap> {
536         MmapOptions::new().map(file)
537     }
538 
539     /// Transition the memory map to be writable.
540     ///
541     /// If the memory map is file-backed, the file must have been opened with write permissions.
542     ///
543     /// # Errors
544     ///
545     /// This method returns an error when the underlying system call fails, which can happen for a
546     /// variety of reasons, such as when the file is not open with writable permissions.
547     ///
548     /// # Example
549     ///
550     /// ```
551     /// # extern crate memmap2;
552     /// # extern crate tempdir;
553     /// #
554     /// use memmap2::Mmap;
555     /// use std::ops::DerefMut;
556     /// use std::io::Write;
557     /// # use std::fs::OpenOptions;
558     ///
559     /// # fn main() -> std::io::Result<()> {
560     /// # let tempdir = tempdir::TempDir::new("mmap")?;
561     /// let file = /* file opened with write permissions */
562     /// #          OpenOptions::new()
563     /// #                      .read(true)
564     /// #                      .write(true)
565     /// #                      .create(true)
566     /// #                      .open(tempdir.path()
567     /// #                      .join("make_mut"))?;
568     /// # file.set_len(128)?;
569     /// let mmap = unsafe { Mmap::map(&file)? };
570     /// // ... use the read-only memory map ...
571     /// let mut mut_mmap = mmap.make_mut()?;
572     /// mut_mmap.deref_mut().write_all(b"hello, world!")?;
573     /// # Ok(())
574     /// # }
575     /// ```
make_mut(mut self) -> Result<MmapMut>576     pub fn make_mut(mut self) -> Result<MmapMut> {
577         self.inner.make_mut()?;
578         Ok(MmapMut { inner: self.inner })
579     }
580 }
581 
582 #[cfg(feature = "stable_deref_trait")]
583 unsafe impl stable_deref_trait::StableDeref for Mmap {}
584 
585 impl Deref for Mmap {
586     type Target = [u8];
587 
588     #[inline]
deref(&self) -> &[u8]589     fn deref(&self) -> &[u8] {
590         unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
591     }
592 }
593 
594 impl AsRef<[u8]> for Mmap {
595     #[inline]
as_ref(&self) -> &[u8]596     fn as_ref(&self) -> &[u8] {
597         self.deref()
598     }
599 }
600 
601 impl fmt::Debug for Mmap {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result602     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
603         fmt.debug_struct("Mmap")
604             .field("ptr", &self.as_ptr())
605             .field("len", &self.len())
606             .finish()
607     }
608 }
609 
610 /// A handle to a raw memory mapped buffer.
611 ///
612 /// This struct never hands out references to its interior, only raw pointers.
613 /// This can be helpful when creating shared memory maps between untrusted processes.
614 pub struct MmapRaw {
615     inner: MmapInner,
616 }
617 
618 impl MmapRaw {
619     /// Creates a writeable memory map backed by a file.
620     ///
621     /// This is equivalent to calling `MmapOptions::new().map_raw(file)`.
622     ///
623     /// # Errors
624     ///
625     /// This method returns an error when the underlying system call fails, which can happen for a
626     /// variety of reasons, such as when the file is not open with read and write permissions.
map_raw<T: MmapAsRawDesc>(file: T) -> Result<MmapRaw>627     pub fn map_raw<T: MmapAsRawDesc>(file: T) -> Result<MmapRaw> {
628         MmapOptions::new().map_raw(file)
629     }
630 
631     /// Returns a raw pointer to the memory mapped file.
632     ///
633     /// Before dereferencing this pointer, you have to make sure that the file has not been
634     /// truncated since the memory map was created.
635     /// Avoiding this will not introduce memory safety issues in Rust terms,
636     /// but will cause SIGBUS (or equivalent) signal.
637     #[inline]
as_ptr(&self) -> *const u8638     pub fn as_ptr(&self) -> *const u8 {
639         self.inner.ptr()
640     }
641 
642     /// Returns an unsafe mutable pointer to the memory mapped file.
643     ///
644     /// Before dereferencing this pointer, you have to make sure that the file has not been
645     /// truncated since the memory map was created.
646     /// Avoiding this will not introduce memory safety issues in Rust terms,
647     /// but will cause SIGBUS (or equivalent) signal.
648     #[inline]
as_mut_ptr(&self) -> *mut u8649     pub fn as_mut_ptr(&self) -> *mut u8 {
650         self.inner.ptr() as _
651     }
652 
653     /// Returns the length in bytes of the memory map.
654     ///
655     /// Note that truncating the file can cause the length to change (and render this value unusable).
656     #[inline]
len(&self) -> usize657     pub fn len(&self) -> usize {
658         self.inner.len()
659     }
660 }
661 
662 impl fmt::Debug for MmapRaw {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result663     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
664         fmt.debug_struct("MmapRaw")
665             .field("ptr", &self.as_ptr())
666             .field("len", &self.len())
667             .finish()
668     }
669 }
670 
671 /// A handle to a mutable memory mapped buffer.
672 ///
673 /// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous
674 /// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use
675 /// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the
676 /// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default
677 /// options are required.
678 ///
679 /// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the
680 /// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File`
681 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
682 /// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped.
683 ///
684 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
685 /// the mapped pages into physical memory) though the details of this are platform specific.
686 ///
687 /// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
688 ///
689 /// See [`Mmap`] for the immutable version.
690 ///
691 /// ## Safety
692 ///
693 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
694 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
695 /// out of process. Applications must consider the risk and take appropriate precautions when using
696 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
697 /// files exist but are platform specific and limited.
698 pub struct MmapMut {
699     inner: MmapInner,
700 }
701 
702 impl MmapMut {
703     /// Creates a writeable memory map backed by a file.
704     ///
705     /// This is equivalent to calling `MmapOptions::new().map_mut(file)`.
706     ///
707     /// # Errors
708     ///
709     /// This method returns an error when the underlying system call fails, which can happen for a
710     /// variety of reasons, such as when the file is not open with read and write permissions.
711     ///
712     /// # Example
713     ///
714     /// ```
715     /// # extern crate memmap2;
716     /// # extern crate tempdir;
717     /// #
718     /// use std::fs::OpenOptions;
719     /// use std::path::PathBuf;
720     ///
721     /// use memmap2::MmapMut;
722     /// #
723     /// # fn main() -> std::io::Result<()> {
724     /// # let tempdir = tempdir::TempDir::new("mmap")?;
725     /// let path: PathBuf = /* path to file */
726     /// #   tempdir.path().join("map_mut");
727     /// let file = OpenOptions::new()
728     ///                        .read(true)
729     ///                        .write(true)
730     ///                        .create(true)
731     ///                        .open(&path)?;
732     /// file.set_len(13)?;
733     ///
734     /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
735     ///
736     /// mmap.copy_from_slice(b"Hello, world!");
737     /// # Ok(())
738     /// # }
739     /// ```
map_mut<T: MmapAsRawDesc>(file: T) -> Result<MmapMut>740     pub unsafe fn map_mut<T: MmapAsRawDesc>(file: T) -> Result<MmapMut> {
741         MmapOptions::new().map_mut(file)
742     }
743 
744     /// Creates an anonymous memory map.
745     ///
746     /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`.
747     ///
748     /// # Errors
749     ///
750     /// This method returns an error when the underlying system call fails.
map_anon(length: usize) -> Result<MmapMut>751     pub fn map_anon(length: usize) -> Result<MmapMut> {
752         MmapOptions::new().len(length).map_anon()
753     }
754 
755     /// Flushes outstanding memory map modifications to disk.
756     ///
757     /// When this method returns with a non-error result, all outstanding changes to a file-backed
758     /// memory map are guaranteed to be durably stored. The file's metadata (including last
759     /// modification timestamp) may not be updated.
760     ///
761     /// # Example
762     ///
763     /// ```
764     /// # extern crate memmap2;
765     /// # extern crate tempdir;
766     /// #
767     /// use std::fs::OpenOptions;
768     /// use std::io::Write;
769     /// use std::path::PathBuf;
770     ///
771     /// use memmap2::MmapMut;
772     ///
773     /// # fn main() -> std::io::Result<()> {
774     /// # let tempdir = tempdir::TempDir::new("mmap")?;
775     /// let path: PathBuf = /* path to file */
776     /// #   tempdir.path().join("flush");
777     /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
778     /// file.set_len(128)?;
779     ///
780     /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
781     ///
782     /// (&mut mmap[..]).write_all(b"Hello, world!")?;
783     /// mmap.flush()?;
784     /// # Ok(())
785     /// # }
786     /// ```
flush(&self) -> Result<()>787     pub fn flush(&self) -> Result<()> {
788         let len = self.len();
789         self.inner.flush(0, len)
790     }
791 
792     /// Asynchronously flushes outstanding memory map modifications to disk.
793     ///
794     /// This method initiates flushing modified pages to durable storage, but it will not wait for
795     /// the operation to complete before returning. The file's metadata (including last
796     /// modification timestamp) may not be updated.
flush_async(&self) -> Result<()>797     pub fn flush_async(&self) -> Result<()> {
798         let len = self.len();
799         self.inner.flush_async(0, len)
800     }
801 
802     /// Flushes outstanding memory map modifications in the range to disk.
803     ///
804     /// The offset and length must be in the bounds of the memory map.
805     ///
806     /// When this method returns with a non-error result, all outstanding changes to a file-backed
807     /// memory in the range are guaranteed to be durable stored. The file's metadata (including
808     /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
809     /// in the specified range are flushed; other outstanding changes to the memory map may be
810     /// flushed as well.
flush_range(&self, offset: usize, len: usize) -> Result<()>811     pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
812         self.inner.flush(offset, len)
813     }
814 
815     /// Asynchronously flushes outstanding memory map modifications in the range to disk.
816     ///
817     /// The offset and length must be in the bounds of the memory map.
818     ///
819     /// This method initiates flushing modified pages to durable storage, but it will not wait for
820     /// the operation to complete before returning. The file's metadata (including last
821     /// modification timestamp) may not be updated. It is not guaranteed that the only changes
822     /// flushed are those in the specified range; other outstanding changes to the memory map may
823     /// be flushed as well.
flush_async_range(&self, offset: usize, len: usize) -> Result<()>824     pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
825         self.inner.flush_async(offset, len)
826     }
827 
828     /// Returns an immutable version of this memory mapped buffer.
829     ///
830     /// If the memory map is file-backed, the file must have been opened with read permissions.
831     ///
832     /// # Errors
833     ///
834     /// This method returns an error when the underlying system call fails, which can happen for a
835     /// variety of reasons, such as when the file has not been opened with read permissions.
836     ///
837     /// # Example
838     ///
839     /// ```
840     /// # extern crate memmap2;
841     /// #
842     /// use std::io::Write;
843     /// use std::path::PathBuf;
844     ///
845     /// use memmap2::{Mmap, MmapMut};
846     ///
847     /// # fn main() -> std::io::Result<()> {
848     /// let mut mmap = MmapMut::map_anon(128)?;
849     ///
850     /// (&mut mmap[..]).write(b"Hello, world!")?;
851     ///
852     /// let mmap: Mmap = mmap.make_read_only()?;
853     /// # Ok(())
854     /// # }
855     /// ```
make_read_only(mut self) -> Result<Mmap>856     pub fn make_read_only(mut self) -> Result<Mmap> {
857         self.inner.make_read_only()?;
858         Ok(Mmap { inner: self.inner })
859     }
860 
861     /// Transition the memory map to be readable and executable.
862     ///
863     /// If the memory map is file-backed, the file must have been opened with execute permissions.
864     ///
865     /// # Errors
866     ///
867     /// This method returns an error when the underlying system call fails, which can happen for a
868     /// variety of reasons, such as when the file has not been opened with execute permissions.
make_exec(mut self) -> Result<Mmap>869     pub fn make_exec(mut self) -> Result<Mmap> {
870         self.inner.make_exec()?;
871         Ok(Mmap { inner: self.inner })
872     }
873 }
874 
875 #[cfg(feature = "stable_deref_trait")]
876 unsafe impl stable_deref_trait::StableDeref for MmapMut {}
877 
878 impl Deref for MmapMut {
879     type Target = [u8];
880 
881     #[inline]
deref(&self) -> &[u8]882     fn deref(&self) -> &[u8] {
883         unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
884     }
885 }
886 
887 impl DerefMut for MmapMut {
888     #[inline]
deref_mut(&mut self) -> &mut [u8]889     fn deref_mut(&mut self) -> &mut [u8] {
890         unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) }
891     }
892 }
893 
894 impl AsRef<[u8]> for MmapMut {
895     #[inline]
as_ref(&self) -> &[u8]896     fn as_ref(&self) -> &[u8] {
897         self.deref()
898     }
899 }
900 
901 impl AsMut<[u8]> for MmapMut {
902     #[inline]
as_mut(&mut self) -> &mut [u8]903     fn as_mut(&mut self) -> &mut [u8] {
904         self.deref_mut()
905     }
906 }
907 
908 impl fmt::Debug for MmapMut {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result909     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
910         fmt.debug_struct("MmapMut")
911             .field("ptr", &self.as_ptr())
912             .field("len", &self.len())
913             .finish()
914     }
915 }
916 
917 #[cfg(test)]
918 mod test {
919     extern crate tempdir;
920 
921     use std::fs::OpenOptions;
922     use std::io::{Read, Write};
923     #[cfg(unix)]
924     use std::os::unix::io::AsRawFd;
925     #[cfg(windows)]
926     use std::os::windows::fs::OpenOptionsExt;
927 
928     #[cfg(windows)]
929     const GENERIC_ALL: u32 = 0x10000000;
930 
931     use super::{Mmap, MmapMut, MmapOptions};
932 
933     #[test]
map_file()934     fn map_file() {
935         let expected_len = 128;
936         let tempdir = tempdir::TempDir::new("mmap").unwrap();
937         let path = tempdir.path().join("mmap");
938 
939         let file = OpenOptions::new()
940             .read(true)
941             .write(true)
942             .create(true)
943             .open(&path)
944             .unwrap();
945 
946         file.set_len(expected_len as u64).unwrap();
947 
948         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
949         let len = mmap.len();
950         assert_eq!(expected_len, len);
951 
952         let zeros = vec![0; len];
953         let incr: Vec<u8> = (0..len as u8).collect();
954 
955         // check that the mmap is empty
956         assert_eq!(&zeros[..], &mmap[..]);
957 
958         // write values into the mmap
959         (&mut mmap[..]).write_all(&incr[..]).unwrap();
960 
961         // read values back
962         assert_eq!(&incr[..], &mmap[..]);
963     }
964 
965     #[test]
966     #[cfg(unix)]
map_fd()967     fn map_fd() {
968         let expected_len = 128;
969         let tempdir = tempdir::TempDir::new("mmap").unwrap();
970         let path = tempdir.path().join("mmap");
971 
972         let file = OpenOptions::new()
973             .read(true)
974             .write(true)
975             .create(true)
976             .open(&path)
977             .unwrap();
978 
979         file.set_len(expected_len as u64).unwrap();
980 
981         let mut mmap = unsafe { MmapMut::map_mut(file.as_raw_fd()).unwrap() };
982         let len = mmap.len();
983         assert_eq!(expected_len, len);
984 
985         let zeros = vec![0; len];
986         let incr: Vec<u8> = (0..len as u8).collect();
987 
988         // check that the mmap is empty
989         assert_eq!(&zeros[..], &mmap[..]);
990 
991         // write values into the mmap
992         (&mut mmap[..]).write_all(&incr[..]).unwrap();
993 
994         // read values back
995         assert_eq!(&incr[..], &mmap[..]);
996     }
997 
998     /// Checks that "mapping" a 0-length file derefs to an empty slice.
999     #[test]
map_empty_file()1000     fn map_empty_file() {
1001         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1002         let path = tempdir.path().join("mmap");
1003 
1004         let file = OpenOptions::new()
1005             .read(true)
1006             .write(true)
1007             .create(true)
1008             .open(&path)
1009             .unwrap();
1010         let mmap = unsafe { Mmap::map(&file).unwrap() };
1011         assert!(mmap.is_empty());
1012         let mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1013         assert!(mmap.is_empty());
1014     }
1015 
1016     #[test]
map_anon()1017     fn map_anon() {
1018         let expected_len = 128;
1019         let mut mmap = MmapMut::map_anon(expected_len).unwrap();
1020         let len = mmap.len();
1021         assert_eq!(expected_len, len);
1022 
1023         let zeros = vec![0; len];
1024         let incr: Vec<u8> = (0..len as u8).collect();
1025 
1026         // check that the mmap is empty
1027         assert_eq!(&zeros[..], &mmap[..]);
1028 
1029         // write values into the mmap
1030         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1031 
1032         // read values back
1033         assert_eq!(&incr[..], &mmap[..]);
1034     }
1035 
1036     #[test]
map_anon_zero_len()1037     fn map_anon_zero_len() {
1038         assert!(MmapOptions::new().map_anon().unwrap().is_empty())
1039     }
1040 
1041     #[test]
file_write()1042     fn file_write() {
1043         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1044         let path = tempdir.path().join("mmap");
1045 
1046         let mut file = OpenOptions::new()
1047             .read(true)
1048             .write(true)
1049             .create(true)
1050             .open(&path)
1051             .unwrap();
1052         file.set_len(128).unwrap();
1053 
1054         let write = b"abc123";
1055         let mut read = [0u8; 6];
1056 
1057         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1058         (&mut mmap[..]).write_all(write).unwrap();
1059         mmap.flush().unwrap();
1060 
1061         file.read_exact(&mut read).unwrap();
1062         assert_eq!(write, &read);
1063     }
1064 
1065     #[test]
flush_range()1066     fn flush_range() {
1067         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1068         let path = tempdir.path().join("mmap");
1069 
1070         let file = OpenOptions::new()
1071             .read(true)
1072             .write(true)
1073             .create(true)
1074             .open(&path)
1075             .unwrap();
1076         file.set_len(128).unwrap();
1077         let write = b"abc123";
1078 
1079         let mut mmap = unsafe {
1080             MmapOptions::new()
1081                 .offset(2)
1082                 .len(write.len())
1083                 .map_mut(&file)
1084                 .unwrap()
1085         };
1086         (&mut mmap[..]).write_all(write).unwrap();
1087         mmap.flush_async_range(0, write.len()).unwrap();
1088         mmap.flush_range(0, write.len()).unwrap();
1089     }
1090 
1091     #[test]
map_copy()1092     fn map_copy() {
1093         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1094         let path = tempdir.path().join("mmap");
1095 
1096         let mut file = OpenOptions::new()
1097             .read(true)
1098             .write(true)
1099             .create(true)
1100             .open(&path)
1101             .unwrap();
1102         file.set_len(128).unwrap();
1103 
1104         let nulls = b"\0\0\0\0\0\0";
1105         let write = b"abc123";
1106         let mut read = [0u8; 6];
1107 
1108         let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() };
1109 
1110         (&mut mmap[..]).write_all(write).unwrap();
1111         mmap.flush().unwrap();
1112 
1113         // The mmap contains the write
1114         (&mmap[..]).read_exact(&mut read).unwrap();
1115         assert_eq!(write, &read);
1116 
1117         // The file does not contain the write
1118         file.read_exact(&mut read).unwrap();
1119         assert_eq!(nulls, &read);
1120 
1121         // another mmap does not contain the write
1122         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1123         (&mmap2[..]).read_exact(&mut read).unwrap();
1124         assert_eq!(nulls, &read);
1125     }
1126 
1127     #[test]
map_copy_read_only()1128     fn map_copy_read_only() {
1129         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1130         let path = tempdir.path().join("mmap");
1131 
1132         let file = OpenOptions::new()
1133             .read(true)
1134             .write(true)
1135             .create(true)
1136             .open(&path)
1137             .unwrap();
1138         file.set_len(128).unwrap();
1139 
1140         let nulls = b"\0\0\0\0\0\0";
1141         let mut read = [0u8; 6];
1142 
1143         let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() };
1144         (&mmap[..]).read_exact(&mut read).unwrap();
1145         assert_eq!(nulls, &read);
1146 
1147         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1148         (&mmap2[..]).read_exact(&mut read).unwrap();
1149         assert_eq!(nulls, &read);
1150     }
1151 
1152     // 32bit Linux cannot map a file larger than i32, but Windows can.
1153     #[cfg(all(target_os = "linux", target_pointer_width = "32"))]
1154     #[test]
map_offset()1155     fn map_offset() {
1156         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1157         let path = tempdir.path().join("mmap");
1158 
1159         let file = OpenOptions::new()
1160             .read(true)
1161             .write(true)
1162             .create(true)
1163             .open(&path)
1164             .unwrap();
1165 
1166         let offset = u32::max_value() as u64 + 2;
1167         let len = 5432;
1168         file.set_len(offset + len as u64).unwrap();
1169 
1170         let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file) };
1171         assert!(mmap.is_err());
1172     }
1173 
1174     #[cfg(not(all(target_os = "linux", target_pointer_width = "32")))]
1175     #[test]
map_offset()1176     fn map_offset() {
1177         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1178         let path = tempdir.path().join("mmap");
1179 
1180         let file = OpenOptions::new()
1181             .read(true)
1182             .write(true)
1183             .create(true)
1184             .open(&path)
1185             .unwrap();
1186 
1187         let offset = u32::max_value() as u64 + 2;
1188         let len = 5432;
1189         file.set_len(offset + len as u64).unwrap();
1190 
1191         // Check inferred length mmap.
1192         let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() };
1193         assert_eq!(len, mmap.len());
1194 
1195         // Check explicit length mmap.
1196         let mut mmap = unsafe {
1197             MmapOptions::new()
1198                 .offset(offset)
1199                 .len(len)
1200                 .map_mut(&file)
1201                 .unwrap()
1202         };
1203         assert_eq!(len, mmap.len());
1204 
1205         let zeros = vec![0; len];
1206         let incr: Vec<_> = (0..len).map(|i| i as u8).collect();
1207 
1208         // check that the mmap is empty
1209         assert_eq!(&zeros[..], &mmap[..]);
1210 
1211         // write values into the mmap
1212         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1213 
1214         // read values back
1215         assert_eq!(&incr[..], &mmap[..]);
1216     }
1217 
1218     #[test]
index()1219     fn index() {
1220         let mut mmap = MmapMut::map_anon(128).unwrap();
1221         mmap[0] = 42;
1222         assert_eq!(42, mmap[0]);
1223     }
1224 
1225     #[test]
sync_send()1226     fn sync_send() {
1227         let mmap = MmapMut::map_anon(129).unwrap();
1228 
1229         fn is_sync_send<T>(_val: T)
1230         where
1231             T: Sync + Send,
1232         {
1233         }
1234 
1235         is_sync_send(mmap);
1236     }
1237 
1238     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86(mut mmap: MmapMut)1239     fn jit_x86(mut mmap: MmapMut) {
1240         use std::mem;
1241         mmap[0] = 0xB8; // mov eax, 0xAB
1242         mmap[1] = 0xAB;
1243         mmap[2] = 0x00;
1244         mmap[3] = 0x00;
1245         mmap[4] = 0x00;
1246         mmap[5] = 0xC3; // ret
1247 
1248         let mmap = mmap.make_exec().expect("make_exec");
1249 
1250         let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) };
1251         assert_eq!(jitfn(), 0xab);
1252     }
1253 
1254     #[test]
1255     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86_anon()1256     fn jit_x86_anon() {
1257         jit_x86(MmapMut::map_anon(4096).unwrap());
1258     }
1259 
1260     #[test]
1261     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86_file()1262     fn jit_x86_file() {
1263         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1264         let mut options = OpenOptions::new();
1265         #[cfg(windows)]
1266         options.access_mode(GENERIC_ALL);
1267 
1268         let file = options
1269             .read(true)
1270             .write(true)
1271             .create(true)
1272             .open(&tempdir.path().join("jit_x86"))
1273             .expect("open");
1274 
1275         file.set_len(4096).expect("set_len");
1276         jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") });
1277     }
1278 
1279     #[test]
mprotect_file()1280     fn mprotect_file() {
1281         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1282         let path = tempdir.path().join("mmap");
1283 
1284         let mut options = OpenOptions::new();
1285         #[cfg(windows)]
1286         options.access_mode(GENERIC_ALL);
1287 
1288         let mut file = options
1289             .read(true)
1290             .write(true)
1291             .create(true)
1292             .open(&path)
1293             .expect("open");
1294         file.set_len(256_u64).expect("set_len");
1295 
1296         let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") };
1297 
1298         let mmap = mmap.make_read_only().expect("make_read_only");
1299         let mut mmap = mmap.make_mut().expect("make_mut");
1300 
1301         let write = b"abc123";
1302         let mut read = [0u8; 6];
1303 
1304         (&mut mmap[..]).write_all(write).unwrap();
1305         mmap.flush().unwrap();
1306 
1307         // The mmap contains the write
1308         (&mmap[..]).read_exact(&mut read).unwrap();
1309         assert_eq!(write, &read);
1310 
1311         // The file should contain the write
1312         file.read_exact(&mut read).unwrap();
1313         assert_eq!(write, &read);
1314 
1315         // another mmap should contain the write
1316         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1317         (&mmap2[..]).read_exact(&mut read).unwrap();
1318         assert_eq!(write, &read);
1319 
1320         let mmap = mmap.make_exec().expect("make_exec");
1321 
1322         drop(mmap);
1323     }
1324 
1325     #[test]
mprotect_copy()1326     fn mprotect_copy() {
1327         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1328         let path = tempdir.path().join("mmap");
1329 
1330         let mut options = OpenOptions::new();
1331         #[cfg(windows)]
1332         options.access_mode(GENERIC_ALL);
1333 
1334         let mut file = options
1335             .read(true)
1336             .write(true)
1337             .create(true)
1338             .open(&path)
1339             .expect("open");
1340         file.set_len(256_u64).expect("set_len");
1341 
1342         let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") };
1343 
1344         let mmap = mmap.make_read_only().expect("make_read_only");
1345         let mut mmap = mmap.make_mut().expect("make_mut");
1346 
1347         let nulls = b"\0\0\0\0\0\0";
1348         let write = b"abc123";
1349         let mut read = [0u8; 6];
1350 
1351         (&mut mmap[..]).write_all(write).unwrap();
1352         mmap.flush().unwrap();
1353 
1354         // The mmap contains the write
1355         (&mmap[..]).read_exact(&mut read).unwrap();
1356         assert_eq!(write, &read);
1357 
1358         // The file does not contain the write
1359         file.read_exact(&mut read).unwrap();
1360         assert_eq!(nulls, &read);
1361 
1362         // another mmap does not contain the write
1363         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1364         (&mmap2[..]).read_exact(&mut read).unwrap();
1365         assert_eq!(nulls, &read);
1366 
1367         let mmap = mmap.make_exec().expect("make_exec");
1368 
1369         drop(mmap);
1370     }
1371 
1372     #[test]
mprotect_anon()1373     fn mprotect_anon() {
1374         let mmap = MmapMut::map_anon(256).expect("map_mut");
1375 
1376         let mmap = mmap.make_read_only().expect("make_read_only");
1377         let mmap = mmap.make_mut().expect("make_mut");
1378         let mmap = mmap.make_exec().expect("make_exec");
1379         drop(mmap);
1380     }
1381 
1382     #[test]
raw()1383     fn raw() {
1384         let tempdir = tempdir::TempDir::new("mmap").unwrap();
1385         let path = tempdir.path().join("mmapraw");
1386 
1387         let mut options = OpenOptions::new();
1388         let mut file = options
1389             .read(true)
1390             .write(true)
1391             .create(true)
1392             .open(&path)
1393             .expect("open");
1394         file.write_all(b"abc123").unwrap();
1395         let mmap = MmapOptions::new().map_raw(&file).unwrap();
1396         assert_eq!(mmap.len(), 6);
1397         assert!(!mmap.as_ptr().is_null());
1398         assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
1399     }
1400 
1401     /// Something that relies on StableDeref
1402     #[test]
1403     #[cfg(feature = "stable_deref_trait")]
owning_ref()1404     fn owning_ref() {
1405         extern crate owning_ref;
1406 
1407         let mut map = MmapMut::map_anon(128).unwrap();
1408         map[10] = 42;
1409         let owning = owning_ref::OwningRef::new(map);
1410         let sliced = owning.map(|map| &map[10..20]);
1411         assert_eq!(42, sliced[0]);
1412 
1413         let map = sliced.into_owner().make_read_only().unwrap();
1414         let owning = owning_ref::OwningRef::new(map);
1415         let sliced = owning.map(|map| &map[10..20]);
1416         assert_eq!(42, sliced[0]);
1417     }
1418 }
1419