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