summaryrefslogtreecommitdiffstats
path: root/vendor/memmap2-0.2.1
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
commita0b8f38ab54ac451646aa00cd5e91b6c76f22a84 (patch)
treefc451898ccaf445814e26b46664d78702178101d /vendor/memmap2-0.2.1
parentAdding debian version 1.71.1+dfsg1-2. (diff)
downloadrustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.tar.xz
rustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.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.json1
-rw-r--r--vendor/memmap2-0.2.1/CHANGELOG.md31
-rw-r--r--vendor/memmap2-0.2.1/Cargo.lock99
-rw-r--r--vendor/memmap2-0.2.1/Cargo.toml26
-rw-r--r--vendor/memmap2-0.2.1/LICENSE-APACHE201
-rw-r--r--vendor/memmap2-0.2.1/LICENSE-MIT26
-rw-r--r--vendor/memmap2-0.2.1/README.md33
-rw-r--r--vendor/memmap2-0.2.1/examples/cat.rs23
-rw-r--r--vendor/memmap2-0.2.1/src/lib.rs1199
-rw-r--r--vendor/memmap2-0.2.1/src/unix.rs224
-rw-r--r--vendor/memmap2-0.2.1/src/windows.rs426
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;
- }
-}