diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/memmap2-0.2.1 | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/memmap2-0.2.1')
-rw-r--r-- | vendor/memmap2-0.2.1/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/CHANGELOG.md | 31 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/Cargo.lock | 99 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/Cargo.toml | 26 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/LICENSE-MIT | 26 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/README.md | 33 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/examples/cat.rs | 23 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/src/lib.rs | 1199 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/src/unix.rs | 224 | ||||
-rw-r--r-- | vendor/memmap2-0.2.1/src/windows.rs | 426 |
11 files changed, 0 insertions, 2289 deletions
diff --git a/vendor/memmap2-0.2.1/.cargo-checksum.json b/vendor/memmap2-0.2.1/.cargo-checksum.json deleted file mode 100644 index 19a48c7a5..000000000 --- a/vendor/memmap2-0.2.1/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"a89928f51b2c7899a897b0f0864b8071c4a35efa353a5d8dd54b1c19621b9aa1","Cargo.lock":"9d2daf6059412a3ff3d7e0aadb74c92d6be8d400d9b38d671246378675d48c38","Cargo.toml":"864c720597df45669fbc7a5bf1150212a813ba5a0b92a87bc52c442bb4e33102","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"e9116f7228fce981d81aa680ae1add0cfb8122c35d801c4664d3d674ad0beda8","README.md":"4e70c39451ff48d9b60e2a0db4754fefc2fe349149b4baf4747ca3556ac7ae15","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/lib.rs":"bc2563ca78e820217366df7c0065938f65c318e8a09e6202652c78efb6b8539e","src/unix.rs":"7fe62be97f49a9225e52d59cdb1a576be868996ab26c4ab445e4b12dc15d6b09","src/windows.rs":"73e7ef54c44a2af917d2f733f4ba3abc7c293653c40f06a10a61bcf3f2757ef5"},"package":"04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"}
\ No newline at end of file diff --git a/vendor/memmap2-0.2.1/CHANGELOG.md b/vendor/memmap2-0.2.1/CHANGELOG.md deleted file mode 100644 index 258be14c2..000000000 --- a/vendor/memmap2-0.2.1/CHANGELOG.md +++ /dev/null @@ -1,31 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [Unreleased] - -## 0.2.1 - 2021-02-08 -### Added -- `MmapOptions::map_raw` and `MmapRaw`. [@diwic](https://github.com/diwic). - -## 0.2.0 - 2020-12-19 -### Changed -- MSRV is 1.31 now (edition 2018). -- Make anonymous memory maps private by default on unix. Thanks to [@CensoredUsername](https://github.com/CensoredUsername). -- Add `map_copy_read_only`. [@zserik](https://github.com/zserik). - -## 0.1.0 - 2020-01-18 -### Added -- Fork [memmap-rs](https://github.com/danburkert/memmap-rs). - -### Changed -- Use `LICENSE-APACHE` instead of `README.md` for some tests since it's immutable. - -### Removed -- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89) - -[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.1...HEAD -[0.2.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.0...v0.2.1 -[0.2.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.1.0...v0.2.0 diff --git a/vendor/memmap2-0.2.1/Cargo.lock b/vendor/memmap2-0.2.1/Cargo.lock deleted file mode 100644 index 76c7131c1..000000000 --- a/vendor/memmap2-0.2.1/Cargo.lock +++ /dev/null @@ -1,99 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "libc" -version = "0.2.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" - -[[package]] -name = "memmap2" -version = "0.2.1" -dependencies = [ - "libc", - "tempdir", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -dependencies = [ - "winapi", -] - -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand", - "remove_dir_all", -] - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/memmap2-0.2.1/Cargo.toml b/vendor/memmap2-0.2.1/Cargo.toml deleted file mode 100644 index 1765b84cc..000000000 --- a/vendor/memmap2-0.2.1/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "memmap2" -version = "0.2.1" -authors = ["Dan Burkert <dan@danburkert.com>", "Evgeniy Reizner <razrfalcon@gmail.com>"] -description = "Cross-platform Rust API for memory-mapped file IO" -documentation = "https://docs.rs/memmap2" -keywords = ["mmap", "memory-map", "io", "file"] -license = "MIT/Apache-2.0" -repository = "https://github.com/RazrFalcon/memmap2-rs" -[dev-dependencies.tempdir] -version = "0.3" -[target."cfg(unix)".dependencies.libc] -version = "0.2" diff --git a/vendor/memmap2-0.2.1/LICENSE-APACHE b/vendor/memmap2-0.2.1/LICENSE-APACHE deleted file mode 100644 index 7be3d81ac..000000000 --- a/vendor/memmap2-0.2.1/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2015] [Dan Burkert] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/memmap2-0.2.1/LICENSE-MIT b/vendor/memmap2-0.2.1/LICENSE-MIT deleted file mode 100644 index 5cc9371f2..000000000 --- a/vendor/memmap2-0.2.1/LICENSE-MIT +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Evgeniy Reizner -Copyright (c) 2015 Dan Burkert - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/memmap2-0.2.1/README.md b/vendor/memmap2-0.2.1/README.md deleted file mode 100644 index 67490933c..000000000 --- a/vendor/memmap2-0.2.1/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# memmap2 -![Build Status](https://github.com/RazrFalcon/memmap2-rs/workflows/Rust/badge.svg) -[![Crates.io](https://img.shields.io/crates/v/memmap2.svg)](https://crates.io/crates/memmap2) -[![Documentation](https://docs.rs/memmap2/badge.svg)](https://docs.rs/memmap2) -[![Rust 1.31+](https://img.shields.io/badge/rust-1.31+-orange.svg)](https://www.rust-lang.org) - -A Rust library for cross-platform memory mapped IO. - -This is a **fork** of the [memmap-rs](https://github.com/danburkert/memmap-rs) crate. - -## Features - -- [x] file-backed memory maps -- [x] anonymous memory maps -- [x] synchronous and asynchronous flushing -- [x] copy-on-write memory maps -- [x] read-only memory maps -- [x] stack support (`MAP_STACK` on unix) -- [x] executable memory maps -- [ ] huge page support - -A list of supported/tested targets can be found in [Actions](https://github.com/RazrFalcon/memmap2-rs/actions). - -## License - -`memmap2` is primarily distributed under the terms of both the MIT license and the -Apache License (Version 2.0). - -See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details. - -Copyright (c) 2020 Evgeniy Reizner - -Copyright (c) 2015 Dan Burkert diff --git a/vendor/memmap2-0.2.1/examples/cat.rs b/vendor/memmap2-0.2.1/examples/cat.rs deleted file mode 100644 index 34599af2e..000000000 --- a/vendor/memmap2-0.2.1/examples/cat.rs +++ /dev/null @@ -1,23 +0,0 @@ -extern crate memmap2; - -use std::env; -use std::fs::File; -use std::io::{self, Write}; - -use memmap2::Mmap; - -/// Output a file's contents to stdout. The file path must be provided as the first process -/// argument. -fn main() { - let path = env::args() - .nth(1) - .expect("supply a single path as the program argument"); - - let file = File::open(path).expect("failed to open the file"); - - let mmap = unsafe { Mmap::map(&file).expect("failed to map the file") }; - - io::stdout() - .write_all(&mmap[..]) - .expect("failed to output the file contents"); -} diff --git a/vendor/memmap2-0.2.1/src/lib.rs b/vendor/memmap2-0.2.1/src/lib.rs deleted file mode 100644 index b408ba8a2..000000000 --- a/vendor/memmap2-0.2.1/src/lib.rs +++ /dev/null @@ -1,1199 +0,0 @@ -//! A cross-platform Rust API for memory mapped buffers. - -#![doc(html_root_url = "https://docs.rs/memmap2/0.2.1")] - -#[cfg(windows)] -mod windows; -#[cfg(windows)] -use windows::MmapInner; - -#[cfg(unix)] -mod unix; -#[cfg(unix)] -use crate::unix::MmapInner; - -use std::fmt; -use std::fs::File; -use std::io::{Error, ErrorKind, Result}; -use std::ops::{Deref, DerefMut}; -use std::slice; -use std::usize; - -/// A memory map builder, providing advanced options and flags for specifying memory map behavior. -/// -/// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a -/// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`], -/// [`map_copy()`], or [`map_copy_read_only()`]. -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when -/// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g. -/// unlinked) files exist but are platform specific and limited. -/// -/// [`map_anon()`]: MmapOptions::map_anon() -/// [`map()`]: MmapOptions::map() -/// [`map_mut()`]: MmapOptions::map_mut() -/// [`map_exec()`]: MmapOptions::map_exec() -/// [`map_copy()`]: MmapOptions::map_copy() -/// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only() -#[derive(Clone, Debug, Default)] -pub struct MmapOptions { - offset: u64, - len: Option<usize>, - stack: bool, -} - -impl MmapOptions { - /// Creates a new set of options for configuring and creating a memory map. - /// - /// # Example - /// - /// ``` - /// use memmap2::{MmapMut, MmapOptions}; - /// # use std::io::Result; - /// - /// # fn main() -> Result<()> { - /// // Create a new memory map builder. - /// let mut mmap_options = MmapOptions::new(); - /// - /// // Configure the memory map builder using option setters, then create - /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`, - /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`: - /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?; - /// - /// // Use the memory map: - /// mmap.copy_from_slice(b"...data to copy to the memory map..."); - /// # Ok(()) - /// # } - /// ``` - pub fn new() -> MmapOptions { - MmapOptions::default() - } - - /// Configures the memory map to start at byte `offset` from the beginning of the file. - /// - /// This option has no effect on anonymous memory maps. - /// - /// By default, the offset is 0. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// - /// # fn main() -> std::io::Result<()> { - /// let mmap = unsafe { - /// MmapOptions::new() - /// .offset(30) - /// .map(&File::open("LICENSE-APACHE")?)? - /// }; - /// assert_eq!(&b"Apache License"[..], - /// &mmap[..14]); - /// # Ok(()) - /// # } - /// ``` - pub fn offset(&mut self, offset: u64) -> &mut Self { - self.offset = offset; - self - } - - /// Configures the created memory mapped buffer to be `len` bytes long. - /// - /// This option is mandatory for anonymous memory maps. - /// - /// For file-backed memory maps, the length will default to the file length. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// - /// # fn main() -> std::io::Result<()> { - /// let mmap = unsafe { - /// MmapOptions::new() - /// .len(9) - /// .map(&File::open("README.md")?)? - /// }; - /// assert_eq!(&b"# memmap2"[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub fn len(&mut self, len: usize) -> &mut Self { - self.len = Some(len); - self - } - - /// Returns the configured length, or the length of the provided file. - fn get_len(&self, file: &File) -> Result<usize> { - self.len.map(Ok).unwrap_or_else(|| { - let len = file.metadata()?.len() - self.offset; - if len > (usize::MAX as u64) { - return Err(Error::new( - ErrorKind::InvalidData, - "memory map length overflows usize", - )); - } - Ok(len as usize) - }) - } - - /// Configures the anonymous memory map to be suitable for a process or thread stack. - /// - /// This option corresponds to the `MAP_STACK` flag on Linux. - /// - /// This option has no effect on file-backed memory maps. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// - /// # fn main() -> std::io::Result<()> { - /// let stack = MmapOptions::new().stack().len(4096).map_anon(); - /// # Ok(()) - /// # } - /// ``` - pub fn stack(&mut self) -> &mut Self { - self.stack = true; - self - } - - /// Creates a read-only memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Read; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("LICENSE-APACHE")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { - /// MmapOptions::new().map(&file)? - /// }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map(&self, file: &File) -> Result<Mmap> { - MmapInner::map(self.get_len(file)?, file, self.offset).map(|inner| Mmap { inner: inner }) - } - - /// Creates a readable and executable memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - pub unsafe fn map_exec(&self, file: &File) -> Result<Mmap> { - MmapInner::map_exec(self.get_len(file)?, file, self.offset) - .map(|inner| Mmap { inner: inner }) - } - - /// Creates a writeable memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapOptions; - /// # - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("map_mut"); - /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?; - /// file.set_len(13)?; - /// - /// let mut mmap = unsafe { - /// MmapOptions::new().map_mut(&file)? - /// }; - /// - /// mmap.copy_from_slice(b"Hello, world!"); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_mut(&self, file: &File) -> Result<MmapMut> { - MmapInner::map_mut(self.get_len(file)?, file, self.offset) - .map(|inner| MmapMut { inner: inner }) - } - - /// Creates a copy-on-write memory map backed by a file. - /// - /// Data written to the memory map will not be visible by other processes, - /// and will not be carried through to the underlying file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with writable permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Write; - /// - /// # fn main() -> std::io::Result<()> { - /// let file = File::open("LICENSE-APACHE")?; - /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? }; - /// (&mut mmap[..]).write_all(b"Hello, world!")?; - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_copy(&self, file: &File) -> Result<MmapMut> { - MmapInner::map_copy(self.get_len(file)?, file, self.offset) - .map(|inner| MmapMut { inner: inner }) - } - - /// Creates a copy-on-write read-only memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Read; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("README.md")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { - /// MmapOptions::new().map_copy_read_only(&file)? - /// }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_copy_read_only(&self, file: &File) -> Result<Mmap> { - MmapInner::map_copy_read_only(self.get_len(file)?, file, self.offset) - .map(|inner| Mmap { inner: inner }) - } - - /// Creates an anonymous memory map. - /// - /// Note: the memory map length must be configured to be greater than 0 before creating an - /// anonymous memory map using `MmapOptions::len()`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails. - pub fn map_anon(&self) -> Result<MmapMut> { - MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner: inner }) - } - - /// Creates a raw memory map. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - pub fn map_raw(&self, file: &File) -> Result<MmapRaw> { - MmapInner::map_mut(self.get_len(file)?, file, self.offset) - .map(|inner| MmapRaw { inner: inner }) - } -} - -/// A handle to an immutable memory mapped buffer. -/// -/// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use -/// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable -/// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable -/// with [`MmapMut::make_read_only()`]. -/// -/// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the -/// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File` -/// used to create it. For consistency, on some platforms this is achieved by duplicating the -/// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped. -/// -/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping -/// the mapped pages into physical memory) though the details of this are platform specific. -/// -/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send). -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when using -/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked) -/// files exist but are platform specific and limited. -/// -/// ## Example -/// -/// ``` -/// use memmap2::MmapOptions; -/// use std::io::Write; -/// use std::fs::File; -/// -/// # fn main() -> std::io::Result<()> { -/// let file = File::open("README.md")?; -/// let mmap = unsafe { MmapOptions::new().map(&file)? }; -/// assert_eq!(b"# memmap2", &mmap[0..9]); -/// # Ok(()) -/// # } -/// ``` -/// -/// See [`MmapMut`] for the mutable version. -/// -/// [`map()`]: Mmap::map() -pub struct Mmap { - inner: MmapInner, -} - -impl Mmap { - /// Creates a read-only memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use std::fs::File; - /// use std::io::Read; - /// - /// use memmap2::Mmap; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("LICENSE-APACHE")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { Mmap::map(&file)? }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map(file: &File) -> Result<Mmap> { - MmapOptions::new().map(file) - } - - /// Transition the memory map to be writable. - /// - /// If the memory map is file-backed, the file must have been opened with write permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with writable permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use memmap2::Mmap; - /// use std::ops::DerefMut; - /// use std::io::Write; - /// # use std::fs::OpenOptions; - /// - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let file = /* file opened with write permissions */ - /// # OpenOptions::new() - /// # .read(true) - /// # .write(true) - /// # .create(true) - /// # .open(tempdir.path() - /// # .join("make_mut"))?; - /// # file.set_len(128)?; - /// let mmap = unsafe { Mmap::map(&file)? }; - /// // ... use the read-only memory map ... - /// let mut mut_mmap = mmap.make_mut()?; - /// mut_mmap.deref_mut().write_all(b"hello, world!")?; - /// # Ok(()) - /// # } - /// ``` - pub fn make_mut(mut self) -> Result<MmapMut> { - self.inner.make_mut()?; - Ok(MmapMut { inner: self.inner }) - } -} - -impl Deref for Mmap { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) } - } -} - -impl AsRef<[u8]> for Mmap { - #[inline] - fn as_ref(&self) -> &[u8] { - self.deref() - } -} - -impl fmt::Debug for Mmap { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Mmap") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} - -/// A handle to a raw memory mapped buffer. -/// -/// This struct never hands out references to its interior, only raw pointers. -/// This can be helpful when creating shared memory maps between untrusted processes. -pub struct MmapRaw { - inner: MmapInner, -} - -impl MmapRaw { - /// Creates a writeable memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map_raw(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - pub fn map_raw(file: &File) -> Result<MmapRaw> { - MmapOptions::new().map_raw(file) - } - - /// Returns a raw pointer to the memory mapped file. - /// - /// # Safety - /// - /// To safely dereference this pointer, you need to make sure that the file has not been - /// truncated since the memory map was created. - #[inline] - pub fn as_ptr(&self) -> *const u8 { self.inner.ptr() } - - /// Returns an unsafe mutable pointer to the memory mapped file. - /// - /// # Safety - /// - /// To safely dereference this pointer, you need to make sure that the file has not been - /// truncated since the memory map was created. - #[inline] - pub fn as_mut_ptr(&self) -> *mut u8 { self.inner.ptr() as _ } - - /// Returns the length in bytes of the memory map. - /// - /// Note that truncating the file can cause the length to change (and render this value unusable). - #[inline] - pub fn len(&self) -> usize { self.inner.len() } -} - -impl fmt::Debug for MmapRaw { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("MmapRaw") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} - -/// A handle to a mutable memory mapped buffer. -/// -/// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous -/// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use -/// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the -/// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default -/// options are required. -/// -/// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the -/// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File` -/// used to create it. For consistency, on some platforms this is achieved by duplicating the -/// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped. -/// -/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping -/// the mapped pages into physical memory) though the details of this are platform specific. -/// -/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send). -/// -/// See [`Mmap`] for the immutable version. -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when using -/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked) -/// files exist but are platform specific and limited. -pub struct MmapMut { - inner: MmapInner, -} - -impl MmapMut { - /// Creates a writeable memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map_mut(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapMut; - /// # - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("map_mut"); - /// let file = OpenOptions::new() - /// .read(true) - /// .write(true) - /// .create(true) - /// .open(&path)?; - /// file.set_len(13)?; - /// - /// let mut mmap = unsafe { MmapMut::map_mut(&file)? }; - /// - /// mmap.copy_from_slice(b"Hello, world!"); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_mut(file: &File) -> Result<MmapMut> { - MmapOptions::new().map_mut(file) - } - - /// Creates an anonymous memory map. - /// - /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails. - pub fn map_anon(length: usize) -> Result<MmapMut> { - MmapOptions::new().len(length).map_anon() - } - - /// Flushes outstanding memory map modifications to disk. - /// - /// When this method returns with a non-error result, all outstanding changes to a file-backed - /// memory map are guaranteed to be durably stored. The file's metadata (including last - /// modification timestamp) may not be updated. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::io::Write; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapMut; - /// - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("flush"); - /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?; - /// file.set_len(128)?; - /// - /// let mut mmap = unsafe { MmapMut::map_mut(&file)? }; - /// - /// (&mut mmap[..]).write_all(b"Hello, world!")?; - /// mmap.flush()?; - /// # Ok(()) - /// # } - /// ``` - pub fn flush(&self) -> Result<()> { - let len = self.len(); - self.inner.flush(0, len) - } - - /// Asynchronously flushes outstanding memory map modifications to disk. - /// - /// This method initiates flushing modified pages to durable storage, but it will not wait for - /// the operation to complete before returning. The file's metadata (including last - /// modification timestamp) may not be updated. - pub fn flush_async(&self) -> Result<()> { - let len = self.len(); - self.inner.flush_async(0, len) - } - - /// Flushes outstanding memory map modifications in the range to disk. - /// - /// The offset and length must be in the bounds of the memory map. - /// - /// When this method returns with a non-error result, all outstanding changes to a file-backed - /// memory in the range are guaranteed to be durable stored. The file's metadata (including - /// last modification timestamp) may not be updated. It is not guaranteed the only the changes - /// in the specified range are flushed; other outstanding changes to the memory map may be - /// flushed as well. - pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> { - self.inner.flush(offset, len) - } - - /// Asynchronously flushes outstanding memory map modifications in the range to disk. - /// - /// The offset and length must be in the bounds of the memory map. - /// - /// This method initiates flushing modified pages to durable storage, but it will not wait for - /// the operation to complete before returning. The file's metadata (including last - /// modification timestamp) may not be updated. It is not guaranteed that the only changes - /// flushed are those in the specified range; other outstanding changes to the memory map may - /// be flushed as well. - pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> { - self.inner.flush_async(offset, len) - } - - /// Returns an immutable version of this memory mapped buffer. - /// - /// If the memory map is file-backed, the file must have been opened with read permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file has not been opened with read permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # - /// use std::io::Write; - /// use std::path::PathBuf; - /// - /// use memmap2::{Mmap, MmapMut}; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut mmap = MmapMut::map_anon(128)?; - /// - /// (&mut mmap[..]).write(b"Hello, world!")?; - /// - /// let mmap: Mmap = mmap.make_read_only()?; - /// # Ok(()) - /// # } - /// ``` - pub fn make_read_only(mut self) -> Result<Mmap> { - self.inner.make_read_only()?; - Ok(Mmap { inner: self.inner }) - } - - /// Transition the memory map to be readable and executable. - /// - /// If the memory map is file-backed, the file must have been opened with execute permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file has not been opened with execute permissions. - pub fn make_exec(mut self) -> Result<Mmap> { - self.inner.make_exec()?; - Ok(Mmap { inner: self.inner }) - } -} - -impl Deref for MmapMut { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) } - } -} - -impl DerefMut for MmapMut { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) } - } -} - -impl AsRef<[u8]> for MmapMut { - #[inline] - fn as_ref(&self) -> &[u8] { - self.deref() - } -} - -impl AsMut<[u8]> for MmapMut { - #[inline] - fn as_mut(&mut self) -> &mut [u8] { - self.deref_mut() - } -} - -impl fmt::Debug for MmapMut { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("MmapMut") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} - -#[cfg(test)] -mod test { - extern crate tempdir; - - use std::fs::OpenOptions; - use std::io::{Read, Write}; - #[cfg(windows)] - use std::os::windows::fs::OpenOptionsExt; - use std::sync::Arc; - use std::thread; - - #[cfg(windows)] - const GENERIC_ALL: u32 = 0x10000000; - - use super::{Mmap, MmapMut, MmapOptions}; - - #[test] - fn map_file() { - let expected_len = 128; - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - - file.set_len(expected_len as u64).unwrap(); - - let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() }; - let len = mmap.len(); - assert_eq!(expected_len, len); - - let zeros = vec![0; len]; - let incr: Vec<u8> = (0..len as u8).collect(); - - // check that the mmap is empty - assert_eq!(&zeros[..], &mmap[..]); - - // write values into the mmap - (&mut mmap[..]).write_all(&incr[..]).unwrap(); - - // read values back - assert_eq!(&incr[..], &mmap[..]); - } - - /// Checks that a 0-length file will not be mapped. - #[test] - fn map_empty_file() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - let mmap = unsafe { Mmap::map(&file) }; - assert!(mmap.is_err()); - } - - #[test] - fn map_anon() { - let expected_len = 128; - let mut mmap = MmapMut::map_anon(expected_len).unwrap(); - let len = mmap.len(); - assert_eq!(expected_len, len); - - let zeros = vec![0; len]; - let incr: Vec<u8> = (0..len as u8).collect(); - - // check that the mmap is empty - assert_eq!(&zeros[..], &mmap[..]); - - // write values into the mmap - (&mut mmap[..]).write_all(&incr[..]).unwrap(); - - // read values back - assert_eq!(&incr[..], &mmap[..]); - } - - #[test] - fn map_anon_zero_len() { - assert!(MmapOptions::new().map_anon().is_err()) - } - - #[test] - fn file_write() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let mut file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - file.set_len(128).unwrap(); - - let write = b"abc123"; - let mut read = [0u8; 6]; - - let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() }; - (&mut mmap[..]).write_all(write).unwrap(); - mmap.flush().unwrap(); - - file.read(&mut read).unwrap(); - assert_eq!(write, &read); - } - - #[test] - fn flush_range() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - file.set_len(128).unwrap(); - let write = b"abc123"; - - let mut mmap = unsafe { - MmapOptions::new() - .offset(2) - .len(write.len()) - .map_mut(&file) - .unwrap() - }; - (&mut mmap[..]).write_all(write).unwrap(); - mmap.flush_range(0, write.len()).unwrap(); - } - - #[test] - fn map_copy() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let mut file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - file.set_len(128).unwrap(); - - let nulls = b"\0\0\0\0\0\0"; - let write = b"abc123"; - let mut read = [0u8; 6]; - - let mut mmap = unsafe { MmapOptions::new().map_copy(&file).unwrap() }; - - (&mut mmap[..]).write(write).unwrap(); - mmap.flush().unwrap(); - - // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); - assert_eq!(write, &read); - - // The file does not contain the write - file.read(&mut read).unwrap(); - assert_eq!(nulls, &read); - - // another mmap does not contain the write - let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() }; - (&mmap2[..]).read(&mut read).unwrap(); - assert_eq!(nulls, &read); - } - - #[test] - fn map_copy_read_only() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - file.set_len(128).unwrap(); - - let nulls = b"\0\0\0\0\0\0"; - let mut read = [0u8; 6]; - - let mmap = unsafe { MmapOptions::new().map_copy_read_only(&file).unwrap() }; - (&mmap[..]).read(&mut read).unwrap(); - assert_eq!(nulls, &read); - - let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() }; - (&mmap2[..]).read(&mut read).unwrap(); - assert_eq!(nulls, &read); - } - - #[test] - fn map_offset() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&path) - .unwrap(); - - let offset = u32::max_value() as u64 + 2; - let len = 5432; - file.set_len(offset + len as u64).unwrap(); - - // Check inferred length mmap. - let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file).unwrap() }; - assert_eq!(len, mmap.len()); - - // Check explicit length mmap. - let mut mmap = unsafe { - MmapOptions::new() - .offset(offset) - .len(len) - .map_mut(&file) - .unwrap() - }; - assert_eq!(len, mmap.len()); - - let zeros = vec![0; len]; - let incr: Vec<_> = (0..len).map(|i| i as u8).collect(); - - // check that the mmap is empty - assert_eq!(&zeros[..], &mmap[..]); - - // write values into the mmap - (&mut mmap[..]).write_all(&incr[..]).unwrap(); - - // read values back - assert_eq!(&incr[..], &mmap[..]); - } - - #[test] - fn index() { - let mut mmap = MmapMut::map_anon(128).unwrap(); - mmap[0] = 42; - assert_eq!(42, mmap[0]); - } - - #[test] - fn sync_send() { - let mmap = Arc::new(MmapMut::map_anon(129).unwrap()); - thread::spawn(move || { - &mmap[..]; - }); - } - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn jit_x86(mut mmap: MmapMut) { - use std::mem; - mmap[0] = 0xB8; // mov eax, 0xAB - mmap[1] = 0xAB; - mmap[2] = 0x00; - mmap[3] = 0x00; - mmap[4] = 0x00; - mmap[5] = 0xC3; // ret - - let mmap = mmap.make_exec().expect("make_exec"); - - let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) }; - assert_eq!(jitfn(), 0xab); - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn jit_x86_anon() { - jit_x86(MmapMut::map_anon(4096).unwrap()); - } - - #[test] - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - fn jit_x86_file() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let mut options = OpenOptions::new(); - #[cfg(windows)] - options.access_mode(GENERIC_ALL); - - let file = options - .read(true) - .write(true) - .create(true) - .open(&tempdir.path().join("jit_x86")) - .expect("open"); - - file.set_len(4096).expect("set_len"); - jit_x86(unsafe { MmapMut::map_mut(&file).expect("map_mut") }); - } - - #[test] - fn mprotect_file() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let mut options = OpenOptions::new(); - #[cfg(windows)] - options.access_mode(GENERIC_ALL); - - let mut file = options - .read(true) - .write(true) - .create(true) - .open(&path) - .expect("open"); - file.set_len(256 as u64).expect("set_len"); - - let mmap = unsafe { MmapMut::map_mut(&file).expect("map_mut") }; - - let mmap = mmap.make_read_only().expect("make_read_only"); - let mut mmap = mmap.make_mut().expect("make_mut"); - - let write = b"abc123"; - let mut read = [0u8; 6]; - - (&mut mmap[..]).write(write).unwrap(); - mmap.flush().unwrap(); - - // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); - assert_eq!(write, &read); - - // The file should contain the write - file.read(&mut read).unwrap(); - assert_eq!(write, &read); - - // another mmap should contain the write - let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() }; - (&mmap2[..]).read(&mut read).unwrap(); - assert_eq!(write, &read); - - let mmap = mmap.make_exec().expect("make_exec"); - - drop(mmap); - } - - #[test] - fn mprotect_copy() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmap"); - - let mut options = OpenOptions::new(); - #[cfg(windows)] - options.access_mode(GENERIC_ALL); - - let mut file = options - .read(true) - .write(true) - .create(true) - .open(&path) - .expect("open"); - file.set_len(256 as u64).expect("set_len"); - - let mmap = unsafe { MmapOptions::new().map_copy(&file).expect("map_mut") }; - - let mmap = mmap.make_read_only().expect("make_read_only"); - let mut mmap = mmap.make_mut().expect("make_mut"); - - let nulls = b"\0\0\0\0\0\0"; - let write = b"abc123"; - let mut read = [0u8; 6]; - - (&mut mmap[..]).write(write).unwrap(); - mmap.flush().unwrap(); - - // The mmap contains the write - (&mmap[..]).read(&mut read).unwrap(); - assert_eq!(write, &read); - - // The file does not contain the write - file.read(&mut read).unwrap(); - assert_eq!(nulls, &read); - - // another mmap does not contain the write - let mmap2 = unsafe { MmapOptions::new().map(&file).unwrap() }; - (&mmap2[..]).read(&mut read).unwrap(); - assert_eq!(nulls, &read); - - let mmap = mmap.make_exec().expect("make_exec"); - - drop(mmap); - } - - #[test] - fn mprotect_anon() { - let mmap = MmapMut::map_anon(256).expect("map_mut"); - - let mmap = mmap.make_read_only().expect("make_read_only"); - let mmap = mmap.make_mut().expect("make_mut"); - let mmap = mmap.make_exec().expect("make_exec"); - drop(mmap); - } - - #[test] - fn raw() { - let tempdir = tempdir::TempDir::new("mmap").unwrap(); - let path = tempdir.path().join("mmapraw"); - - let mut options = OpenOptions::new(); - let mut file = options - .read(true) - .write(true) - .create(true) - .open(&path) - .expect("open"); - file.write(b"abc123").unwrap(); - let mmap = MmapOptions::new().map_raw(&file).unwrap(); - assert_eq!(mmap.len(), 6); - assert!(!mmap.as_ptr().is_null()); - assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a'); - } -} diff --git a/vendor/memmap2-0.2.1/src/unix.rs b/vendor/memmap2-0.2.1/src/unix.rs deleted file mode 100644 index d8437a921..000000000 --- a/vendor/memmap2-0.2.1/src/unix.rs +++ /dev/null @@ -1,224 +0,0 @@ -extern crate libc; - -use std::fs::File; -use std::os::unix::io::{AsRawFd, RawFd}; -use std::{io, ptr}; - -#[cfg(any( - all(target_os = "linux", not(target_arch = "mips")), - target_os = "freebsd", - target_os = "android" -))] -const MAP_STACK: libc::c_int = libc::MAP_STACK; - -#[cfg(not(any( - all(target_os = "linux", not(target_arch = "mips")), - target_os = "freebsd", - target_os = "android" -)))] -const MAP_STACK: libc::c_int = 0; - -pub struct MmapInner { - ptr: *mut libc::c_void, - len: usize, -} - -impl MmapInner { - /// Creates a new `MmapInner`. - /// - /// This is a thin wrapper around the `mmap` sytem call. - fn new( - len: usize, - prot: libc::c_int, - flags: libc::c_int, - file: RawFd, - offset: u64, - ) -> io::Result<MmapInner> { - let alignment = offset % page_size() as u64; - let aligned_offset = offset - alignment; - let aligned_len = len + alignment as usize; - if aligned_len == 0 { - // Normally the OS would catch this, but it segfaults under QEMU. - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "memory map must have a non-zero length", - )); - } - - unsafe { - let ptr = libc::mmap( - ptr::null_mut(), - aligned_len as libc::size_t, - prot, - flags, - file, - aligned_offset as libc::off_t, - ); - - if ptr == libc::MAP_FAILED { - Err(io::Error::last_os_error()) - } else { - Ok(MmapInner { - ptr: ptr.offset(alignment as isize), - len: len, - }) - } - } - } - - pub fn map(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - MmapInner::new( - len, - libc::PROT_READ, - libc::MAP_SHARED, - file.as_raw_fd(), - offset, - ) - } - - pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - MmapInner::new( - len, - libc::PROT_READ | libc::PROT_EXEC, - libc::MAP_SHARED, - file.as_raw_fd(), - offset, - ) - } - - pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - MmapInner::new( - len, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_SHARED, - file.as_raw_fd(), - offset, - ) - } - - pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - MmapInner::new( - len, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_PRIVATE, - file.as_raw_fd(), - offset, - ) - } - - pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - MmapInner::new( - len, - libc::PROT_READ, - libc::MAP_PRIVATE, - file.as_raw_fd(), - offset, - ) - } - - /// Open an anonymous memory map. - pub fn map_anon(len: usize, stack: bool) -> io::Result<MmapInner> { - let stack = if stack { MAP_STACK } else { 0 }; - MmapInner::new( - len, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_PRIVATE | libc::MAP_ANON | stack, - -1, - 0, - ) - } - - pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> { - let alignment = (self.ptr as usize + offset) % page_size(); - let offset = offset as isize - alignment as isize; - let len = len + alignment; - let result = - unsafe { libc::msync(self.ptr.offset(offset), len as libc::size_t, libc::MS_SYNC) }; - if result == 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - - pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> { - let alignment = offset % page_size(); - let aligned_offset = offset - alignment; - let aligned_len = len + alignment; - let result = unsafe { - libc::msync( - self.ptr.offset(aligned_offset as isize), - aligned_len as libc::size_t, - libc::MS_ASYNC, - ) - }; - if result == 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - - fn mprotect(&mut self, prot: libc::c_int) -> io::Result<()> { - unsafe { - let alignment = self.ptr as usize % page_size(); - let ptr = self.ptr.offset(-(alignment as isize)); - let len = self.len + alignment; - if libc::mprotect(ptr, len, prot) == 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - } - - pub fn make_read_only(&mut self) -> io::Result<()> { - self.mprotect(libc::PROT_READ) - } - - pub fn make_exec(&mut self) -> io::Result<()> { - self.mprotect(libc::PROT_READ | libc::PROT_EXEC) - } - - pub fn make_mut(&mut self) -> io::Result<()> { - self.mprotect(libc::PROT_READ | libc::PROT_WRITE) - } - - #[inline] - pub fn ptr(&self) -> *const u8 { - self.ptr as *const u8 - } - - #[inline] - pub fn mut_ptr(&mut self) -> *mut u8 { - self.ptr as *mut u8 - } - - #[inline] - pub fn len(&self) -> usize { - self.len - } -} - -impl Drop for MmapInner { - fn drop(&mut self) { - let alignment = self.ptr as usize % page_size(); - unsafe { - assert!( - libc::munmap( - self.ptr.offset(-(alignment as isize)), - (self.len + alignment) as libc::size_t - ) == 0, - "unable to unmap mmap: {}", - io::Error::last_os_error() - ); - } - } -} - -unsafe impl Sync for MmapInner {} -unsafe impl Send for MmapInner {} - -fn page_size() -> usize { - unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } -} diff --git a/vendor/memmap2-0.2.1/src/windows.rs b/vendor/memmap2-0.2.1/src/windows.rs deleted file mode 100644 index a0f3d552a..000000000 --- a/vendor/memmap2-0.2.1/src/windows.rs +++ /dev/null @@ -1,426 +0,0 @@ -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use std::fs::File; -use std::os::raw::c_void; -use std::os::windows::io::{AsRawHandle, RawHandle}; -use std::{io, mem, ptr}; - -type BOOL = i32; -type WORD = u16; -type DWORD = u32; -type WCHAR = u16; -type HANDLE = *mut c_void; -type LPVOID = *mut c_void; -type LPCVOID = *const c_void; -type ULONG_PTR = usize; -type SIZE_T = ULONG_PTR; -type LPCWSTR = *const WCHAR; -type PDWORD = *mut DWORD; -type DWORD_PTR = ULONG_PTR; -type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; -type LPSYSTEM_INFO = *mut SYSTEM_INFO; - -const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE; - -const STANDARD_RIGHTS_REQUIRED: DWORD = 0x000F0000; - -const SECTION_QUERY: DWORD = 0x0001; -const SECTION_MAP_WRITE: DWORD = 0x0002; -const SECTION_MAP_READ: DWORD = 0x0004; -const SECTION_MAP_EXECUTE: DWORD = 0x0008; -const SECTION_EXTEND_SIZE: DWORD = 0x0010; -const SECTION_MAP_EXECUTE_EXPLICIT: DWORD = 0x0020; -const SECTION_ALL_ACCESS: DWORD = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY - | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE; - -const PAGE_READONLY: DWORD = 0x02; -const PAGE_READWRITE: DWORD = 0x04; -const PAGE_WRITECOPY: DWORD = 0x08; -const PAGE_EXECUTE_READ: DWORD = 0x20; -const PAGE_EXECUTE_READWRITE: DWORD = 0x40; -const PAGE_EXECUTE_WRITECOPY: DWORD = 0x80; - -const FILE_MAP_WRITE: DWORD = SECTION_MAP_WRITE; -const FILE_MAP_READ: DWORD = SECTION_MAP_READ; -const FILE_MAP_ALL_ACCESS: DWORD = SECTION_ALL_ACCESS; -const FILE_MAP_EXECUTE: DWORD = SECTION_MAP_EXECUTE_EXPLICIT; -const FILE_MAP_COPY: DWORD = 0x00000001; - -#[repr(C)] -#[derive(Clone, Copy)] -struct SECURITY_ATTRIBUTES { - nLength: DWORD, - lpSecurityDescriptor: LPVOID, - bInheritHandle: BOOL, -} - -#[repr(C)] -#[derive(Clone, Copy)] -struct SYSTEM_INFO_u_s { - wProcessorArchitecture: WORD, - wReserved: WORD, -} - -#[repr(C)] -#[derive(Clone, Copy)] -struct SYSTEM_INFO_u([u32; 1]); - -#[repr(C)] -#[derive(Clone, Copy)] -struct SYSTEM_INFO { - u: SYSTEM_INFO_u, - dwPageSize: DWORD, - lpMinimumApplicationAddress: LPVOID, - lpMaximumApplicationAddress: LPVOID, - dwActiveProcessorMask: DWORD_PTR, - dwNumberOfProcessors: DWORD, - dwProcessorType: DWORD, - dwAllocationGranularity: DWORD, - wProcessorLevel: WORD, - wProcessorRevision: WORD, -} - -extern "system" { - fn CloseHandle( - hObject: HANDLE, - ) -> BOOL; - - fn CreateFileMappingW( - hFile: HANDLE, - lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, - flProtect: DWORD, - dwMaximumSizeHigh: DWORD, - dwMaximumSizeLow: DWORD, - lpName: LPCWSTR, - ) -> HANDLE; - - fn FlushViewOfFile( - lpBaseAddress: LPCVOID, - dwNumberOfBytesToFlush: SIZE_T, - ) -> BOOL; - - fn UnmapViewOfFile( - lpBaseAddress: LPCVOID, - ) -> BOOL; - - fn MapViewOfFile( - hFileMappingObject: HANDLE, - dwDesiredAccess: DWORD, - dwFileOffsetHigh: DWORD, - dwFileOffsetLow: DWORD, - dwNumberOfBytesToMap: SIZE_T, - ) -> LPVOID; - - fn VirtualProtect( - lpAddress: LPVOID, - dwSize: SIZE_T, - flNewProtect: DWORD, - lpflOldProtect: PDWORD, - ) -> BOOL; - - fn GetSystemInfo( - lpSystemInfo: LPSYSTEM_INFO, - ); -} - -pub struct MmapInner { - file: Option<File>, - ptr: *mut c_void, - len: usize, - copy: bool, -} - -impl MmapInner { - /// Creates a new `MmapInner`. - /// - /// This is a thin wrapper around the `CreateFileMappingW` and `MapViewOfFile` system calls. - pub fn new( - file: &File, - protect: DWORD, - access: DWORD, - offset: u64, - len: usize, - copy: bool, - ) -> io::Result<MmapInner> { - let alignment = offset % allocation_granularity() as u64; - let aligned_offset = offset - alignment as u64; - let aligned_len = len + alignment as usize; - - unsafe { - let handle = CreateFileMappingW( - file.as_raw_handle(), - ptr::null_mut(), - protect, - 0, - 0, - ptr::null(), - ); - if handle == ptr::null_mut() { - return Err(io::Error::last_os_error()); - } - - let ptr = MapViewOfFile( - handle, - access, - (aligned_offset >> 16 >> 16) as DWORD, - (aligned_offset & 0xffffffff) as DWORD, - aligned_len as SIZE_T, - ); - CloseHandle(handle); - - if ptr == ptr::null_mut() { - Err(io::Error::last_os_error()) - } else { - Ok(MmapInner { - file: Some(file.try_clone()?), - ptr: ptr.offset(alignment as isize), - len: len as usize, - copy: copy, - }) - } - } - } - - pub fn map(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE); - let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ); - let mut access = FILE_MAP_READ; - let protection = match (write, exec) { - (true, true) => { - access |= FILE_MAP_WRITE | FILE_MAP_EXECUTE; - PAGE_EXECUTE_READWRITE - } - (true, false) => { - access |= FILE_MAP_WRITE; - PAGE_READWRITE - } - (false, true) => { - access |= FILE_MAP_EXECUTE; - PAGE_EXECUTE_READ - } - (false, false) => PAGE_READONLY, - }; - - let mut inner = MmapInner::new(file, protection, access, offset, len, false)?; - if write || exec { - inner.make_read_only()?; - } - Ok(inner) - } - - pub fn map_exec(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE); - let mut access = FILE_MAP_READ | FILE_MAP_EXECUTE; - let protection = if write { - access |= FILE_MAP_WRITE; - PAGE_EXECUTE_READWRITE - } else { - PAGE_EXECUTE_READ - }; - - let mut inner = MmapInner::new(file, protection, access, offset, len, false)?; - if write { - inner.make_exec()?; - } - Ok(inner) - } - - pub fn map_mut(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ); - let mut access = FILE_MAP_READ | FILE_MAP_WRITE; - let protection = if exec { - access |= FILE_MAP_EXECUTE; - PAGE_EXECUTE_READWRITE - } else { - PAGE_READWRITE - }; - - let mut inner = MmapInner::new(file, protection, access, offset, len, false)?; - if exec { - inner.make_mut()?; - } - Ok(inner) - } - - pub fn map_copy(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READWRITE); - let mut access = FILE_MAP_COPY; - let protection = if exec { - access |= FILE_MAP_EXECUTE; - PAGE_EXECUTE_WRITECOPY - } else { - PAGE_WRITECOPY - }; - - let mut inner = MmapInner::new(file, protection, access, offset, len, true)?; - if exec { - inner.make_mut()?; - } - Ok(inner) - } - - pub fn map_copy_read_only(len: usize, file: &File, offset: u64) -> io::Result<MmapInner> { - let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE); - let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ); - let mut access = FILE_MAP_COPY; - let protection = if exec { - access |= FILE_MAP_EXECUTE; - PAGE_EXECUTE_WRITECOPY - } else { - PAGE_WRITECOPY - }; - - let mut inner = MmapInner::new(file, protection, access, offset, len, true)?; - if write || exec { - inner.make_read_only()?; - } - Ok(inner) - } - - pub fn map_anon(len: usize, _stack: bool) -> io::Result<MmapInner> { - unsafe { - // Create a mapping and view with maximum access permissions, then use `VirtualProtect` - // to set the actual `Protection`. This way, we can set more permissive protection later - // on. - // Also see https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx - - let handle = CreateFileMappingW( - INVALID_HANDLE_VALUE, - ptr::null_mut(), - PAGE_EXECUTE_READWRITE, - (len >> 16 >> 16) as DWORD, - (len & 0xffffffff) as DWORD, - ptr::null(), - ); - if handle == ptr::null_mut() { - return Err(io::Error::last_os_error()); - } - let access = FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE; - let ptr = MapViewOfFile(handle, access, 0, 0, len as SIZE_T); - CloseHandle(handle); - - if ptr == ptr::null_mut() { - return Err(io::Error::last_os_error()); - } - - let mut old = 0; - let result = VirtualProtect(ptr, len as SIZE_T, PAGE_READWRITE, &mut old); - if result != 0 { - Ok(MmapInner { - file: None, - ptr: ptr, - len: len as usize, - copy: false, - }) - } else { - Err(io::Error::last_os_error()) - } - } - } - - pub fn flush(&self, offset: usize, len: usize) -> io::Result<()> { - self.flush_async(offset, len)?; - if let Some(ref file) = self.file { - file.sync_data()?; - } - Ok(()) - } - - pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> { - let result = unsafe { FlushViewOfFile(self.ptr.offset(offset as isize), len as SIZE_T) }; - if result != 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - - fn virtual_protect(&mut self, protect: DWORD) -> io::Result<()> { - unsafe { - let alignment = self.ptr as usize % allocation_granularity(); - let ptr = self.ptr.offset(-(alignment as isize)); - let aligned_len = self.len as SIZE_T + alignment as SIZE_T; - - let mut old = 0; - let result = VirtualProtect(ptr, aligned_len, protect, &mut old); - - if result != 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) - } - } - } - - pub fn make_read_only(&mut self) -> io::Result<()> { - self.virtual_protect(PAGE_READONLY) - } - - pub fn make_exec(&mut self) -> io::Result<()> { - if self.copy { - self.virtual_protect(PAGE_EXECUTE_WRITECOPY) - } else { - self.virtual_protect(PAGE_EXECUTE_READ) - } - } - - pub fn make_mut(&mut self) -> io::Result<()> { - if self.copy { - self.virtual_protect(PAGE_WRITECOPY) - } else { - self.virtual_protect(PAGE_READWRITE) - } - } - - #[inline] - pub fn ptr(&self) -> *const u8 { - self.ptr as *const u8 - } - - #[inline] - pub fn mut_ptr(&mut self) -> *mut u8 { - self.ptr as *mut u8 - } - - #[inline] - pub fn len(&self) -> usize { - self.len - } -} - -impl Drop for MmapInner { - fn drop(&mut self) { - let alignment = self.ptr as usize % allocation_granularity(); - unsafe { - let ptr = self.ptr.offset(-(alignment as isize)); - assert!( - UnmapViewOfFile(ptr) != 0, - "unable to unmap mmap: {}", - io::Error::last_os_error() - ); - } - } -} - -unsafe impl Sync for MmapInner {} -unsafe impl Send for MmapInner {} - -fn protection_supported(handle: RawHandle, protection: DWORD) -> bool { - unsafe { - let handle = CreateFileMappingW(handle, ptr::null_mut(), protection, 0, 0, ptr::null()); - if handle == ptr::null_mut() { - return false; - } - CloseHandle(handle); - true - } -} - -fn allocation_granularity() -> usize { - unsafe { - let mut info = mem::zeroed(); - GetSystemInfo(&mut info); - return info.dwAllocationGranularity as usize; - } -} |