1 //! A cross-platform Rust API for memory mapped buffers.
2 //!
3 //! The core functionality is provided by either [`Mmap`] or [`MmapMut`],
4 //! which correspond to mapping a [`File`] to a [`&[u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
5 //! or [`&mut [u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
6 //! respectively. Both function by dereferencing to a slice, allowing the
7 //! [`Mmap`]/[`MmapMut`] to be used in the same way you would the equivalent slice
8 //! types.
9 //!
10 //! [`File`]: std::fs::File
11 //!
12 //! # Examples
13 //!
14 //! For simple cases [`Mmap`] can be used directly:
15 //!
16 //! ```
17 //! use std::fs::File;
18 //! use std::io::Read;
19 //!
20 //! use memmap2::Mmap;
21 //!
22 //! # fn main() -> std::io::Result<()> {
23 //! let mut file = File::open("LICENSE-APACHE")?;
24 //!
25 //! let mut contents = Vec::new();
26 //! file.read_to_end(&mut contents)?;
27 //!
28 //! let mmap = unsafe { Mmap::map(&file)?  };
29 //!
30 //! assert_eq!(&contents[..], &mmap[..]);
31 //! # Ok(())
32 //! # }
33 //! ```
34 //!
35 //! However for cases which require configuration of the mapping, then
36 //! you can use [`MmapOptions`] in order to further configure a mapping
37 //! before you create it.
38 
39 #![allow(clippy::len_without_is_empty, clippy::missing_safety_doc)]
40 
41 #[cfg_attr(unix, path = "unix.rs")]
42 #[cfg_attr(windows, path = "windows.rs")]
43 #[cfg_attr(not(any(unix, windows)), path = "stub.rs")]
44 mod os;
45 use crate::os::{file_len, MmapInner};
46 
47 #[cfg(unix)]
48 mod advice;
49 #[cfg(unix)]
50 pub use crate::advice::Advice;
51 
52 use std::fmt;
53 #[cfg(not(any(unix, windows)))]
54 use std::fs::File;
55 use std::io::{Error, ErrorKind, Result};
56 use std::isize;
57 use std::mem;
58 use std::ops::{Deref, DerefMut};
59 #[cfg(unix)]
60 use std::os::unix::io::{AsRawFd, RawFd};
61 #[cfg(windows)]
62 use std::os::windows::io::{AsRawHandle, RawHandle};
63 use std::slice;
64 
65 #[cfg(not(any(unix, windows)))]
66 pub struct MmapRawDescriptor<'a>(&'a File);
67 
68 #[cfg(unix)]
69 pub struct MmapRawDescriptor(RawFd);
70 
71 #[cfg(windows)]
72 pub struct MmapRawDescriptor(RawHandle);
73 
74 pub trait MmapAsRawDesc {
as_raw_desc(&self) -> MmapRawDescriptor75     fn as_raw_desc(&self) -> MmapRawDescriptor;
76 }
77 
78 #[cfg(not(any(unix, windows)))]
79 impl MmapAsRawDesc for &File {
as_raw_desc(&self) -> MmapRawDescriptor80     fn as_raw_desc(&self) -> MmapRawDescriptor {
81         MmapRawDescriptor(self)
82     }
83 }
84 
85 #[cfg(unix)]
86 impl MmapAsRawDesc for RawFd {
as_raw_desc(&self) -> MmapRawDescriptor87     fn as_raw_desc(&self) -> MmapRawDescriptor {
88         MmapRawDescriptor(*self)
89     }
90 }
91 
92 #[cfg(unix)]
93 impl<'a, T> MmapAsRawDesc for &'a T
94 where
95     T: AsRawFd,
96 {
as_raw_desc(&self) -> MmapRawDescriptor97     fn as_raw_desc(&self) -> MmapRawDescriptor {
98         MmapRawDescriptor(self.as_raw_fd())
99     }
100 }
101 
102 #[cfg(windows)]
103 impl MmapAsRawDesc for RawHandle {
as_raw_desc(&self) -> MmapRawDescriptor104     fn as_raw_desc(&self) -> MmapRawDescriptor {
105         MmapRawDescriptor(*self)
106     }
107 }
108 
109 #[cfg(windows)]
110 impl<'a, T> MmapAsRawDesc for &'a T
111 where
112     T: AsRawHandle,
113 {
as_raw_desc(&self) -> MmapRawDescriptor114     fn as_raw_desc(&self) -> MmapRawDescriptor {
115         MmapRawDescriptor(self.as_raw_handle())
116     }
117 }
118 
119 /// A memory map builder, providing advanced options and flags for specifying memory map behavior.
120 ///
121 /// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a
122 /// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`],
123 /// [`map_copy()`], or [`map_copy_read_only()`].
124 ///
125 /// ## Safety
126 ///
127 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
128 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
129 /// out of process. Applications must consider the risk and take appropriate precautions when
130 /// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g.
131 /// unlinked) files exist but are platform specific and limited.
132 ///
133 /// [`map_anon()`]: MmapOptions::map_anon()
134 /// [`map()`]: MmapOptions::map()
135 /// [`map_mut()`]: MmapOptions::map_mut()
136 /// [`map_exec()`]: MmapOptions::map_exec()
137 /// [`map_copy()`]: MmapOptions::map_copy()
138 /// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only()
139 #[derive(Clone, Debug, Default)]
140 pub struct MmapOptions {
141     offset: u64,
142     len: Option<usize>,
143     stack: bool,
144     populate: bool,
145 }
146 
147 impl MmapOptions {
148     /// Creates a new set of options for configuring and creating a memory map.
149     ///
150     /// # Example
151     ///
152     /// ```
153     /// use memmap2::{MmapMut, MmapOptions};
154     /// # use std::io::Result;
155     ///
156     /// # fn main() -> Result<()> {
157     /// // Create a new memory map builder.
158     /// let mut mmap_options = MmapOptions::new();
159     ///
160     /// // Configure the memory map builder using option setters, then create
161     /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`,
162     /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`:
163     /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?;
164     ///
165     /// // Use the memory map:
166     /// mmap.copy_from_slice(b"...data to copy to the memory map...");
167     /// # Ok(())
168     /// # }
169     /// ```
new() -> MmapOptions170     pub fn new() -> MmapOptions {
171         MmapOptions::default()
172     }
173 
174     /// Configures the memory map to start at byte `offset` from the beginning of the file.
175     ///
176     /// This option has no effect on anonymous memory maps.
177     ///
178     /// By default, the offset is 0.
179     ///
180     /// # Example
181     ///
182     /// ```
183     /// use memmap2::MmapOptions;
184     /// use std::fs::File;
185     ///
186     /// # fn main() -> std::io::Result<()> {
187     /// let mmap = unsafe {
188     ///     MmapOptions::new()
189     ///                 .offset(30)
190     ///                 .map(&File::open("LICENSE-APACHE")?)?
191     /// };
192     /// assert_eq!(&b"Apache License"[..],
193     ///            &mmap[..14]);
194     /// # Ok(())
195     /// # }
196     /// ```
offset(&mut self, offset: u64) -> &mut Self197     pub fn offset(&mut self, offset: u64) -> &mut Self {
198         self.offset = offset;
199         self
200     }
201 
202     /// Configures the created memory mapped buffer to be `len` bytes long.
203     ///
204     /// This option is mandatory for anonymous memory maps.
205     ///
206     /// For file-backed memory maps, the length will default to the file length.
207     ///
208     /// # Example
209     ///
210     /// ```
211     /// use memmap2::MmapOptions;
212     /// use std::fs::File;
213     ///
214     /// # fn main() -> std::io::Result<()> {
215     /// let mmap = unsafe {
216     ///     MmapOptions::new()
217     ///                 .len(9)
218     ///                 .map(&File::open("README.md")?)?
219     /// };
220     /// assert_eq!(&b"# memmap2"[..], &mmap[..]);
221     /// # Ok(())
222     /// # }
223     /// ```
len(&mut self, len: usize) -> &mut Self224     pub fn len(&mut self, len: usize) -> &mut Self {
225         self.len = Some(len);
226         self
227     }
228 
229     /// Returns the configured length, or the length of the provided file.
get_len<T: MmapAsRawDesc>(&self, file: &T) -> Result<usize>230     fn get_len<T: MmapAsRawDesc>(&self, file: &T) -> Result<usize> {
231         self.len.map(Ok).unwrap_or_else(|| {
232             let desc = file.as_raw_desc();
233             let file_len = file_len(desc.0)?;
234 
235             if file_len < self.offset {
236                 return Err(Error::new(
237                     ErrorKind::InvalidData,
238                     "memory map offset is larger than length",
239                 ));
240             }
241             let len = file_len - self.offset;
242 
243             // Rust's slice cannot be larger than isize::MAX.
244             // See https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html
245             //
246             // This is not a problem on 64-bit targets, but on 32-bit one
247             // having a file or an anonymous mapping larger than 2GB is quite normal
248             // and we have to prevent it.
249             //
250             // The code below is essentially the same as in Rust's std:
251             // https://github.com/rust-lang/rust/blob/db78ab70a88a0a5e89031d7ee4eccec835dcdbde/library/alloc/src/raw_vec.rs#L495
252             if mem::size_of::<usize>() < 8 && len > isize::MAX as u64 {
253                 return Err(Error::new(
254                     ErrorKind::InvalidData,
255                     "memory map length overflows isize",
256                 ));
257             }
258 
259             Ok(len as usize)
260         })
261     }
262 
263     /// Configures the anonymous memory map to be suitable for a process or thread stack.
264     ///
265     /// This option corresponds to the `MAP_STACK` flag on Linux. It has no effect on Windows.
266     ///
267     /// This option has no effect on file-backed memory maps.
268     ///
269     /// # Example
270     ///
271     /// ```
272     /// use memmap2::MmapOptions;
273     ///
274     /// # fn main() -> std::io::Result<()> {
275     /// let stack = MmapOptions::new().stack().len(4096).map_anon();
276     /// # Ok(())
277     /// # }
278     /// ```
stack(&mut self) -> &mut Self279     pub fn stack(&mut self) -> &mut Self {
280         self.stack = true;
281         self
282     }
283 
284     /// Populate (prefault) page tables for a mapping.
285     ///
286     /// For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later.
287     ///
288     /// This option corresponds to the `MAP_POPULATE` flag on Linux. It has no effect on Windows.
289     ///
290     /// # Example
291     ///
292     /// ```
293     /// use memmap2::MmapOptions;
294     /// use std::fs::File;
295     ///
296     /// # fn main() -> std::io::Result<()> {
297     /// let file = File::open("LICENSE-MIT")?;
298     ///
299     /// let mmap = unsafe {
300     ///     MmapOptions::new().populate().map(&file)?
301     /// };
302     ///
303     /// assert_eq!(&b"Copyright"[..], &mmap[..9]);
304     /// # Ok(())
305     /// # }
306     /// ```
populate(&mut self) -> &mut Self307     pub fn populate(&mut self) -> &mut Self {
308         self.populate = true;
309         self
310     }
311 
312     /// Creates a read-only memory map backed by a file.
313     ///
314     /// # Errors
315     ///
316     /// This method returns an error when the underlying system call fails, which can happen for a
317     /// variety of reasons, such as when the file is not open with read permissions.
318     ///
319     /// # Example
320     ///
321     /// ```
322     /// use memmap2::MmapOptions;
323     /// use std::fs::File;
324     /// use std::io::Read;
325     ///
326     /// # fn main() -> std::io::Result<()> {
327     /// let mut file = File::open("LICENSE-APACHE")?;
328     ///
329     /// let mut contents = Vec::new();
330     /// file.read_to_end(&mut contents)?;
331     ///
332     /// let mmap = unsafe {
333     ///     MmapOptions::new().map(&file)?
334     /// };
335     ///
336     /// assert_eq!(&contents[..], &mmap[..]);
337     /// # Ok(())
338     /// # }
339     /// ```
map<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>340     pub unsafe fn map<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
341         let desc = file.as_raw_desc();
342 
343         MmapInner::map(self.get_len(&file)?, desc.0, self.offset, self.populate)
344             .map(|inner| Mmap { inner })
345     }
346 
347     /// Creates a readable and executable memory map backed by a file.
348     ///
349     /// # Errors
350     ///
351     /// This method returns an error when the underlying system call fails, which can happen for a
352     /// variety of reasons, such as when the file is not open with read permissions.
map_exec<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>353     pub unsafe fn map_exec<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
354         let desc = file.as_raw_desc();
355 
356         MmapInner::map_exec(self.get_len(&file)?, desc.0, self.offset, self.populate)
357             .map(|inner| Mmap { inner })
358     }
359 
360     /// Creates a writeable memory map backed by a file.
361     ///
362     /// # Errors
363     ///
364     /// This method returns an error when the underlying system call fails, which can happen for a
365     /// variety of reasons, such as when the file is not open with read and write permissions.
366     ///
367     /// # Example
368     ///
369     /// ```
370     /// # extern crate memmap2;
371     /// # extern crate tempfile;
372     /// #
373     /// use std::fs::OpenOptions;
374     /// use std::path::PathBuf;
375     ///
376     /// use memmap2::MmapOptions;
377     /// #
378     /// # fn main() -> std::io::Result<()> {
379     /// # let tempdir = tempfile::tempdir()?;
380     /// let path: PathBuf = /* path to file */
381     /// #   tempdir.path().join("map_mut");
382     /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
383     /// file.set_len(13)?;
384     ///
385     /// let mut mmap = unsafe {
386     ///     MmapOptions::new().map_mut(&file)?
387     /// };
388     ///
389     /// mmap.copy_from_slice(b"Hello, world!");
390     /// # Ok(())
391     /// # }
392     /// ```
map_mut<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut>393     pub unsafe fn map_mut<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut> {
394         let desc = file.as_raw_desc();
395 
396         MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
397             .map(|inner| MmapMut { inner })
398     }
399 
400     /// Creates a copy-on-write memory map backed by a file.
401     ///
402     /// Data written to the memory map will not be visible by other processes,
403     /// and will not be carried through to the underlying file.
404     ///
405     /// # Errors
406     ///
407     /// This method returns an error when the underlying system call fails, which can happen for a
408     /// variety of reasons, such as when the file is not open with writable permissions.
409     ///
410     /// # Example
411     ///
412     /// ```
413     /// use memmap2::MmapOptions;
414     /// use std::fs::File;
415     /// use std::io::Write;
416     ///
417     /// # fn main() -> std::io::Result<()> {
418     /// let file = File::open("LICENSE-APACHE")?;
419     /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? };
420     /// (&mut mmap[..]).write_all(b"Hello, world!")?;
421     /// # Ok(())
422     /// # }
423     /// ```
map_copy<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut>424     pub unsafe fn map_copy<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapMut> {
425         let desc = file.as_raw_desc();
426 
427         MmapInner::map_copy(self.get_len(&file)?, desc.0, self.offset, self.populate)
428             .map(|inner| MmapMut { inner })
429     }
430 
431     /// Creates a copy-on-write read-only memory map backed by a file.
432     ///
433     /// # Errors
434     ///
435     /// This method returns an error when the underlying system call fails, which can happen for a
436     /// variety of reasons, such as when the file is not open with read permissions.
437     ///
438     /// # Example
439     ///
440     /// ```
441     /// use memmap2::MmapOptions;
442     /// use std::fs::File;
443     /// use std::io::Read;
444     ///
445     /// # fn main() -> std::io::Result<()> {
446     /// let mut file = File::open("README.md")?;
447     ///
448     /// let mut contents = Vec::new();
449     /// file.read_to_end(&mut contents)?;
450     ///
451     /// let mmap = unsafe {
452     ///     MmapOptions::new().map_copy_read_only(&file)?
453     /// };
454     ///
455     /// assert_eq!(&contents[..], &mmap[..]);
456     /// # Ok(())
457     /// # }
458     /// ```
map_copy_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap>459     pub unsafe fn map_copy_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<Mmap> {
460         let desc = file.as_raw_desc();
461 
462         MmapInner::map_copy_read_only(self.get_len(&file)?, desc.0, self.offset, self.populate)
463             .map(|inner| Mmap { inner })
464     }
465 
466     /// Creates an anonymous memory map.
467     ///
468     /// The memory map length should be configured using [`MmapOptions::len()`]
469     /// before creating an anonymous memory map, otherwise a zero-length mapping
470     /// will be crated.
471     ///
472     /// # Errors
473     ///
474     /// This method returns an error when the underlying system call fails or
475     /// when `len > isize::MAX`.
map_anon(&self) -> Result<MmapMut>476     pub fn map_anon(&self) -> Result<MmapMut> {
477         let len = self.len.unwrap_or(0);
478 
479         // See get_len() for details.
480         if mem::size_of::<usize>() < 8 && len > isize::MAX as usize {
481             return Err(Error::new(
482                 ErrorKind::InvalidData,
483                 "memory map length overflows isize",
484             ));
485         }
486 
487         MmapInner::map_anon(len, self.stack, self.populate).map(|inner| MmapMut { inner })
488     }
489 
490     /// Creates a raw memory map.
491     ///
492     /// # Errors
493     ///
494     /// This method returns an error when the underlying system call fails, which can happen for a
495     /// 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>496     pub fn map_raw<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw> {
497         let desc = file.as_raw_desc();
498 
499         MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
500             .map(|inner| MmapRaw { inner })
501     }
502 
503     /// Creates a read-only raw memory map
504     ///
505     /// This is primarily useful to avoid intermediate `Mmap` instances when
506     /// read-only access to files modified elsewhere are required.
507     ///
508     /// # Errors
509     ///
510     /// This method returns an error when the underlying system call fails
map_raw_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw>511     pub fn map_raw_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw> {
512         let desc = file.as_raw_desc();
513 
514         MmapInner::map(self.get_len(&file)?, desc.0, self.offset, self.populate)
515             .map(|inner| MmapRaw { inner })
516     }
517 }
518 
519 /// A handle to an immutable memory mapped buffer.
520 ///
521 /// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use
522 /// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable
523 /// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable
524 /// with [`MmapMut::make_read_only()`].
525 ///
526 /// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the
527 /// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File`
528 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
529 /// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped.
530 ///
531 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
532 /// the mapped pages into physical memory) though the details of this are platform specific.
533 ///
534 /// `Mmap` is [`Sync`] and [`Send`].
535 ///
536 /// ## Safety
537 ///
538 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
539 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
540 /// out of process. Applications must consider the risk and take appropriate precautions when using
541 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
542 /// files exist but are platform specific and limited.
543 ///
544 /// ## Example
545 ///
546 /// ```
547 /// use memmap2::MmapOptions;
548 /// use std::io::Write;
549 /// use std::fs::File;
550 ///
551 /// # fn main() -> std::io::Result<()> {
552 /// let file = File::open("README.md")?;
553 /// let mmap = unsafe { MmapOptions::new().map(&file)? };
554 /// assert_eq!(b"# memmap2", &mmap[0..9]);
555 /// # Ok(())
556 /// # }
557 /// ```
558 ///
559 /// See [`MmapMut`] for the mutable version.
560 ///
561 /// [`map()`]: Mmap::map()
562 pub struct Mmap {
563     inner: MmapInner,
564 }
565 
566 impl Mmap {
567     /// Creates a read-only memory map backed by a file.
568     ///
569     /// This is equivalent to calling `MmapOptions::new().map(file)`.
570     ///
571     /// # Errors
572     ///
573     /// This method returns an error when the underlying system call fails, which can happen for a
574     /// variety of reasons, such as when the file is not open with read permissions.
575     ///
576     /// # Example
577     ///
578     /// ```
579     /// use std::fs::File;
580     /// use std::io::Read;
581     ///
582     /// use memmap2::Mmap;
583     ///
584     /// # fn main() -> std::io::Result<()> {
585     /// let mut file = File::open("LICENSE-APACHE")?;
586     ///
587     /// let mut contents = Vec::new();
588     /// file.read_to_end(&mut contents)?;
589     ///
590     /// let mmap = unsafe { Mmap::map(&file)?  };
591     ///
592     /// assert_eq!(&contents[..], &mmap[..]);
593     /// # Ok(())
594     /// # }
595     /// ```
map<T: MmapAsRawDesc>(file: T) -> Result<Mmap>596     pub unsafe fn map<T: MmapAsRawDesc>(file: T) -> Result<Mmap> {
597         MmapOptions::new().map(file)
598     }
599 
600     /// Transition the memory map to be writable.
601     ///
602     /// If the memory map is file-backed, the file must have been opened with write permissions.
603     ///
604     /// # Errors
605     ///
606     /// This method returns an error when the underlying system call fails, which can happen for a
607     /// variety of reasons, such as when the file is not open with writable permissions.
608     ///
609     /// # Example
610     ///
611     /// ```
612     /// # extern crate memmap2;
613     /// # extern crate tempfile;
614     /// #
615     /// use memmap2::Mmap;
616     /// use std::ops::DerefMut;
617     /// use std::io::Write;
618     /// # use std::fs::OpenOptions;
619     ///
620     /// # fn main() -> std::io::Result<()> {
621     /// # let tempdir = tempfile::tempdir()?;
622     /// let file = /* file opened with write permissions */
623     /// #          OpenOptions::new()
624     /// #                      .read(true)
625     /// #                      .write(true)
626     /// #                      .create(true)
627     /// #                      .open(tempdir.path()
628     /// #                      .join("make_mut"))?;
629     /// # file.set_len(128)?;
630     /// let mmap = unsafe { Mmap::map(&file)? };
631     /// // ... use the read-only memory map ...
632     /// let mut mut_mmap = mmap.make_mut()?;
633     /// mut_mmap.deref_mut().write_all(b"hello, world!")?;
634     /// # Ok(())
635     /// # }
636     /// ```
make_mut(mut self) -> Result<MmapMut>637     pub fn make_mut(mut self) -> Result<MmapMut> {
638         self.inner.make_mut()?;
639         Ok(MmapMut { inner: self.inner })
640     }
641 
642     /// Advise OS how this memory map will be accessed. Only supported on Unix.
643     ///
644     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
645     #[cfg(unix)]
advise(&self, advice: Advice) -> Result<()>646     pub fn advise(&self, advice: Advice) -> Result<()> {
647         self.inner.advise(advice, 0, self.inner.len())
648     }
649 
650     /// Advise OS how this range of memory map will be accessed.
651     ///
652     /// The offset and length must be in the bounds of the memory map.
653     ///
654     /// Only supported on Unix.
655     ///
656     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
657     #[cfg(unix)]
advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()>658     pub fn advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()> {
659         self.inner.advise(advice, offset, len)
660     }
661 
662     /// Lock the whole memory map into RAM. Only supported on Unix.
663     ///
664     /// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
665     #[cfg(unix)]
lock(&self) -> Result<()>666     pub fn lock(&self) -> Result<()> {
667         self.inner.lock()
668     }
669 
670     /// Unlock the whole memory map. Only supported on Unix.
671     ///
672     /// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
673     #[cfg(unix)]
unlock(&self) -> Result<()>674     pub fn unlock(&self) -> Result<()> {
675         self.inner.unlock()
676     }
677 
678     /// Adjust the size of the memory mapping.
679     ///
680     /// This will try to resize the memory mapping in place. If
681     /// [`RemapOptions::may_move`] is specified it will move the mapping if it
682     /// could not resize in place, otherwise it will error.
683     ///
684     /// Only supported on Linux.
685     ///
686     /// See the [`mremap(2)`] man page.
687     ///
688     /// # Safety
689     ///
690     /// Resizing the memory mapping beyond the end of the mapped file will
691     /// result in UB should you happen to access memory beyond the end of the
692     /// file.
693     ///
694     /// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
695     #[cfg(target_os = "linux")]
remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()>696     pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
697         self.inner.remap(new_len, options)
698     }
699 }
700 
701 #[cfg(feature = "stable_deref_trait")]
702 unsafe impl stable_deref_trait::StableDeref for Mmap {}
703 
704 impl Deref for Mmap {
705     type Target = [u8];
706 
707     #[inline]
deref(&self) -> &[u8]708     fn deref(&self) -> &[u8] {
709         unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
710     }
711 }
712 
713 impl AsRef<[u8]> for Mmap {
714     #[inline]
as_ref(&self) -> &[u8]715     fn as_ref(&self) -> &[u8] {
716         self.deref()
717     }
718 }
719 
720 impl fmt::Debug for Mmap {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result721     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
722         fmt.debug_struct("Mmap")
723             .field("ptr", &self.as_ptr())
724             .field("len", &self.len())
725             .finish()
726     }
727 }
728 
729 /// A handle to a raw memory mapped buffer.
730 ///
731 /// This struct never hands out references to its interior, only raw pointers.
732 /// This can be helpful when creating shared memory maps between untrusted processes.
733 pub struct MmapRaw {
734     inner: MmapInner,
735 }
736 
737 impl MmapRaw {
738     /// Creates a writeable memory map backed by a file.
739     ///
740     /// This is equivalent to calling `MmapOptions::new().map_raw(file)`.
741     ///
742     /// # Errors
743     ///
744     /// This method returns an error when the underlying system call fails, which can happen for a
745     /// variety of reasons, such as when the file is not open with read and write permissions.
map_raw<T: MmapAsRawDesc>(file: T) -> Result<MmapRaw>746     pub fn map_raw<T: MmapAsRawDesc>(file: T) -> Result<MmapRaw> {
747         MmapOptions::new().map_raw(file)
748     }
749 
750     /// Returns a raw pointer to the memory mapped file.
751     ///
752     /// Before dereferencing this pointer, you have to make sure that the file has not been
753     /// truncated since the memory map was created.
754     /// Avoiding this will not introduce memory safety issues in Rust terms,
755     /// but will cause SIGBUS (or equivalent) signal.
756     #[inline]
as_ptr(&self) -> *const u8757     pub fn as_ptr(&self) -> *const u8 {
758         self.inner.ptr()
759     }
760 
761     /// Returns an unsafe mutable pointer to the memory mapped file.
762     ///
763     /// Before dereferencing this pointer, you have to make sure that the file has not been
764     /// truncated since the memory map was created.
765     /// Avoiding this will not introduce memory safety issues in Rust terms,
766     /// but will cause SIGBUS (or equivalent) signal.
767     #[inline]
as_mut_ptr(&self) -> *mut u8768     pub fn as_mut_ptr(&self) -> *mut u8 {
769         self.inner.ptr() as _
770     }
771 
772     /// Returns the length in bytes of the memory map.
773     ///
774     /// Note that truncating the file can cause the length to change (and render this value unusable).
775     #[inline]
len(&self) -> usize776     pub fn len(&self) -> usize {
777         self.inner.len()
778     }
779 
780     /// Flushes outstanding memory map modifications to disk.
781     ///
782     /// When this method returns with a non-error result, all outstanding changes to a file-backed
783     /// memory map are guaranteed to be durably stored. The file's metadata (including last
784     /// modification timestamp) may not be updated.
785     ///
786     /// # Example
787     ///
788     /// ```
789     /// # extern crate memmap2;
790     /// # extern crate tempfile;
791     /// #
792     /// use std::fs::OpenOptions;
793     /// use std::io::Write;
794     /// use std::path::PathBuf;
795     /// use std::slice;
796     ///
797     /// use memmap2::MmapRaw;
798     ///
799     /// # fn main() -> std::io::Result<()> {
800     /// let tempdir = tempfile::tempdir()?;
801     /// let path: PathBuf = /* path to file */
802     /// #   tempdir.path().join("flush");
803     /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
804     /// file.set_len(128)?;
805     ///
806     /// let mut mmap = unsafe { MmapRaw::map_raw(&file)? };
807     ///
808     /// let mut memory = unsafe { slice::from_raw_parts_mut(mmap.as_mut_ptr(), 128) };
809     /// memory.write_all(b"Hello, world!")?;
810     /// mmap.flush()?;
811     /// # Ok(())
812     /// # }
813     /// ```
flush(&self) -> Result<()>814     pub fn flush(&self) -> Result<()> {
815         let len = self.len();
816         self.inner.flush(0, len)
817     }
818 
819     /// Asynchronously flushes outstanding memory map modifications to disk.
820     ///
821     /// This method initiates flushing modified pages to durable storage, but it will not wait for
822     /// the operation to complete before returning. The file's metadata (including last
823     /// modification timestamp) may not be updated.
flush_async(&self) -> Result<()>824     pub fn flush_async(&self) -> Result<()> {
825         let len = self.len();
826         self.inner.flush_async(0, len)
827     }
828 
829     /// Flushes outstanding memory map modifications in the range to disk.
830     ///
831     /// The offset and length must be in the bounds of the memory map.
832     ///
833     /// When this method returns with a non-error result, all outstanding changes to a file-backed
834     /// memory in the range are guaranteed to be durable stored. The file's metadata (including
835     /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
836     /// in the specified range are flushed; other outstanding changes to the memory map may be
837     /// flushed as well.
flush_range(&self, offset: usize, len: usize) -> Result<()>838     pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
839         self.inner.flush(offset, len)
840     }
841 
842     /// Asynchronously flushes outstanding memory map modifications in the range to disk.
843     ///
844     /// The offset and length must be in the bounds of the memory map.
845     ///
846     /// This method initiates flushing modified pages to durable storage, but it will not wait for
847     /// the operation to complete before returning. The file's metadata (including last
848     /// modification timestamp) may not be updated. It is not guaranteed that the only changes
849     /// flushed are those in the specified range; other outstanding changes to the memory map may
850     /// be flushed as well.
flush_async_range(&self, offset: usize, len: usize) -> Result<()>851     pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
852         self.inner.flush_async(offset, len)
853     }
854 
855     /// Advise OS how this memory map will be accessed. Only supported on Unix.
856     ///
857     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
858     #[cfg(unix)]
advise(&self, advice: Advice) -> Result<()>859     pub fn advise(&self, advice: Advice) -> Result<()> {
860         self.inner.advise(advice, 0, self.inner.len())
861     }
862 
863     /// Advise OS how this range of memory map will be accessed.
864     ///
865     /// The offset and length must be in the bounds of the memory map.
866     ///
867     /// Only supported on Unix.
868     ///
869     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
870     #[cfg(unix)]
advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()>871     pub fn advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()> {
872         self.inner.advise(advice, offset, len)
873     }
874 
875     /// Lock the whole memory map into RAM. Only supported on Unix.
876     ///
877     /// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
878     #[cfg(unix)]
lock(&self) -> Result<()>879     pub fn lock(&self) -> Result<()> {
880         self.inner.lock()
881     }
882 
883     /// Unlock the whole memory map. Only supported on Unix.
884     ///
885     /// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
886     #[cfg(unix)]
unlock(&self) -> Result<()>887     pub fn unlock(&self) -> Result<()> {
888         self.inner.unlock()
889     }
890 
891     /// Adjust the size of the memory mapping.
892     ///
893     /// This will try to resize the memory mapping in place. If
894     /// [`RemapOptions::may_move`] is specified it will move the mapping if it
895     /// could not resize in place, otherwise it will error.
896     ///
897     /// Only supported on Linux.
898     ///
899     /// See the [`mremap(2)`] man page.
900     ///
901     /// # Safety
902     ///
903     /// Resizing the memory mapping beyond the end of the mapped file will
904     /// result in UB should you happen to access memory beyond the end of the
905     /// file.
906     ///
907     /// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
908     #[cfg(target_os = "linux")]
remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()>909     pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
910         self.inner.remap(new_len, options)
911     }
912 }
913 
914 impl fmt::Debug for MmapRaw {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result915     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
916         fmt.debug_struct("MmapRaw")
917             .field("ptr", &self.as_ptr())
918             .field("len", &self.len())
919             .finish()
920     }
921 }
922 
923 impl From<Mmap> for MmapRaw {
from(value: Mmap) -> Self924     fn from(value: Mmap) -> Self {
925         Self { inner: value.inner }
926     }
927 }
928 
929 impl From<MmapMut> for MmapRaw {
from(value: MmapMut) -> Self930     fn from(value: MmapMut) -> Self {
931         Self { inner: value.inner }
932     }
933 }
934 
935 /// A handle to a mutable memory mapped buffer.
936 ///
937 /// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous
938 /// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use
939 /// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the
940 /// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default
941 /// options are required.
942 ///
943 /// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the
944 /// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File`
945 /// used to create it. For consistency, on some platforms this is achieved by duplicating the
946 /// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped.
947 ///
948 /// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
949 /// the mapped pages into physical memory) though the details of this are platform specific.
950 ///
951 /// `Mmap` is [`Sync`] and [`Send`].
952 ///
953 /// See [`Mmap`] for the immutable version.
954 ///
955 /// ## Safety
956 ///
957 /// All file-backed memory map constructors are marked `unsafe` because of the potential for
958 /// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or
959 /// out of process. Applications must consider the risk and take appropriate precautions when using
960 /// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked)
961 /// files exist but are platform specific and limited.
962 pub struct MmapMut {
963     inner: MmapInner,
964 }
965 
966 impl MmapMut {
967     /// Creates a writeable memory map backed by a file.
968     ///
969     /// This is equivalent to calling `MmapOptions::new().map_mut(file)`.
970     ///
971     /// # Errors
972     ///
973     /// This method returns an error when the underlying system call fails, which can happen for a
974     /// variety of reasons, such as when the file is not open with read and write permissions.
975     ///
976     /// # Example
977     ///
978     /// ```
979     /// # extern crate memmap2;
980     /// # extern crate tempfile;
981     /// #
982     /// use std::fs::OpenOptions;
983     /// use std::path::PathBuf;
984     ///
985     /// use memmap2::MmapMut;
986     /// #
987     /// # fn main() -> std::io::Result<()> {
988     /// # let tempdir = tempfile::tempdir()?;
989     /// let path: PathBuf = /* path to file */
990     /// #   tempdir.path().join("map_mut");
991     /// let file = OpenOptions::new()
992     ///                        .read(true)
993     ///                        .write(true)
994     ///                        .create(true)
995     ///                        .open(&path)?;
996     /// file.set_len(13)?;
997     ///
998     /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
999     ///
1000     /// mmap.copy_from_slice(b"Hello, world!");
1001     /// # Ok(())
1002     /// # }
1003     /// ```
map_mut<T: MmapAsRawDesc>(file: T) -> Result<MmapMut>1004     pub unsafe fn map_mut<T: MmapAsRawDesc>(file: T) -> Result<MmapMut> {
1005         MmapOptions::new().map_mut(file)
1006     }
1007 
1008     /// Creates an anonymous memory map.
1009     ///
1010     /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`.
1011     ///
1012     /// # Errors
1013     ///
1014     /// This method returns an error when the underlying system call fails or
1015     /// when `len > isize::MAX`.
map_anon(length: usize) -> Result<MmapMut>1016     pub fn map_anon(length: usize) -> Result<MmapMut> {
1017         MmapOptions::new().len(length).map_anon()
1018     }
1019 
1020     /// Flushes outstanding memory map modifications to disk.
1021     ///
1022     /// When this method returns with a non-error result, all outstanding changes to a file-backed
1023     /// memory map are guaranteed to be durably stored. The file's metadata (including last
1024     /// modification timestamp) may not be updated.
1025     ///
1026     /// # Example
1027     ///
1028     /// ```
1029     /// # extern crate memmap2;
1030     /// # extern crate tempfile;
1031     /// #
1032     /// use std::fs::OpenOptions;
1033     /// use std::io::Write;
1034     /// use std::path::PathBuf;
1035     ///
1036     /// use memmap2::MmapMut;
1037     ///
1038     /// # fn main() -> std::io::Result<()> {
1039     /// # let tempdir = tempfile::tempdir()?;
1040     /// let path: PathBuf = /* path to file */
1041     /// #   tempdir.path().join("flush");
1042     /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
1043     /// file.set_len(128)?;
1044     ///
1045     /// let mut mmap = unsafe { MmapMut::map_mut(&file)? };
1046     ///
1047     /// (&mut mmap[..]).write_all(b"Hello, world!")?;
1048     /// mmap.flush()?;
1049     /// # Ok(())
1050     /// # }
1051     /// ```
flush(&self) -> Result<()>1052     pub fn flush(&self) -> Result<()> {
1053         let len = self.len();
1054         self.inner.flush(0, len)
1055     }
1056 
1057     /// Asynchronously flushes outstanding memory map modifications to disk.
1058     ///
1059     /// This method initiates flushing modified pages to durable storage, but it will not wait for
1060     /// the operation to complete before returning. The file's metadata (including last
1061     /// modification timestamp) may not be updated.
flush_async(&self) -> Result<()>1062     pub fn flush_async(&self) -> Result<()> {
1063         let len = self.len();
1064         self.inner.flush_async(0, len)
1065     }
1066 
1067     /// Flushes outstanding memory map modifications in the range to disk.
1068     ///
1069     /// The offset and length must be in the bounds of the memory map.
1070     ///
1071     /// When this method returns with a non-error result, all outstanding changes to a file-backed
1072     /// memory in the range are guaranteed to be durable stored. The file's metadata (including
1073     /// last modification timestamp) may not be updated. It is not guaranteed the only the changes
1074     /// in the specified range are flushed; other outstanding changes to the memory map may be
1075     /// flushed as well.
flush_range(&self, offset: usize, len: usize) -> Result<()>1076     pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> {
1077         self.inner.flush(offset, len)
1078     }
1079 
1080     /// Asynchronously flushes outstanding memory map modifications in the range to disk.
1081     ///
1082     /// The offset and length must be in the bounds of the memory map.
1083     ///
1084     /// This method initiates flushing modified pages to durable storage, but it will not wait for
1085     /// the operation to complete before returning. The file's metadata (including last
1086     /// modification timestamp) may not be updated. It is not guaranteed that the only changes
1087     /// flushed are those in the specified range; other outstanding changes to the memory map may
1088     /// be flushed as well.
flush_async_range(&self, offset: usize, len: usize) -> Result<()>1089     pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
1090         self.inner.flush_async(offset, len)
1091     }
1092 
1093     /// Returns an immutable version of this memory mapped buffer.
1094     ///
1095     /// If the memory map is file-backed, the file must have been opened with read permissions.
1096     ///
1097     /// # Errors
1098     ///
1099     /// This method returns an error when the underlying system call fails, which can happen for a
1100     /// variety of reasons, such as when the file has not been opened with read permissions.
1101     ///
1102     /// # Example
1103     ///
1104     /// ```
1105     /// # extern crate memmap2;
1106     /// #
1107     /// use std::io::Write;
1108     /// use std::path::PathBuf;
1109     ///
1110     /// use memmap2::{Mmap, MmapMut};
1111     ///
1112     /// # fn main() -> std::io::Result<()> {
1113     /// let mut mmap = MmapMut::map_anon(128)?;
1114     ///
1115     /// (&mut mmap[..]).write(b"Hello, world!")?;
1116     ///
1117     /// let mmap: Mmap = mmap.make_read_only()?;
1118     /// # Ok(())
1119     /// # }
1120     /// ```
make_read_only(mut self) -> Result<Mmap>1121     pub fn make_read_only(mut self) -> Result<Mmap> {
1122         self.inner.make_read_only()?;
1123         Ok(Mmap { inner: self.inner })
1124     }
1125 
1126     /// Transition the memory map to be readable and executable.
1127     ///
1128     /// If the memory map is file-backed, the file must have been opened with execute permissions.
1129     ///
1130     /// On systems with separate instructions and data caches (a category that includes many ARM
1131     /// chips), a platform-specific call may be needed to ensure that the changes are visible to the
1132     /// execution unit (e.g. when using this function to implement a JIT compiler).  For more
1133     /// details, see [this ARM write-up](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/caches-and-self-modifying-code)
1134     /// or the `man` page for [`sys_icache_invalidate`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html).
1135     ///
1136     /// # Errors
1137     ///
1138     /// This method returns an error when the underlying system call fails, which can happen for a
1139     /// variety of reasons, such as when the file has not been opened with execute permissions.
make_exec(mut self) -> Result<Mmap>1140     pub fn make_exec(mut self) -> Result<Mmap> {
1141         self.inner.make_exec()?;
1142         Ok(Mmap { inner: self.inner })
1143     }
1144 
1145     /// Advise OS how this memory map will be accessed. Only supported on Unix.
1146     ///
1147     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
1148     #[cfg(unix)]
advise(&self, advice: Advice) -> Result<()>1149     pub fn advise(&self, advice: Advice) -> Result<()> {
1150         self.inner.advise(advice, 0, self.inner.len())
1151     }
1152 
1153     /// Advise OS how this range of memory map will be accessed.
1154     ///
1155     /// The offset and length must be in the bounds of the memory map.
1156     ///
1157     /// Only supported on Unix.
1158     ///
1159     /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
1160     #[cfg(unix)]
advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()>1161     pub fn advise_range(&self, advice: Advice, offset: usize, len: usize) -> Result<()> {
1162         self.inner.advise(advice, offset, len)
1163     }
1164 
1165     /// Lock the whole memory map into RAM. Only supported on Unix.
1166     ///
1167     /// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
1168     #[cfg(unix)]
lock(&self) -> Result<()>1169     pub fn lock(&self) -> Result<()> {
1170         self.inner.lock()
1171     }
1172 
1173     /// Unlock the whole memory map. Only supported on Unix.
1174     ///
1175     /// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
1176     #[cfg(unix)]
unlock(&self) -> Result<()>1177     pub fn unlock(&self) -> Result<()> {
1178         self.inner.unlock()
1179     }
1180 
1181     /// Adjust the size of the memory mapping.
1182     ///
1183     /// This will try to resize the memory mapping in place. If
1184     /// [`RemapOptions::may_move`] is specified it will move the mapping if it
1185     /// could not resize in place, otherwise it will error.
1186     ///
1187     /// Only supported on Linux.
1188     ///
1189     /// See the [`mremap(2)`] man page.
1190     ///
1191     /// # Safety
1192     ///
1193     /// Resizing the memory mapping beyond the end of the mapped file will
1194     /// result in UB should you happen to access memory beyond the end of the
1195     /// file.
1196     ///
1197     /// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
1198     #[cfg(target_os = "linux")]
remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()>1199     pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
1200         self.inner.remap(new_len, options)
1201     }
1202 }
1203 
1204 #[cfg(feature = "stable_deref_trait")]
1205 unsafe impl stable_deref_trait::StableDeref for MmapMut {}
1206 
1207 impl Deref for MmapMut {
1208     type Target = [u8];
1209 
1210     #[inline]
deref(&self) -> &[u8]1211     fn deref(&self) -> &[u8] {
1212         unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) }
1213     }
1214 }
1215 
1216 impl DerefMut for MmapMut {
1217     #[inline]
deref_mut(&mut self) -> &mut [u8]1218     fn deref_mut(&mut self) -> &mut [u8] {
1219         unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) }
1220     }
1221 }
1222 
1223 impl AsRef<[u8]> for MmapMut {
1224     #[inline]
as_ref(&self) -> &[u8]1225     fn as_ref(&self) -> &[u8] {
1226         self.deref()
1227     }
1228 }
1229 
1230 impl AsMut<[u8]> for MmapMut {
1231     #[inline]
as_mut(&mut self) -> &mut [u8]1232     fn as_mut(&mut self) -> &mut [u8] {
1233         self.deref_mut()
1234     }
1235 }
1236 
1237 impl fmt::Debug for MmapMut {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1238     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1239         fmt.debug_struct("MmapMut")
1240             .field("ptr", &self.as_ptr())
1241             .field("len", &self.len())
1242             .finish()
1243     }
1244 }
1245 
1246 /// Options for [`Mmap::remap`] and [`MmapMut::remap`].
1247 #[derive(Copy, Clone, Default, Debug)]
1248 #[cfg(target_os = "linux")]
1249 pub struct RemapOptions {
1250     may_move: bool,
1251 }
1252 
1253 #[cfg(target_os = "linux")]
1254 impl RemapOptions {
1255     /// Creates a mew set of options for resizing a memory map.
new() -> Self1256     pub fn new() -> Self {
1257         Self::default()
1258     }
1259 
1260     /// Controls whether the memory map can be moved if it is not possible to
1261     /// resize it in place.
1262     ///
1263     /// If false then the memory map is guaranteed to remain at the same
1264     /// address when being resized but attempting to resize will return an
1265     /// error if the new memory map would overlap with something else in the
1266     /// current process' memory.
1267     ///
1268     /// By default this is false.
1269     ///
1270     /// # `may_move` and `StableDeref`
1271     /// If the `stable_deref_trait` feature is enabled then [`Mmap`] and
1272     /// [`MmapMut`] implement `StableDeref`. `StableDeref` promises that the
1273     /// memory map dereferences to a fixed address, however, calling `remap`
1274     /// with `may_move` set may result in the backing memory of the mapping
1275     /// being moved to a new address. This may cause UB in other code
1276     /// depending on the `StableDeref` guarantees.
may_move(mut self, may_move: bool) -> Self1277     pub fn may_move(mut self, may_move: bool) -> Self {
1278         self.may_move = may_move;
1279         self
1280     }
1281 
into_flags(self) -> libc::c_int1282     pub(crate) fn into_flags(self) -> libc::c_int {
1283         if self.may_move {
1284             libc::MREMAP_MAYMOVE
1285         } else {
1286             0
1287         }
1288     }
1289 }
1290 
1291 #[cfg(test)]
1292 mod test {
1293     extern crate tempfile;
1294 
1295     #[cfg(unix)]
1296     use crate::advice::Advice;
1297     use std::fs::{File, OpenOptions};
1298     use std::io::{Read, Write};
1299     use std::mem;
1300     #[cfg(unix)]
1301     use std::os::unix::io::AsRawFd;
1302     #[cfg(windows)]
1303     use std::os::windows::fs::OpenOptionsExt;
1304 
1305     #[cfg(windows)]
1306     const GENERIC_ALL: u32 = 0x10000000;
1307 
1308     use super::{Mmap, MmapMut, MmapOptions};
1309 
1310     #[test]
map_file()1311     fn map_file() {
1312         let expected_len = 128;
1313         let tempdir = tempfile::tempdir().unwrap();
1314         let path = tempdir.path().join("mmap");
1315 
1316         let file = OpenOptions::new()
1317             .read(true)
1318             .write(true)
1319             .create(true)
1320             .open(path)
1321             .unwrap();
1322 
1323         file.set_len(expected_len as u64).unwrap();
1324 
1325         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1326         let len = mmap.len();
1327         assert_eq!(expected_len, len);
1328 
1329         let zeros = vec![0; len];
1330         let incr: Vec<u8> = (0..len as u8).collect();
1331 
1332         // check that the mmap is empty
1333         assert_eq!(&zeros[..], &mmap[..]);
1334 
1335         // write values into the mmap
1336         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1337 
1338         // read values back
1339         assert_eq!(&incr[..], &mmap[..]);
1340     }
1341 
1342     #[test]
1343     #[cfg(unix)]
map_fd()1344     fn map_fd() {
1345         let expected_len = 128;
1346         let tempdir = tempfile::tempdir().unwrap();
1347         let path = tempdir.path().join("mmap");
1348 
1349         let file = OpenOptions::new()
1350             .read(true)
1351             .write(true)
1352             .create(true)
1353             .open(path)
1354             .unwrap();
1355 
1356         file.set_len(expected_len as u64).unwrap();
1357 
1358         let mut mmap = unsafe { MmapMut::map_mut(file.as_raw_fd()).unwrap() };
1359         let len = mmap.len();
1360         assert_eq!(expected_len, len);
1361 
1362         let zeros = vec![0; len];
1363         let incr: Vec<u8> = (0..len as u8).collect();
1364 
1365         // check that the mmap is empty
1366         assert_eq!(&zeros[..], &mmap[..]);
1367 
1368         // write values into the mmap
1369         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1370 
1371         // read values back
1372         assert_eq!(&incr[..], &mmap[..]);
1373     }
1374 
1375     /// Checks that "mapping" a 0-length file derefs to an empty slice.
1376     #[test]
map_empty_file()1377     fn map_empty_file() {
1378         let tempdir = tempfile::tempdir().unwrap();
1379         let path = tempdir.path().join("mmap");
1380 
1381         let file = OpenOptions::new()
1382             .read(true)
1383             .write(true)
1384             .create(true)
1385             .open(path)
1386             .unwrap();
1387         let mmap = unsafe { Mmap::map(&file).unwrap() };
1388         assert!(mmap.is_empty());
1389         assert_eq!(mmap.as_ptr().align_offset(mem::size_of::<usize>()), 0);
1390         let mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1391         assert!(mmap.is_empty());
1392         assert_eq!(mmap.as_ptr().align_offset(mem::size_of::<usize>()), 0);
1393     }
1394 
1395     #[test]
map_anon()1396     fn map_anon() {
1397         let expected_len = 128;
1398         let mut mmap = MmapMut::map_anon(expected_len).unwrap();
1399         let len = mmap.len();
1400         assert_eq!(expected_len, len);
1401 
1402         let zeros = vec![0; len];
1403         let incr: Vec<u8> = (0..len as u8).collect();
1404 
1405         // check that the mmap is empty
1406         assert_eq!(&zeros[..], &mmap[..]);
1407 
1408         // write values into the mmap
1409         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1410 
1411         // read values back
1412         assert_eq!(&incr[..], &mmap[..]);
1413     }
1414 
1415     #[test]
map_anon_zero_len()1416     fn map_anon_zero_len() {
1417         assert!(MmapOptions::new().map_anon().unwrap().is_empty())
1418     }
1419 
1420     #[test]
1421     #[cfg(target_pointer_width = "32")]
map_anon_len_overflow()1422     fn map_anon_len_overflow() {
1423         let res = MmapMut::map_anon(0x80000000);
1424 
1425         assert_eq!(
1426             res.unwrap_err().to_string(),
1427             "memory map length overflows isize"
1428         );
1429     }
1430 
1431     #[test]
file_write()1432     fn file_write() {
1433         let tempdir = tempfile::tempdir().unwrap();
1434         let path = tempdir.path().join("mmap");
1435 
1436         let mut file = OpenOptions::new()
1437             .read(true)
1438             .write(true)
1439             .create(true)
1440             .open(path)
1441             .unwrap();
1442         file.set_len(128).unwrap();
1443 
1444         let write = b"abc123";
1445         let mut read = [0u8; 6];
1446 
1447         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1448         (&mut mmap[..]).write_all(write).unwrap();
1449         mmap.flush().unwrap();
1450 
1451         file.read_exact(&mut read).unwrap();
1452         assert_eq!(write, &read);
1453     }
1454 
1455     #[test]
flush_range()1456     fn flush_range() {
1457         let tempdir = tempfile::tempdir().unwrap();
1458         let path = tempdir.path().join("mmap");
1459 
1460         let file = OpenOptions::new()
1461             .read(true)
1462             .write(true)
1463             .create(true)
1464             .open(path)
1465             .unwrap();
1466         file.set_len(128).unwrap();
1467         let write = b"abc123";
1468 
1469         let mut mmap = unsafe {
1470             MmapOptions::new()
1471                 .offset(2)
1472                 .len(write.len())
1473                 .map_mut(&file)
1474                 .unwrap()
1475         };
1476         (&mut mmap[..]).write_all(write).unwrap();
1477         mmap.flush_async_range(0, write.len()).unwrap();
1478         mmap.flush_range(0, write.len()).unwrap();
1479     }
1480 
1481     #[test]
map_copy()1482     fn map_copy() {
1483         let tempdir = tempfile::tempdir().unwrap();
1484         let path = tempdir.path().join("mmap");
1485 
1486         let mut file = OpenOptions::new()
1487             .read(true)
1488             .write(true)
1489             .create(true)
1490             .open(path)
1491             .unwrap();
1492         file.set_len(128).unwrap();
1493 
1494         let nulls = b"\0\0\0\0\0\0";
1495         let write = b"abc123";
1496         let mut read = [0u8; 6];
1497 
1498         let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() };
1499 
1500         (&mut mmap[..]).write_all(write).unwrap();
1501         mmap.flush().unwrap();
1502 
1503         // The mmap contains the write
1504         (&mmap[..]).read_exact(&mut read).unwrap();
1505         assert_eq!(write, &read);
1506 
1507         // The file does not contain the write
1508         file.read_exact(&mut read).unwrap();
1509         assert_eq!(nulls, &read);
1510 
1511         // another mmap does not contain the write
1512         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1513         (&mmap2[..]).read_exact(&mut read).unwrap();
1514         assert_eq!(nulls, &read);
1515     }
1516 
1517     #[test]
map_copy_read_only()1518     fn map_copy_read_only() {
1519         let tempdir = tempfile::tempdir().unwrap();
1520         let path = tempdir.path().join("mmap");
1521 
1522         let file = OpenOptions::new()
1523             .read(true)
1524             .write(true)
1525             .create(true)
1526             .open(path)
1527             .unwrap();
1528         file.set_len(128).unwrap();
1529 
1530         let nulls = b"\0\0\0\0\0\0";
1531         let mut read = [0u8; 6];
1532 
1533         let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() };
1534         (&mmap[..]).read_exact(&mut read).unwrap();
1535         assert_eq!(nulls, &read);
1536 
1537         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1538         (&mmap2[..]).read_exact(&mut read).unwrap();
1539         assert_eq!(nulls, &read);
1540     }
1541 
1542     #[test]
map_offset()1543     fn map_offset() {
1544         let tempdir = tempfile::tempdir().unwrap();
1545         let path = tempdir.path().join("mmap");
1546 
1547         let file = OpenOptions::new()
1548             .read(true)
1549             .write(true)
1550             .create(true)
1551             .open(path)
1552             .unwrap();
1553 
1554         let offset = u32::MAX as u64 + 2;
1555         let len = 5432;
1556         file.set_len(offset + len as u64).unwrap();
1557 
1558         // Check inferred length mmap.
1559         let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() };
1560         assert_eq!(len, mmap.len());
1561 
1562         // Check explicit length mmap.
1563         let mut mmap = unsafe {
1564             MmapOptions::new()
1565                 .offset(offset)
1566                 .len(len)
1567                 .map_mut(&file)
1568                 .unwrap()
1569         };
1570         assert_eq!(len, mmap.len());
1571 
1572         let zeros = vec![0; len];
1573         let incr: Vec<_> = (0..len).map(|i| i as u8).collect();
1574 
1575         // check that the mmap is empty
1576         assert_eq!(&zeros[..], &mmap[..]);
1577 
1578         // write values into the mmap
1579         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1580 
1581         // read values back
1582         assert_eq!(&incr[..], &mmap[..]);
1583     }
1584 
1585     #[test]
index()1586     fn index() {
1587         let mut mmap = MmapMut::map_anon(128).unwrap();
1588         mmap[0] = 42;
1589         assert_eq!(42, mmap[0]);
1590     }
1591 
1592     #[test]
sync_send()1593     fn sync_send() {
1594         let mmap = MmapMut::map_anon(129).unwrap();
1595 
1596         fn is_sync_send<T>(_val: T)
1597         where
1598             T: Sync + Send,
1599         {
1600         }
1601 
1602         is_sync_send(mmap);
1603     }
1604 
1605     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86(mut mmap: MmapMut)1606     fn jit_x86(mut mmap: MmapMut) {
1607         mmap[0] = 0xB8; // mov eax, 0xAB
1608         mmap[1] = 0xAB;
1609         mmap[2] = 0x00;
1610         mmap[3] = 0x00;
1611         mmap[4] = 0x00;
1612         mmap[5] = 0xC3; // ret
1613 
1614         let mmap = mmap.make_exec().expect("make_exec");
1615 
1616         let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) };
1617         assert_eq!(jitfn(), 0xab);
1618     }
1619 
1620     #[test]
1621     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86_anon()1622     fn jit_x86_anon() {
1623         jit_x86(MmapMut::map_anon(4096).unwrap());
1624     }
1625 
1626     #[test]
1627     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
jit_x86_file()1628     fn jit_x86_file() {
1629         let tempdir = tempfile::tempdir().unwrap();
1630         let mut options = OpenOptions::new();
1631         #[cfg(windows)]
1632         options.access_mode(GENERIC_ALL);
1633 
1634         let file = options
1635             .read(true)
1636             .write(true)
1637             .create(true)
1638             .open(tempdir.path().join("jit_x86"))
1639             .expect("open");
1640 
1641         file.set_len(4096).expect("set_len");
1642         jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") });
1643     }
1644 
1645     #[test]
mprotect_file()1646     fn mprotect_file() {
1647         let tempdir = tempfile::tempdir().unwrap();
1648         let path = tempdir.path().join("mmap");
1649 
1650         let mut options = OpenOptions::new();
1651         #[cfg(windows)]
1652         options.access_mode(GENERIC_ALL);
1653 
1654         let mut file = options
1655             .read(true)
1656             .write(true)
1657             .create(true)
1658             .open(path)
1659             .expect("open");
1660         file.set_len(256_u64).expect("set_len");
1661 
1662         let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") };
1663 
1664         let mmap = mmap.make_read_only().expect("make_read_only");
1665         let mut mmap = mmap.make_mut().expect("make_mut");
1666 
1667         let write = b"abc123";
1668         let mut read = [0u8; 6];
1669 
1670         (&mut mmap[..]).write_all(write).unwrap();
1671         mmap.flush().unwrap();
1672 
1673         // The mmap contains the write
1674         (&mmap[..]).read_exact(&mut read).unwrap();
1675         assert_eq!(write, &read);
1676 
1677         // The file should contain the write
1678         file.read_exact(&mut read).unwrap();
1679         assert_eq!(write, &read);
1680 
1681         // another mmap should contain the write
1682         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1683         (&mmap2[..]).read_exact(&mut read).unwrap();
1684         assert_eq!(write, &read);
1685 
1686         let mmap = mmap.make_exec().expect("make_exec");
1687 
1688         drop(mmap);
1689     }
1690 
1691     #[test]
mprotect_copy()1692     fn mprotect_copy() {
1693         let tempdir = tempfile::tempdir().unwrap();
1694         let path = tempdir.path().join("mmap");
1695 
1696         let mut options = OpenOptions::new();
1697         #[cfg(windows)]
1698         options.access_mode(GENERIC_ALL);
1699 
1700         let mut file = options
1701             .read(true)
1702             .write(true)
1703             .create(true)
1704             .open(path)
1705             .expect("open");
1706         file.set_len(256_u64).expect("set_len");
1707 
1708         let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") };
1709 
1710         let mmap = mmap.make_read_only().expect("make_read_only");
1711         let mut mmap = mmap.make_mut().expect("make_mut");
1712 
1713         let nulls = b"\0\0\0\0\0\0";
1714         let write = b"abc123";
1715         let mut read = [0u8; 6];
1716 
1717         (&mut mmap[..]).write_all(write).unwrap();
1718         mmap.flush().unwrap();
1719 
1720         // The mmap contains the write
1721         (&mmap[..]).read_exact(&mut read).unwrap();
1722         assert_eq!(write, &read);
1723 
1724         // The file does not contain the write
1725         file.read_exact(&mut read).unwrap();
1726         assert_eq!(nulls, &read);
1727 
1728         // another mmap does not contain the write
1729         let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() };
1730         (&mmap2[..]).read_exact(&mut read).unwrap();
1731         assert_eq!(nulls, &read);
1732 
1733         let mmap = mmap.make_exec().expect("make_exec");
1734 
1735         drop(mmap);
1736     }
1737 
1738     #[test]
mprotect_anon()1739     fn mprotect_anon() {
1740         let mmap = MmapMut::map_anon(256).expect("map_mut");
1741 
1742         let mmap = mmap.make_read_only().expect("make_read_only");
1743         let mmap = mmap.make_mut().expect("make_mut");
1744         let mmap = mmap.make_exec().expect("make_exec");
1745         drop(mmap);
1746     }
1747 
1748     #[test]
raw()1749     fn raw() {
1750         let tempdir = tempfile::tempdir().unwrap();
1751         let path = tempdir.path().join("mmapraw");
1752 
1753         let mut options = OpenOptions::new();
1754         let mut file = options
1755             .read(true)
1756             .write(true)
1757             .create(true)
1758             .open(path)
1759             .expect("open");
1760         file.write_all(b"abc123").unwrap();
1761         let mmap = MmapOptions::new().map_raw(&file).unwrap();
1762         assert_eq!(mmap.len(), 6);
1763         assert!(!mmap.as_ptr().is_null());
1764         assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
1765     }
1766 
1767     #[test]
raw_read_only()1768     fn raw_read_only() {
1769         let tempdir = tempfile::tempdir().unwrap();
1770         let path = tempdir.path().join("mmaprawro");
1771 
1772         File::create(&path).unwrap().write_all(b"abc123").unwrap();
1773 
1774         let mmap = MmapOptions::new()
1775             .map_raw_read_only(&File::open(&path).unwrap())
1776             .unwrap();
1777 
1778         assert_eq!(mmap.len(), 6);
1779         assert!(!mmap.as_ptr().is_null());
1780         assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
1781     }
1782 
1783     /// Something that relies on StableDeref
1784     #[test]
1785     #[cfg(feature = "stable_deref_trait")]
owning_ref()1786     fn owning_ref() {
1787         extern crate owning_ref;
1788 
1789         let mut map = MmapMut::map_anon(128).unwrap();
1790         map[10] = 42;
1791         let owning = owning_ref::OwningRef::new(map);
1792         let sliced = owning.map(|map| &map[10..20]);
1793         assert_eq!(42, sliced[0]);
1794 
1795         let map = sliced.into_owner().make_read_only().unwrap();
1796         let owning = owning_ref::OwningRef::new(map);
1797         let sliced = owning.map(|map| &map[10..20]);
1798         assert_eq!(42, sliced[0]);
1799     }
1800 
1801     #[test]
1802     #[cfg(unix)]
advise()1803     fn advise() {
1804         let expected_len = 128;
1805         let tempdir = tempfile::tempdir().unwrap();
1806         let path = tempdir.path().join("mmap_advise");
1807 
1808         let file = OpenOptions::new()
1809             .read(true)
1810             .write(true)
1811             .create(true)
1812             .open(path)
1813             .unwrap();
1814 
1815         file.set_len(expected_len as u64).unwrap();
1816 
1817         // Test MmapMut::advise
1818         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1819         mmap.advise(Advice::random())
1820             .expect("mmap advising should be supported on unix");
1821 
1822         let len = mmap.len();
1823         assert_eq!(expected_len, len);
1824 
1825         let zeros = vec![0; len];
1826         let incr: Vec<u8> = (0..len as u8).collect();
1827 
1828         // check that the mmap is empty
1829         assert_eq!(&zeros[..], &mmap[..]);
1830 
1831         mmap.advise_range(Advice::sequential(), 0, mmap.len())
1832             .expect("mmap advising should be supported on unix");
1833 
1834         // write values into the mmap
1835         (&mut mmap[..]).write_all(&incr[..]).unwrap();
1836 
1837         // read values back
1838         assert_eq!(&incr[..], &mmap[..]);
1839 
1840         // Set advice and Read from the read-only map
1841         let mmap = unsafe { Mmap::map(&file).unwrap() };
1842 
1843         mmap.advise(Advice::random())
1844             .expect("mmap advising should be supported on unix");
1845 
1846         // read values back
1847         assert_eq!(&incr[..], &mmap[..]);
1848     }
1849 
1850     #[test]
1851     #[cfg(target_os = "linux")]
advise_writes_unsafely()1852     fn advise_writes_unsafely() {
1853         let mut mmap = MmapMut::map_anon(4096).unwrap();
1854         mmap.as_mut().fill(255);
1855         let mmap = mmap.make_read_only().unwrap();
1856 
1857         let a = mmap.as_ref()[0];
1858         mmap.advise(unsafe { Advice::dont_need() }).unwrap();
1859         let b = mmap.as_ref()[0];
1860 
1861         assert_eq!(a, 255);
1862         assert_eq!(b, 0);
1863     }
1864 
1865     /// Returns true if a non-zero amount of memory is locked.
1866     #[cfg(target_os = "linux")]
is_locked() -> bool1867     fn is_locked() -> bool {
1868         let status = &std::fs::read_to_string("/proc/self/status")
1869             .expect("/proc/self/status should be available");
1870         for line in status.lines() {
1871             if line.starts_with("VmLck:") {
1872                 let numbers = line.replace(|c: char| !c.is_ascii_digit(), "");
1873                 return numbers != "0";
1874             }
1875         }
1876         panic!("cannot get VmLck information")
1877     }
1878 
1879     #[test]
1880     #[cfg(unix)]
lock()1881     fn lock() {
1882         let tempdir = tempfile::tempdir().unwrap();
1883         let path = tempdir.path().join("mmap_lock");
1884 
1885         let file = OpenOptions::new()
1886             .read(true)
1887             .write(true)
1888             .create(true)
1889             .open(path)
1890             .unwrap();
1891         file.set_len(128).unwrap();
1892 
1893         let mmap = unsafe { Mmap::map(&file).unwrap() };
1894         #[cfg(target_os = "linux")]
1895         assert!(!is_locked());
1896 
1897         mmap.lock().expect("mmap lock should be supported on unix");
1898         #[cfg(target_os = "linux")]
1899         assert!(is_locked());
1900 
1901         mmap.lock()
1902             .expect("mmap lock again should not cause problems");
1903         #[cfg(target_os = "linux")]
1904         assert!(is_locked());
1905 
1906         mmap.unlock()
1907             .expect("mmap unlock should be supported on unix");
1908         #[cfg(target_os = "linux")]
1909         assert!(!is_locked());
1910 
1911         mmap.unlock()
1912             .expect("mmap unlock again should not cause problems");
1913         #[cfg(target_os = "linux")]
1914         assert!(!is_locked());
1915     }
1916 
1917     #[test]
1918     #[cfg(target_os = "linux")]
remap_grow()1919     fn remap_grow() {
1920         use crate::RemapOptions;
1921 
1922         let initial_len = 128;
1923         let final_len = 2000;
1924 
1925         let zeros = vec![0u8; final_len];
1926         let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
1927 
1928         let file = tempfile::tempfile().unwrap();
1929         file.set_len(final_len as u64).unwrap();
1930 
1931         let mut mmap = unsafe { MmapOptions::new().len(initial_len).map_mut(&file).unwrap() };
1932         assert_eq!(mmap.len(), initial_len);
1933         assert_eq!(&mmap[..], &zeros[..initial_len]);
1934 
1935         unsafe {
1936             mmap.remap(final_len, RemapOptions::new().may_move(true))
1937                 .unwrap()
1938         };
1939 
1940         // The size should have been updated
1941         assert_eq!(mmap.len(), final_len);
1942 
1943         // Should still be all zeros
1944         assert_eq!(&mmap[..], &zeros);
1945 
1946         // Write out to the whole expanded slice.
1947         mmap.copy_from_slice(&incr);
1948     }
1949 
1950     #[test]
1951     #[cfg(target_os = "linux")]
remap_shrink()1952     fn remap_shrink() {
1953         use crate::RemapOptions;
1954 
1955         let initial_len = 20000;
1956         let final_len = 400;
1957 
1958         let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
1959 
1960         let file = tempfile::tempfile().unwrap();
1961         file.set_len(initial_len as u64).unwrap();
1962 
1963         let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
1964         assert_eq!(mmap.len(), initial_len);
1965 
1966         unsafe { mmap.remap(final_len, RemapOptions::new()).unwrap() };
1967         assert_eq!(mmap.len(), final_len);
1968 
1969         // Check that the mmap is still writable along the slice length
1970         mmap.copy_from_slice(&incr);
1971     }
1972 
1973     #[test]
1974     #[cfg(target_os = "linux")]
1975     #[cfg(target_pointer_width = "32")]
remap_len_overflow()1976     fn remap_len_overflow() {
1977         use crate::RemapOptions;
1978 
1979         let file = tempfile::tempfile().unwrap();
1980         file.set_len(1024).unwrap();
1981         let mut mmap = unsafe { MmapOptions::new().len(1024).map(&file).unwrap() };
1982 
1983         let res = unsafe { mmap.remap(0x80000000, RemapOptions::new().may_move(true)) };
1984         assert_eq!(
1985             res.unwrap_err().to_string(),
1986             "memory map length overflows isize"
1987         );
1988 
1989         assert_eq!(mmap.len(), 1024);
1990     }
1991 
1992     #[test]
1993     #[cfg(target_os = "linux")]
remap_with_offset()1994     fn remap_with_offset() {
1995         use crate::RemapOptions;
1996 
1997         let offset = 77;
1998         let initial_len = 128;
1999         let final_len = 2000;
2000 
2001         let zeros = vec![0u8; final_len];
2002         let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
2003 
2004         let file = tempfile::tempfile().unwrap();
2005         file.set_len(final_len as u64 + offset).unwrap();
2006 
2007         let mut mmap = unsafe {
2008             MmapOptions::new()
2009                 .len(initial_len)
2010                 .offset(offset)
2011                 .map_mut(&file)
2012                 .unwrap()
2013         };
2014         assert_eq!(mmap.len(), initial_len);
2015         assert_eq!(&mmap[..], &zeros[..initial_len]);
2016 
2017         unsafe {
2018             mmap.remap(final_len, RemapOptions::new().may_move(true))
2019                 .unwrap()
2020         };
2021 
2022         // The size should have been updated
2023         assert_eq!(mmap.len(), final_len);
2024 
2025         // Should still be all zeros
2026         assert_eq!(&mmap[..], &zeros);
2027 
2028         // Write out to the whole expanded slice.
2029         mmap.copy_from_slice(&incr);
2030     }
2031 }
2032