mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1774512 - Update memmap2 to 0.5. r=emilio,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D149463
This commit is contained in:
parent
a211cd2aea
commit
504fed29a9
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -3213,14 +3213,14 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
name = "memmap2"
|
||||
version = "0.2.999"
|
||||
dependencies = [
|
||||
"memmap2 0.3.1",
|
||||
"memmap2 0.5.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.3.1"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"
|
||||
checksum = "d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@ -4237,7 +4237,7 @@ dependencies = [
|
||||
name = "profiler_helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"memmap2 0.3.1",
|
||||
"memmap2 0.5.4",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"thin-vec",
|
||||
|
@ -8,4 +8,4 @@ license = "MPL-2.0"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
memmap2 = "0.3"
|
||||
memmap2 = "0.5"
|
||||
|
@ -896,7 +896,7 @@ version = "2.5.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[unaudited.memmap2]]
|
||||
version = "0.3.1"
|
||||
version = "0.5.4"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[unaudited.memoffset]]
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"CHANGELOG.md":"1d984b7fd11609a7dafd72c48ae294aa6c0cd202c45797c4e5bbb9e861ef4334","Cargo.lock":"589809de388088d9ef97fad54e41d817013fae9d861029bf564181ca3a4fd973","Cargo.toml":"f9e95c4b10ade059adbdc85235f631cb45fa5e6386cdc928713aa3e9f93319b8","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"a318cac19725dfbf39890da55f6a48fcb11a32790819c66d776eaeb20fb03d50","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/lib.rs":"fd69a723368ccf3656877230328dbbbef5778061f0d73567c434c111e97078bd","src/stub.rs":"6041ed9bbc6186e05a04ed3a8e5dbcb7ad8feb0135e617a3b0f1f09134ebcdf8","src/unix.rs":"6e6871ccfe0b0d56ba23400c0b45878433eb033d1a080dbf9d524923d76e4b9a","src/windows.rs":"1028d14387456fa785d2a31d8198794e2d4fe109f9ce8422610cc1bd26ace57c"},"package":"00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"}
|
||||
{"files":{"CHANGELOG.md":"9a280d0719b9d9a1fb12d31a2da544d103cb15f01ee2cf40bdcf28c6484eb1b8","Cargo.lock":"47b6feef3907ecbd586b49aadff92eaf84695d7508214210978fbf58b4f00ab6","Cargo.toml":"b93bec2a5377b79002ab53089a9ea9c0a8107f25c1dfb796ba0c01a50e7a1dec","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"c7b3cd928f0d1a10faa255e2f84a2a06636e55ea3e7edd4f6334dd9215151205","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/advice.rs":"194bfd6a32495f6b0c739d083b06230ae656927767f15c1b49b245b63431cc4d","src/lib.rs":"2fa8c6162297441c82471132b9e26d3effcb9c06ae414a0104f9d871eba0aa00","src/stub.rs":"f276bb5e4bc29c2129ebc660b01a1de173b9575e2e866ea5a34e0ee6318f1177","src/unix.rs":"4fa52c514f15dd5e990e03671599a0c3f15770b8fb5f8fea3ea6333766b1e31c","src/windows.rs":"73838f8b2dc8b0c8d37045db36c3c7eb2dc00e6f5d5a7bc0c693bdb55d3ec721"},"package":"d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae"}
|
60
third_party/rust/memmap2/CHANGELOG.md
vendored
60
third_party/rust/memmap2/CHANGELOG.md
vendored
@ -6,6 +6,56 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.5.4] - 2022-06-04
|
||||
### Added
|
||||
- Add madvice operations specific to Darwin. [@turbocool3r](https://github.com/turbocool3r)
|
||||
- Implement common traits for the `Advice` enum. [@nyurik](https://github.com/nyurik)
|
||||
|
||||
### Changed
|
||||
- Make stub implementation Infallible. [@coolreader18](https://github.com/coolreader18)
|
||||
- Use `tempfile` crate instead of `tempdir` in tests.
|
||||
[@alexanderkjall](https://github.com/alexanderkjall)
|
||||
|
||||
## [0.5.3] - 2022-02-10
|
||||
### Added
|
||||
- `Mmap::advise` and `MmapMut::advise`. [@nyurik](https://github.com/nyurik)
|
||||
|
||||
## [0.5.2] - 2022-01-10
|
||||
### Added
|
||||
- `flush`, `flush_async`, `flush_range` and `flush_async_range` to `MmapRaw` matching
|
||||
the corresponding methods on `MmapMut`.
|
||||
[@cberner](https://github.com/cberner)
|
||||
|
||||
## [0.5.1] - 2022-01-09
|
||||
### Fixed
|
||||
- Explicitly call `fstat64` on Linux, emscripten and l4re targets.
|
||||
[@adamreichold](https://github.com/adamreichold)
|
||||
|
||||
## [0.5.0] - 2021-09-19
|
||||
### Added
|
||||
- `MmapOptions` accepts any type that supports `RawHandle`/`RawFd` returning now.
|
||||
This allows using `memmap2` not only with Rust std types, but also with
|
||||
[async-std](https://github.com/async-rs/async-std) one.
|
||||
[@adamreichold](https://github.com/adamreichold)
|
||||
- (unix) Memoize page size to avoid repeatedly calling into sysconf machinery.
|
||||
[@adamreichold](https://github.com/adamreichold)
|
||||
|
||||
### Changed
|
||||
- (win) Use `std::os::windows::io::AsRawHandle` directly, without relying on `std::fs::File`.
|
||||
[@adamreichold](https://github.com/adamreichold)
|
||||
- Do not panic when failing to release resources in Drop impls.
|
||||
[@adamreichold](https://github.com/adamreichold)
|
||||
|
||||
## [0.4.0] - 2021-09-16
|
||||
### Added
|
||||
- Optional [`StableDeref`](https://github.com/storyyeller/stable_deref_trait) support.
|
||||
[@SimonSapin](https://github.com/SimonSapin)
|
||||
|
||||
### Changed
|
||||
- Mapping of zero-sized files is no longer an error.
|
||||
[@SimonSapin](https://github.com/SimonSapin)
|
||||
- MSRV changed from 1.31 to 1.36
|
||||
|
||||
## [0.3.1] - 2021-08-15
|
||||
### Fixed
|
||||
- Integer overflow during file length calculation on 32bit targets.
|
||||
@ -38,7 +88,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
### Changed
|
||||
- MSRV is 1.31 now (edition 2018).
|
||||
- Make anonymous memory maps private by default on unix. [@CensoredUsername](https://github.com/CensoredUsername)
|
||||
- Add `map_copy_read_only`. [@zserik](https://github.com/zserik)
|
||||
- Add `map_copy_read_only`. [@zseri](https://github.com/zseri)
|
||||
|
||||
## 0.1.0 - 2020-01-18
|
||||
### Added
|
||||
@ -50,7 +100,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
### Removed
|
||||
- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89)
|
||||
|
||||
[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.3.1...HEAD
|
||||
[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.4...HEAD
|
||||
[0.5.4]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.3...v0.5.4
|
||||
[0.5.3]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.2...v0.5.3
|
||||
[0.5.2]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.1...v0.5.2
|
||||
[0.5.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.0...v0.5.1
|
||||
[0.5.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.4.0...v0.5.0
|
||||
[0.4.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.3.1...v0.4.0
|
||||
[0.3.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.3.0...v0.3.1
|
||||
[0.3.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.3...v0.3.0
|
||||
[0.2.3]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.2.2...v0.2.3
|
||||
|
89
third_party/rust/memmap2/Cargo.lock
generated
vendored
89
third_party/rust/memmap2/Cargo.lock
generated
vendored
@ -3,10 +3,34 @@
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
@ -16,47 +40,30 @@ checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.3.1"
|
||||
version = "0.5.4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tempdir",
|
||||
"owning_ref",
|
||||
"stable_deref_trait",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.6"
|
||||
name = "owning_ref"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
|
||||
dependencies = [
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.3.1",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||
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",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -69,13 +76,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempdir"
|
||||
version = "0.3.7"
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
36
third_party/rust/memmap2/Cargo.toml
vendored
36
third_party/rust/memmap2/Cargo.toml
vendored
@ -3,24 +3,40 @@
|
||||
# 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
|
||||
# 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)
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "memmap2"
|
||||
version = "0.3.1"
|
||||
authors = ["Dan Burkert <dan@danburkert.com>", "Yevhenii Reizner <razrfalcon@gmail.com>"]
|
||||
version = "0.5.4"
|
||||
authors = [
|
||||
"Dan Burkert <dan@danburkert.com>",
|
||||
"Yevhenii 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"]
|
||||
keywords = [
|
||||
"mmap",
|
||||
"memory-map",
|
||||
"io",
|
||||
"file",
|
||||
]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/RazrFalcon/memmap2-rs"
|
||||
[dev-dependencies.tempdir]
|
||||
version = "0.3"
|
||||
|
||||
[dependencies.stable_deref_trait]
|
||||
version = "1.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.owning_ref]
|
||||
version = "0.4.1"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3"
|
||||
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2"
|
||||
|
2
third_party/rust/memmap2/README.md
vendored
2
third_party/rust/memmap2/README.md
vendored
@ -2,7 +2,7 @@
|
||||
![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)
|
||||
[![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-orange.svg)](https://www.rust-lang.org)
|
||||
|
||||
A Rust library for cross-platform memory mapped IO.
|
||||
|
||||
|
273
third_party/rust/memmap2/src/advice.rs
vendored
Normal file
273
third_party/rust/memmap2/src/advice.rs
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
// The use statement is needed for the `cargo docs`
|
||||
#[allow(unused_imports)]
|
||||
use crate::{Mmap, MmapMut};
|
||||
|
||||
/// Values supported by [Mmap::advise] and [MmapMut::advise] functions.
|
||||
/// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
|
||||
#[repr(i32)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum Advice {
|
||||
/// **MADV_NORMAL**
|
||||
///
|
||||
/// No special treatment. This is the default.
|
||||
Normal = libc::MADV_NORMAL,
|
||||
|
||||
/// **MADV_RANDOM**
|
||||
///
|
||||
/// Expect page references in random order. (Hence, read
|
||||
/// ahead may be less useful than normally.)
|
||||
Random = libc::MADV_RANDOM,
|
||||
|
||||
/// **MADV_SEQUENTIAL**
|
||||
///
|
||||
/// Expect page references in sequential order. (Hence, pages
|
||||
/// in the given range can be aggressively read ahead, and may
|
||||
/// be freed soon after they are accessed.)
|
||||
Sequential = libc::MADV_SEQUENTIAL,
|
||||
|
||||
/// **MADV_WILLNEED**
|
||||
///
|
||||
/// Expect access in the near future. (Hence, it might be a
|
||||
/// good idea to read some pages ahead.)
|
||||
WillNeed = libc::MADV_WILLNEED,
|
||||
|
||||
/// **MADV_DONTNEED**
|
||||
///
|
||||
/// Do not expect access in the near future. (For the time
|
||||
/// being, the application is finished with the given range,
|
||||
/// so the kernel can free resources associated with it.)
|
||||
///
|
||||
/// After a successful MADV_DONTNEED operation, the semantics
|
||||
/// of memory access in the specified region are changed:
|
||||
/// subsequent accesses of pages in the range will succeed,
|
||||
/// but will result in either repopulating the memory contents
|
||||
/// from the up-to-date contents of the underlying mapped file
|
||||
/// (for shared file mappings, shared anonymous mappings, and
|
||||
/// shmem-based techniques such as System V shared memory
|
||||
/// segments) or zero-fill-on-demand pages for anonymous
|
||||
/// private mappings.
|
||||
///
|
||||
/// Note that, when applied to shared mappings, MADV_DONTNEED
|
||||
/// might not lead to immediate freeing of the pages in the
|
||||
/// range. The kernel is free to delay freeing the pages
|
||||
/// until an appropriate moment. The resident set size (RSS)
|
||||
/// of the calling process will be immediately reduced
|
||||
/// however.
|
||||
///
|
||||
/// **MADV_DONTNEED** cannot be applied to locked pages, Huge TLB
|
||||
/// pages, or VM_PFNMAP pages. (Pages marked with the kernel-
|
||||
/// internal VM_PFNMAP flag are special memory areas that are
|
||||
/// not managed by the virtual memory subsystem. Such pages
|
||||
/// are typically created by device drivers that map the pages
|
||||
/// into user space.)
|
||||
DontNeed = libc::MADV_DONTNEED,
|
||||
|
||||
//
|
||||
// The rest are Linux-specific
|
||||
//
|
||||
/// **MADV_FREE** - Linux (since Linux 4.5) and Darwin
|
||||
///
|
||||
/// The application no longer requires the pages in the range
|
||||
/// specified by addr and len. The kernel can thus free these
|
||||
/// pages, but the freeing could be delayed until memory
|
||||
/// pressure occurs. For each of the pages that has been
|
||||
/// marked to be freed but has not yet been freed, the free
|
||||
/// operation will be canceled if the caller writes into the
|
||||
/// page. After a successful MADV_FREE operation, any stale
|
||||
/// data (i.e., dirty, unwritten pages) will be lost when the
|
||||
/// kernel frees the pages. However, subsequent writes to
|
||||
/// pages in the range will succeed and then kernel cannot
|
||||
/// free those dirtied pages, so that the caller can always
|
||||
/// see just written data. If there is no subsequent write,
|
||||
/// the kernel can free the pages at any time. Once pages in
|
||||
/// the range have been freed, the caller will see zero-fill-
|
||||
/// on-demand pages upon subsequent page references.
|
||||
///
|
||||
/// The MADV_FREE operation can be applied only to private
|
||||
/// anonymous pages (see mmap(2)). In Linux before version
|
||||
/// 4.12, when freeing pages on a swapless system, the pages
|
||||
/// in the given range are freed instantly, regardless of
|
||||
/// memory pressure.
|
||||
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios"))]
|
||||
Free = libc::MADV_FREE,
|
||||
|
||||
/// **MADV_REMOVE** - Linux only (since Linux 2.6.16)
|
||||
///
|
||||
/// Free up a given range of pages and its associated backing
|
||||
/// store. This is equivalent to punching a hole in the
|
||||
/// corresponding byte range of the backing store (see
|
||||
/// fallocate(2)). Subsequent accesses in the specified
|
||||
/// address range will see bytes containing zero.
|
||||
///
|
||||
/// The specified address range must be mapped shared and
|
||||
/// writable. This flag cannot be applied to locked pages,
|
||||
/// Huge TLB pages, or VM_PFNMAP pages.
|
||||
///
|
||||
/// In the initial implementation, only tmpfs(5) was supported
|
||||
/// **MADV_REMOVE**; but since Linux 3.5, any filesystem which
|
||||
/// supports the fallocate(2) FALLOC_FL_PUNCH_HOLE mode also
|
||||
/// supports MADV_REMOVE. Hugetlbfs fails with the error
|
||||
/// EINVAL and other filesystems fail with the error
|
||||
/// EOPNOTSUPP.
|
||||
#[cfg(target_os = "linux")]
|
||||
Remove = libc::MADV_REMOVE,
|
||||
|
||||
/// **MADV_DONTFORK** - Linux only (since Linux 2.6.16)
|
||||
///
|
||||
/// Do not make the pages in this range available to the child
|
||||
/// after a fork(2). This is useful to prevent copy-on-write
|
||||
/// semantics from changing the physical location of a page if
|
||||
/// the parent writes to it after a fork(2). (Such page
|
||||
/// relocations cause problems for hardware that DMAs into the
|
||||
/// page.)
|
||||
#[cfg(target_os = "linux")]
|
||||
DontFork = libc::MADV_DONTFORK,
|
||||
|
||||
/// **MADV_DOFORK** - Linux only (since Linux 2.6.16)
|
||||
///
|
||||
/// Undo the effect of MADV_DONTFORK, restoring the default
|
||||
/// behavior, whereby a mapping is inherited across fork(2).
|
||||
#[cfg(target_os = "linux")]
|
||||
DoFork = libc::MADV_DOFORK,
|
||||
|
||||
/// **MADV_MERGEABLE** - Linux only (since Linux 2.6.32)
|
||||
///
|
||||
/// Enable Kernel Samepage Merging (KSM) for the pages in the
|
||||
/// range specified by addr and length. The kernel regularly
|
||||
/// scans those areas of user memory that have been marked as
|
||||
/// mergeable, looking for pages with identical content.
|
||||
/// These are replaced by a single write-protected page (which
|
||||
/// is automatically copied if a process later wants to update
|
||||
/// the content of the page). KSM merges only private
|
||||
/// anonymous pages (see mmap(2)).
|
||||
///
|
||||
/// The KSM feature is intended for applications that generate
|
||||
/// many instances of the same data (e.g., virtualization
|
||||
/// systems such as KVM). It can consume a lot of processing
|
||||
/// power; use with care. See the Linux kernel source file
|
||||
/// Documentation/admin-guide/mm/ksm.rst for more details.
|
||||
///
|
||||
/// The MADV_MERGEABLE and MADV_UNMERGEABLE operations are
|
||||
/// available only if the kernel was configured with
|
||||
/// CONFIG_KSM.
|
||||
#[cfg(target_os = "linux")]
|
||||
Mergeable = libc::MADV_MERGEABLE,
|
||||
|
||||
/// **MADV_UNMERGEABLE** - Linux only (since Linux 2.6.32)
|
||||
///
|
||||
/// Undo the effect of an earlier MADV_MERGEABLE operation on
|
||||
/// the specified address range; KSM unmerges whatever pages
|
||||
/// it had merged in the address range specified by addr and
|
||||
/// length.
|
||||
#[cfg(target_os = "linux")]
|
||||
Unmergeable = libc::MADV_UNMERGEABLE,
|
||||
|
||||
/// **MADV_HUGEPAGE** - Linux only (since Linux 2.6.38)
|
||||
///
|
||||
/// Enable Transparent Huge Pages (THP) for pages in the range
|
||||
/// specified by addr and length. Currently, Transparent Huge
|
||||
/// Pages work only with private anonymous pages (see
|
||||
/// mmap(2)). The kernel will regularly scan the areas marked
|
||||
/// as huge page candidates to replace them with huge pages.
|
||||
/// The kernel will also allocate huge pages directly when the
|
||||
/// region is naturally aligned to the huge page size (see
|
||||
/// posix_memalign(2)).
|
||||
///
|
||||
/// This feature is primarily aimed at applications that use
|
||||
/// large mappings of data and access large regions of that
|
||||
/// memory at a time (e.g., virtualization systems such as
|
||||
/// QEMU). It can very easily waste memory (e.g., a 2 MB
|
||||
/// mapping that only ever accesses 1 byte will result in 2 MB
|
||||
/// of wired memory instead of one 4 KB page). See the Linux
|
||||
/// kernel source file
|
||||
/// Documentation/admin-guide/mm/transhuge.rst for more
|
||||
/// details.
|
||||
///
|
||||
/// Most common kernels configurations provide MADV_HUGEPAGE-
|
||||
/// style behavior by default, and thus MADV_HUGEPAGE is
|
||||
/// normally not necessary. It is mostly intended for
|
||||
/// embedded systems, where MADV_HUGEPAGE-style behavior may
|
||||
/// not be enabled by default in the kernel. On such systems,
|
||||
/// this flag can be used in order to selectively enable THP.
|
||||
/// Whenever MADV_HUGEPAGE is used, it should always be in
|
||||
/// regions of memory with an access pattern that the
|
||||
/// developer knows in advance won't risk to increase the
|
||||
/// memory footprint of the application when transparent
|
||||
/// hugepages are enabled.
|
||||
///
|
||||
/// The MADV_HUGEPAGE and MADV_NOHUGEPAGE operations are
|
||||
/// available only if the kernel was configured with
|
||||
/// CONFIG_TRANSPARENT_HUGEPAGE.
|
||||
#[cfg(target_os = "linux")]
|
||||
HugePage = libc::MADV_HUGEPAGE,
|
||||
|
||||
/// **MADV_NOHUGEPAGE** - Linux only (since Linux 2.6.38)
|
||||
///
|
||||
/// Ensures that memory in the address range specified by addr
|
||||
/// and length will not be backed by transparent hugepages.
|
||||
#[cfg(target_os = "linux")]
|
||||
NoHugePage = libc::MADV_NOHUGEPAGE,
|
||||
|
||||
/// **MADV_DONTDUMP** - Linux only (since Linux 3.4)
|
||||
///
|
||||
/// Exclude from a core dump those pages in the range
|
||||
/// specified by addr and length. This is useful in
|
||||
/// applications that have large areas of memory that are
|
||||
/// known not to be useful in a core dump. The effect of
|
||||
/// **MADV_DONTDUMP** takes precedence over the bit mask that is
|
||||
/// set via the `/proc/[pid]/coredump_filter` file (see
|
||||
/// core(5)).
|
||||
#[cfg(target_os = "linux")]
|
||||
DontDump = libc::MADV_DONTDUMP,
|
||||
|
||||
/// **MADV_DODUMP** - Linux only (since Linux 3.4)
|
||||
///
|
||||
/// Undo the effect of an earlier MADV_DONTDUMP.
|
||||
#[cfg(target_os = "linux")]
|
||||
DoDump = libc::MADV_DODUMP,
|
||||
|
||||
/// **MADV_HWPOISON** - Linux only (since Linux 2.6.32)
|
||||
///
|
||||
/// Poison the pages in the range specified by addr and length
|
||||
/// and handle subsequent references to those pages like a
|
||||
/// hardware memory corruption. This operation is available
|
||||
/// only for privileged (CAP_SYS_ADMIN) processes. This
|
||||
/// operation may result in the calling process receiving a
|
||||
/// SIGBUS and the page being unmapped.
|
||||
///
|
||||
/// This feature is intended for testing of memory error-
|
||||
/// handling code; it is available only if the kernel was
|
||||
/// configured with CONFIG_MEMORY_FAILURE.
|
||||
#[cfg(target_os = "linux")]
|
||||
HwPoison = libc::MADV_HWPOISON,
|
||||
|
||||
/// **MADV_ZERO_WIRED_PAGES** - Darwin only
|
||||
///
|
||||
/// Indicates that the application would like the wired pages in this address range to be
|
||||
/// zeroed out if the address range is deallocated without first unwiring the pages (i.e.
|
||||
/// a munmap(2) without a preceding munlock(2) or the application quits). This is used
|
||||
/// with madvise() system call.
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
ZeroWiredPages = libc::MADV_ZERO_WIRED_PAGES,
|
||||
|
||||
/// **MADV_FREE_REUSABLE** - Darwin only
|
||||
///
|
||||
/// Behaves like **MADV_FREE**, but the freed pages are accounted for in the RSS of the process.
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
FreeReusable = libc::MADV_FREE_REUSABLE,
|
||||
|
||||
/// **MADV_FREE_REUSE** - Darwin only
|
||||
///
|
||||
/// Marks a memory region previously freed by **MADV_FREE_REUSABLE** as non-reusable, accounts
|
||||
/// for the pages in the RSS of the process. Pages that have been freed will be replaced by
|
||||
/// zero-filled pages on demand, other pages will be left as is.
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
FreeReuse = libc::MADV_FREE_REUSE,
|
||||
}
|
||||
|
||||
// Future expansion:
|
||||
// MADV_SOFT_OFFLINE (since Linux 2.6.33)
|
||||
// MADV_WIPEONFORK (since Linux 4.14)
|
||||
// MADV_KEEPONFORK (since Linux 4.14)
|
||||
// MADV_COLD (since Linux 5.4)
|
||||
// MADV_PAGEOUT (since Linux 5.4)
|
360
third_party/rust/memmap2/src/lib.rs
vendored
360
third_party/rust/memmap2/src/lib.rs
vendored
@ -1,51 +1,78 @@
|
||||
//! A cross-platform Rust API for memory mapped buffers.
|
||||
//!
|
||||
//! The core functionality is provided by either [`Mmap`] or [`MmapMut`],
|
||||
//! which correspond to mapping a [`File`] to a [`&[u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
|
||||
//! or [`&mut [u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
|
||||
//! respectively. Both function by dereferencing to a slice, allowing the
|
||||
//! [`Mmap`]/[`MmapMut`] to be used in the same way you would the equivelant slice
|
||||
//! types.
|
||||
//!
|
||||
//! [`File`]: std::fs::File
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! For simple cases [`Mmap`] can be used directly:
|
||||
//!
|
||||
//! ```
|
||||
//! 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(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! However for cases which require configuration of the mapping, then
|
||||
//! you can use [`MmapOptions`] in order to further configure a mapping
|
||||
//! before you create it.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/memmap2/0.3.1")]
|
||||
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
#[cfg(windows)]
|
||||
use crate::windows::file_len;
|
||||
#[cfg(windows)]
|
||||
use crate::windows::MmapInner;
|
||||
#[cfg_attr(unix, path = "unix.rs")]
|
||||
#[cfg_attr(windows, path = "windows.rs")]
|
||||
#[cfg_attr(not(any(unix, windows)), path = "stub.rs")]
|
||||
mod os;
|
||||
use crate::os::{file_len, MmapInner};
|
||||
|
||||
#[cfg(unix)]
|
||||
mod unix;
|
||||
mod advice;
|
||||
#[cfg(unix)]
|
||||
use crate::unix::file_len;
|
||||
#[cfg(unix)]
|
||||
use crate::unix::MmapInner;
|
||||
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
mod stub;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
use crate::stub::file_len;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
use crate::stub::MmapInner;
|
||||
pub use crate::advice::Advice;
|
||||
|
||||
use std::fmt;
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
use std::fs::File;
|
||||
use std::io::{Error, ErrorKind, Result};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawHandle, RawHandle};
|
||||
use std::slice;
|
||||
use std::usize;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
pub struct MmapRawDescriptor<'a>(&'a File);
|
||||
|
||||
#[cfg(unix)]
|
||||
pub struct MmapRawDescriptor(std::os::unix::io::RawFd);
|
||||
pub struct MmapRawDescriptor(RawFd);
|
||||
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
pub struct MmapRawDescriptor<'a>(&'a File);
|
||||
#[cfg(windows)]
|
||||
pub struct MmapRawDescriptor(RawHandle);
|
||||
|
||||
pub trait MmapAsRawDesc {
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
impl MmapAsRawDesc for &File {
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(self)
|
||||
@ -53,23 +80,36 @@ impl MmapAsRawDesc for &File {
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl MmapAsRawDesc for &File {
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(self.as_raw_fd())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl MmapAsRawDesc for std::os::unix::io::RawFd {
|
||||
impl MmapAsRawDesc for RawFd {
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(*self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
impl MmapAsRawDesc for &File {
|
||||
#[cfg(unix)]
|
||||
impl<'a, T> MmapAsRawDesc for &'a T
|
||||
where
|
||||
T: AsRawFd,
|
||||
{
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(self)
|
||||
MmapRawDescriptor(self.as_raw_fd())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl MmapAsRawDesc for RawHandle {
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(*self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl<'a, T> MmapAsRawDesc for &'a T
|
||||
where
|
||||
T: AsRawHandle,
|
||||
{
|
||||
fn as_raw_desc(&self) -> MmapRawDescriptor {
|
||||
MmapRawDescriptor(self.as_raw_handle())
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +346,7 @@ impl MmapOptions {
|
||||
let desc = file.as_raw_desc();
|
||||
|
||||
MmapInner::map_exec(self.get_len(&file)?, desc.0, self.offset, self.populate)
|
||||
.map(|inner| Mmap { inner: inner })
|
||||
.map(|inner| Mmap { inner })
|
||||
}
|
||||
|
||||
/// Creates a writeable memory map backed by a file.
|
||||
@ -320,7 +360,7 @@ impl MmapOptions {
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate memmap2;
|
||||
/// # extern crate tempdir;
|
||||
/// # extern crate tempfile;
|
||||
/// #
|
||||
/// use std::fs::OpenOptions;
|
||||
/// use std::path::PathBuf;
|
||||
@ -328,7 +368,7 @@ impl MmapOptions {
|
||||
/// use memmap2::MmapOptions;
|
||||
/// #
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// # let tempdir = tempdir::TempDir::new("mmap")?;
|
||||
/// # let tempdir = tempfile::tempdir()?;
|
||||
/// let path: PathBuf = /* path to file */
|
||||
/// # tempdir.path().join("map_mut");
|
||||
/// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
|
||||
@ -346,7 +386,7 @@ impl MmapOptions {
|
||||
let desc = file.as_raw_desc();
|
||||
|
||||
MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
|
||||
.map(|inner| MmapMut { inner: inner })
|
||||
.map(|inner| MmapMut { inner })
|
||||
}
|
||||
|
||||
/// Creates a copy-on-write memory map backed by a file.
|
||||
@ -377,7 +417,7 @@ impl MmapOptions {
|
||||
let desc = file.as_raw_desc();
|
||||
|
||||
MmapInner::map_copy(self.get_len(&file)?, desc.0, self.offset, self.populate)
|
||||
.map(|inner| MmapMut { inner: inner })
|
||||
.map(|inner| MmapMut { inner })
|
||||
}
|
||||
|
||||
/// Creates a copy-on-write read-only memory map backed by a file.
|
||||
@ -412,7 +452,7 @@ impl MmapOptions {
|
||||
let desc = file.as_raw_desc();
|
||||
|
||||
MmapInner::map_copy_read_only(self.get_len(&file)?, desc.0, self.offset, self.populate)
|
||||
.map(|inner| Mmap { inner: inner })
|
||||
.map(|inner| Mmap { inner })
|
||||
}
|
||||
|
||||
/// Creates an anonymous memory map.
|
||||
@ -437,7 +477,7 @@ impl MmapOptions {
|
||||
let desc = file.as_raw_desc();
|
||||
|
||||
MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
|
||||
.map(|inner| MmapRaw { inner: inner })
|
||||
.map(|inner| MmapRaw { inner })
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,7 +575,7 @@ impl Mmap {
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate memmap2;
|
||||
/// # extern crate tempdir;
|
||||
/// # extern crate tempfile;
|
||||
/// #
|
||||
/// use memmap2::Mmap;
|
||||
/// use std::ops::DerefMut;
|
||||
@ -543,7 +583,7 @@ impl Mmap {
|
||||
/// # use std::fs::OpenOptions;
|
||||
///
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// # let tempdir = tempdir::TempDir::new("mmap")?;
|
||||
/// # let tempdir = tempfile::tempdir()?;
|
||||
/// let file = /* file opened with write permissions */
|
||||
/// # OpenOptions::new()
|
||||
/// # .read(true)
|
||||
@ -563,8 +603,19 @@ impl Mmap {
|
||||
self.inner.make_mut()?;
|
||||
Ok(MmapMut { inner: self.inner })
|
||||
}
|
||||
|
||||
/// Advise OS how this memory map will be accessed. Only supported on Unix.
|
||||
///
|
||||
/// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
|
||||
#[cfg(unix)]
|
||||
pub fn advise(&self, advice: Advice) -> Result<()> {
|
||||
self.inner.advise(advice)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "stable_deref_trait")]
|
||||
unsafe impl stable_deref_trait::StableDeref for Mmap {}
|
||||
|
||||
impl Deref for Mmap {
|
||||
type Target = [u8];
|
||||
|
||||
@ -640,6 +691,81 @@ impl MmapRaw {
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
/// 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 tempfile;
|
||||
/// #
|
||||
/// use std::fs::OpenOptions;
|
||||
/// use std::io::Write;
|
||||
/// use std::path::PathBuf;
|
||||
/// use std::slice;
|
||||
///
|
||||
/// use memmap2::MmapRaw;
|
||||
///
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// let tempdir = tempfile::tempdir()?;
|
||||
/// 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 { MmapRaw::map_raw(&file)? };
|
||||
///
|
||||
/// let mut memory = unsafe { slice::from_raw_parts_mut(mmap.as_mut_ptr(), 128) };
|
||||
/// memory.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)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for MmapRaw {
|
||||
@ -696,7 +822,7 @@ impl MmapMut {
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate memmap2;
|
||||
/// # extern crate tempdir;
|
||||
/// # extern crate tempfile;
|
||||
/// #
|
||||
/// use std::fs::OpenOptions;
|
||||
/// use std::path::PathBuf;
|
||||
@ -704,7 +830,7 @@ impl MmapMut {
|
||||
/// use memmap2::MmapMut;
|
||||
/// #
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// # let tempdir = tempdir::TempDir::new("mmap")?;
|
||||
/// # let tempdir = tempfile::tempdir()?;
|
||||
/// let path: PathBuf = /* path to file */
|
||||
/// # tempdir.path().join("map_mut");
|
||||
/// let file = OpenOptions::new()
|
||||
@ -745,7 +871,7 @@ impl MmapMut {
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate memmap2;
|
||||
/// # extern crate tempdir;
|
||||
/// # extern crate tempfile;
|
||||
/// #
|
||||
/// use std::fs::OpenOptions;
|
||||
/// use std::io::Write;
|
||||
@ -754,7 +880,7 @@ impl MmapMut {
|
||||
/// use memmap2::MmapMut;
|
||||
///
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// # let tempdir = tempdir::TempDir::new("mmap")?;
|
||||
/// # let tempdir = tempfile::tempdir()?;
|
||||
/// let path: PathBuf = /* path to file */
|
||||
/// # tempdir.path().join("flush");
|
||||
/// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?;
|
||||
@ -853,8 +979,19 @@ impl MmapMut {
|
||||
self.inner.make_exec()?;
|
||||
Ok(Mmap { inner: self.inner })
|
||||
}
|
||||
|
||||
/// Advise OS how this memory map will be accessed. Only supported on Unix.
|
||||
///
|
||||
/// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
|
||||
#[cfg(unix)]
|
||||
pub fn advise(&self, advice: Advice) -> Result<()> {
|
||||
self.inner.advise(advice)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "stable_deref_trait")]
|
||||
unsafe impl stable_deref_trait::StableDeref for MmapMut {}
|
||||
|
||||
impl Deref for MmapMut {
|
||||
type Target = [u8];
|
||||
|
||||
@ -896,8 +1033,10 @@ impl fmt::Debug for MmapMut {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate tempdir;
|
||||
extern crate tempfile;
|
||||
|
||||
#[cfg(unix)]
|
||||
use crate::advice::Advice;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
#[cfg(unix)]
|
||||
@ -913,7 +1052,7 @@ mod test {
|
||||
#[test]
|
||||
fn map_file() {
|
||||
let expected_len = 128;
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -946,7 +1085,7 @@ mod test {
|
||||
#[cfg(unix)]
|
||||
fn map_fd() {
|
||||
let expected_len = 128;
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -975,10 +1114,10 @@ mod test {
|
||||
assert_eq!(&incr[..], &mmap[..]);
|
||||
}
|
||||
|
||||
/// Checks that a 0-length file will not be mapped.
|
||||
/// Checks that "mapping" a 0-length file derefs to an empty slice.
|
||||
#[test]
|
||||
fn map_empty_file() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -987,8 +1126,10 @@ mod test {
|
||||
.create(true)
|
||||
.open(&path)
|
||||
.unwrap();
|
||||
let mmap = unsafe { Mmap::map(&file) };
|
||||
assert!(mmap.is_err());
|
||||
let mmap = unsafe { Mmap::map(&file).unwrap() };
|
||||
assert!(mmap.is_empty());
|
||||
let mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
|
||||
assert!(mmap.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1013,12 +1154,12 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn map_anon_zero_len() {
|
||||
assert!(MmapOptions::new().map_anon().is_err())
|
||||
assert!(MmapOptions::new().map_anon().unwrap().is_empty())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_write() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
@ -1042,7 +1183,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn flush_range() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -1068,7 +1209,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn map_copy() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
@ -1104,7 +1245,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn map_copy_read_only() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -1127,32 +1268,9 @@ mod test {
|
||||
assert_eq!(nulls, &read);
|
||||
}
|
||||
|
||||
// 32bit Linux cannot map a file larger than i32, but Windows can.
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "32"))]
|
||||
#[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();
|
||||
|
||||
let mmap = unsafe { MmapOptions::new().offset(offset).map_mut(&file) };
|
||||
assert!(mmap.is_err());
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_os = "linux", target_pointer_width = "32")))]
|
||||
#[test]
|
||||
fn map_offset() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
@ -1238,7 +1356,7 @@ mod test {
|
||||
#[test]
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn jit_x86_file() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let mut options = OpenOptions::new();
|
||||
#[cfg(windows)]
|
||||
options.access_mode(GENERIC_ALL);
|
||||
@ -1256,7 +1374,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn mprotect_file() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
@ -1302,7 +1420,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn mprotect_copy() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap");
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
@ -1359,7 +1477,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn raw() {
|
||||
let tempdir = tempdir::TempDir::new("mmap").unwrap();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmapraw");
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
@ -1375,4 +1493,68 @@ mod test {
|
||||
assert!(!mmap.as_ptr().is_null());
|
||||
assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
|
||||
}
|
||||
|
||||
/// Something that relies on StableDeref
|
||||
#[test]
|
||||
#[cfg(feature = "stable_deref_trait")]
|
||||
fn owning_ref() {
|
||||
extern crate owning_ref;
|
||||
|
||||
let mut map = MmapMut::map_anon(128).unwrap();
|
||||
map[10] = 42;
|
||||
let owning = owning_ref::OwningRef::new(map);
|
||||
let sliced = owning.map(|map| &map[10..20]);
|
||||
assert_eq!(42, sliced[0]);
|
||||
|
||||
let map = sliced.into_owner().make_read_only().unwrap();
|
||||
let owning = owning_ref::OwningRef::new(map);
|
||||
let sliced = owning.map(|map| &map[10..20]);
|
||||
assert_eq!(42, sliced[0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn advise() {
|
||||
let expected_len = 128;
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("mmap_advise");
|
||||
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&path)
|
||||
.unwrap();
|
||||
|
||||
file.set_len(expected_len as u64).unwrap();
|
||||
|
||||
// Test MmapMut::advise
|
||||
let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
|
||||
mmap.advise(Advice::Random)
|
||||
.expect("mmap advising should be supported on unix");
|
||||
|
||||
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[..]);
|
||||
|
||||
// Set advice and Read from the read-only map
|
||||
let mmap = unsafe { Mmap::map(&file).unwrap() };
|
||||
|
||||
mmap.advise(Advice::Random)
|
||||
.expect("mmap advising should be supported on unix");
|
||||
|
||||
// read values back
|
||||
assert_eq!(&incr[..], &mmap[..]);
|
||||
}
|
||||
}
|
||||
|
23
third_party/rust/memmap2/src/stub.rs
vendored
23
third_party/rust/memmap2/src/stub.rs
vendored
@ -1,10 +1,11 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
// A stable alternative to https://doc.rust-lang.org/stable/std/primitive.never.html
|
||||
enum Never {}
|
||||
|
||||
pub struct MmapInner {
|
||||
// Private member to prevent external construction
|
||||
// (might be nice to change the type to ! once that's stable)
|
||||
__: (),
|
||||
never: Never,
|
||||
}
|
||||
|
||||
impl MmapInner {
|
||||
@ -40,38 +41,38 @@ impl MmapInner {
|
||||
}
|
||||
|
||||
pub fn flush(&self, _: usize, _: usize) -> io::Result<()> {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
pub fn flush_async(&self, _: usize, _: usize) -> io::Result<()> {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
pub fn make_read_only(&mut self) -> io::Result<()> {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
pub fn make_exec(&mut self) -> io::Result<()> {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
pub fn make_mut(&mut self) -> io::Result<()> {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ptr(&self) -> *const u8 {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mut_ptr(&mut self) -> *mut u8 {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unreachable!("self unconstructable");
|
||||
match self.never {}
|
||||
}
|
||||
}
|
||||
|
||||
|
95
third_party/rust/memmap2/src/unix.rs
vendored
95
third_party/rust/memmap2/src/unix.rs
vendored
@ -1,8 +1,12 @@
|
||||
extern crate libc;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::{io, ptr};
|
||||
|
||||
use crate::advice::Advice;
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "linux", not(target_arch = "mips")),
|
||||
target_os = "freebsd",
|
||||
@ -42,13 +46,38 @@ impl 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",
|
||||
));
|
||||
}
|
||||
|
||||
// `libc::mmap` does not support zero-size mappings. POSIX defines:
|
||||
//
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
|
||||
// > If `len` is zero, `mmap()` shall fail and no mapping shall be established.
|
||||
//
|
||||
// So if we would create such a mapping, crate a one-byte mapping instead:
|
||||
let aligned_len = aligned_len.max(1);
|
||||
|
||||
// Note that in that case `MmapInner::len` is still set to zero,
|
||||
// and `Mmap` will still dereferences to an empty slice.
|
||||
//
|
||||
// If this mapping is backed by an empty file, we create a mapping larger than the file.
|
||||
// This is unusual but well-defined. On the same man page, POSIX further defines:
|
||||
//
|
||||
// > The `mmap()` function can be used to map a region of memory that is larger
|
||||
// > than the current size of the object.
|
||||
//
|
||||
// (The object here is the file.)
|
||||
//
|
||||
// > Memory access within the mapping but beyond the current end of the underlying
|
||||
// > objects may result in SIGBUS signals being sent to the process. The reason for this
|
||||
// > is that the size of the object can be manipulated by other processes and can change
|
||||
// > at any moment. The implementation should tell the application that a memory reference
|
||||
// > is outside the object where this can be detected; otherwise, written data may be lost
|
||||
// > and read data may not reflect actual data in the object.
|
||||
//
|
||||
// Because `MmapInner::len` is not incremented, this increment of `aligned_len`
|
||||
// will not allow accesses past the end of the file and will not cause SIGBUS.
|
||||
//
|
||||
// (SIGBUS is still possible by mapping a non-empty file and then truncating it
|
||||
// to a shorter size, but that is unrelated to this handling of empty files.)
|
||||
|
||||
unsafe {
|
||||
let ptr = libc::mmap(
|
||||
@ -174,6 +203,7 @@ impl MmapInner {
|
||||
let alignment = self.ptr as usize % page_size();
|
||||
let ptr = self.ptr.offset(-(alignment as isize));
|
||||
let len = self.len + alignment;
|
||||
let len = len.max(1);
|
||||
if libc::mprotect(ptr, len, prot) == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
@ -208,20 +238,29 @@ impl MmapInner {
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub fn advise(&self, advice: Advice) -> io::Result<()> {
|
||||
unsafe {
|
||||
if libc::madvise(self.ptr, self.len, advice as i32) != 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MmapInner {
|
||||
fn drop(&mut self) {
|
||||
let alignment = self.ptr as usize % page_size();
|
||||
let len = self.len + alignment;
|
||||
let len = len.max(1);
|
||||
// Any errors during unmapping/closing are ignored as the only way
|
||||
// to report them would be through panicking which is highly discouraged
|
||||
// in Drop impls, c.f. https://github.com/rust-lang/lang-team/issues/97
|
||||
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()
|
||||
);
|
||||
let ptr = self.ptr.offset(-(alignment as isize));
|
||||
libc::munmap(ptr, len as libc::size_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,16 +269,32 @@ unsafe impl Sync for MmapInner {}
|
||||
unsafe impl Send for MmapInner {}
|
||||
|
||||
fn page_size() -> usize {
|
||||
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||
static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
match PAGE_SIZE.load(Ordering::Relaxed) {
|
||||
0 => {
|
||||
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize };
|
||||
|
||||
PAGE_SIZE.store(page_size, Ordering::Relaxed);
|
||||
|
||||
page_size
|
||||
}
|
||||
page_size => page_size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_len(file: RawFd) -> io::Result<u64> {
|
||||
unsafe {
|
||||
let mut stat: libc::stat = std::mem::zeroed();
|
||||
#[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "l4re")))]
|
||||
use libc::{fstat, stat};
|
||||
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
|
||||
use libc::{fstat64 as fstat, stat64 as stat};
|
||||
|
||||
let result = libc::fstat(file, &mut stat);
|
||||
unsafe {
|
||||
let mut stat = MaybeUninit::<stat>::uninit();
|
||||
|
||||
let result = fstat(file, stat.as_mut_ptr());
|
||||
if result == 0 {
|
||||
Ok(stat.st_size as u64)
|
||||
Ok(stat.assume_init().st_size as u64)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
|
249
third_party/rust/memmap2/src/windows.rs
vendored
249
third_party/rust/memmap2/src/windows.rs
vendored
@ -1,9 +1,8 @@
|
||||
#![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::os::windows::io::RawHandle;
|
||||
use std::{io, mem, ptr};
|
||||
|
||||
type BOOL = i32;
|
||||
@ -11,6 +10,7 @@ type WORD = u16;
|
||||
type DWORD = u32;
|
||||
type WCHAR = u16;
|
||||
type HANDLE = *mut c_void;
|
||||
type LPHANDLE = *mut HANDLE;
|
||||
type LPVOID = *mut c_void;
|
||||
type LPCVOID = *const c_void;
|
||||
type ULONG_PTR = usize;
|
||||
@ -23,6 +23,8 @@ type LPSYSTEM_INFO = *mut SYSTEM_INFO;
|
||||
|
||||
const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
|
||||
|
||||
const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;
|
||||
|
||||
const STANDARD_RIGHTS_REQUIRED: DWORD = 0x000F0000;
|
||||
|
||||
const SECTION_QUERY: DWORD = 0x0001;
|
||||
@ -52,7 +54,6 @@ 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,
|
||||
@ -60,20 +61,9 @@ struct SECURITY_ATTRIBUTES {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct SYSTEM_INFO_u_s {
|
||||
struct SYSTEM_INFO {
|
||||
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,
|
||||
@ -85,9 +75,44 @@ struct SYSTEM_INFO {
|
||||
wProcessorRevision: WORD,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FILETIME {
|
||||
pub dwLowDateTime: DWORD,
|
||||
pub dwHighDateTime: DWORD,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct BY_HANDLE_FILE_INFORMATION {
|
||||
dwFileAttributes: DWORD,
|
||||
ftCreationTime: FILETIME,
|
||||
ftLastAccessTime: FILETIME,
|
||||
ftLastWriteTime: FILETIME,
|
||||
dwVolumeSerialNumber: DWORD,
|
||||
nFileSizeHigh: DWORD,
|
||||
nFileSizeLow: DWORD,
|
||||
nNumberOfLinks: DWORD,
|
||||
nFileIndexHigh: DWORD,
|
||||
nFileIndexLow: DWORD,
|
||||
}
|
||||
|
||||
type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
|
||||
|
||||
extern "system" {
|
||||
fn GetCurrentProcess() -> HANDLE;
|
||||
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
|
||||
fn DuplicateHandle(
|
||||
hSourceProcessHandle: HANDLE,
|
||||
hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
lpTargetHandle: LPHANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwOptions: DWORD,
|
||||
) -> BOOL;
|
||||
|
||||
fn CreateFileMappingW(
|
||||
hFile: HANDLE,
|
||||
lpFileMappingAttributes: LPSECURITY_ATTRIBUTES,
|
||||
@ -97,6 +122,13 @@ extern "system" {
|
||||
lpName: LPCWSTR,
|
||||
) -> HANDLE;
|
||||
|
||||
fn FlushFileBuffers(hFile: HANDLE) -> BOOL;
|
||||
|
||||
fn GetFileInformationByHandle(
|
||||
hFile: HANDLE,
|
||||
lpFileInformation: LPBY_HANDLE_FILE_INFORMATION,
|
||||
) -> BOOL;
|
||||
|
||||
fn FlushViewOfFile(lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T) -> BOOL;
|
||||
|
||||
fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
|
||||
@ -119,8 +151,13 @@ extern "system" {
|
||||
fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
|
||||
}
|
||||
|
||||
/// Returns a fixed pointer that is valid for `slice::from_raw_parts::<u8>` with `len == 0`.
|
||||
fn empty_slice_ptr() -> *mut c_void {
|
||||
std::ptr::NonNull::<u8>::dangling().cast().as_ptr()
|
||||
}
|
||||
|
||||
pub struct MmapInner {
|
||||
file: Option<File>,
|
||||
handle: Option<RawHandle>,
|
||||
ptr: *mut c_void,
|
||||
len: usize,
|
||||
copy: bool,
|
||||
@ -131,7 +168,7 @@ impl MmapInner {
|
||||
///
|
||||
/// This is a thin wrapper around the `CreateFileMappingW` and `MapViewOfFile` system calls.
|
||||
pub fn new(
|
||||
file: &File,
|
||||
handle: RawHandle,
|
||||
protect: DWORD,
|
||||
access: DWORD,
|
||||
offset: u64,
|
||||
@ -141,45 +178,74 @@ impl MmapInner {
|
||||
let alignment = offset % allocation_granularity() as u64;
|
||||
let aligned_offset = offset - alignment as u64;
|
||||
let aligned_len = len + alignment as usize;
|
||||
if aligned_len == 0 {
|
||||
// `CreateFileMappingW` documents:
|
||||
//
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingw
|
||||
// > An attempt to map a file with a length of 0 (zero) fails with an error code
|
||||
// > of ERROR_FILE_INVALID. Applications should test for files with a length of 0
|
||||
// > (zero) and reject those files.
|
||||
//
|
||||
// For such files, don’t create a mapping at all and use a marker pointer instead.
|
||||
return Ok(MmapInner {
|
||||
handle: None,
|
||||
ptr: empty_slice_ptr(),
|
||||
len: 0,
|
||||
copy,
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let handle = CreateFileMappingW(
|
||||
file.as_raw_handle(),
|
||||
ptr::null_mut(),
|
||||
protect,
|
||||
0,
|
||||
0,
|
||||
ptr::null(),
|
||||
);
|
||||
if handle.is_null() {
|
||||
let mapping = CreateFileMappingW(handle, ptr::null_mut(), protect, 0, 0, ptr::null());
|
||||
if mapping.is_null() {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let ptr = MapViewOfFile(
|
||||
handle,
|
||||
mapping,
|
||||
access,
|
||||
(aligned_offset >> 16 >> 16) as DWORD,
|
||||
(aligned_offset & 0xffffffff) as DWORD,
|
||||
aligned_len as SIZE_T,
|
||||
);
|
||||
CloseHandle(handle);
|
||||
|
||||
CloseHandle(mapping);
|
||||
if ptr.is_null() {
|
||||
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,
|
||||
})
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let mut new_handle = 0 as RawHandle;
|
||||
let cur_proc = GetCurrentProcess();
|
||||
let ok = DuplicateHandle(
|
||||
cur_proc,
|
||||
handle,
|
||||
cur_proc,
|
||||
&mut new_handle,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
if ok == 0 {
|
||||
UnmapViewOfFile(ptr);
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(MmapInner {
|
||||
handle: Some(new_handle),
|
||||
ptr: ptr.offset(alignment as isize),
|
||||
len: len as usize,
|
||||
copy,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result<MmapInner> {
|
||||
let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
|
||||
let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
|
||||
pub fn map(
|
||||
len: usize,
|
||||
handle: RawHandle,
|
||||
offset: u64,
|
||||
_populate: bool,
|
||||
) -> io::Result<MmapInner> {
|
||||
let write = protection_supported(handle, PAGE_READWRITE);
|
||||
let exec = protection_supported(handle, PAGE_EXECUTE_READ);
|
||||
let mut access = FILE_MAP_READ;
|
||||
let protection = match (write, exec) {
|
||||
(true, true) => {
|
||||
@ -197,7 +263,7 @@ impl MmapInner {
|
||||
(false, false) => PAGE_READONLY,
|
||||
};
|
||||
|
||||
let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
|
||||
let mut inner = MmapInner::new(handle, protection, access, offset, len, false)?;
|
||||
if write || exec {
|
||||
inner.make_read_only()?;
|
||||
}
|
||||
@ -206,11 +272,11 @@ impl MmapInner {
|
||||
|
||||
pub fn map_exec(
|
||||
len: usize,
|
||||
file: &File,
|
||||
handle: RawHandle,
|
||||
offset: u64,
|
||||
_populate: bool,
|
||||
) -> io::Result<MmapInner> {
|
||||
let write = protection_supported(file.as_raw_handle(), PAGE_READWRITE);
|
||||
let write = protection_supported(handle, PAGE_READWRITE);
|
||||
let mut access = FILE_MAP_READ | FILE_MAP_EXECUTE;
|
||||
let protection = if write {
|
||||
access |= FILE_MAP_WRITE;
|
||||
@ -219,15 +285,20 @@ impl MmapInner {
|
||||
PAGE_EXECUTE_READ
|
||||
};
|
||||
|
||||
let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
|
||||
let mut inner = MmapInner::new(handle, protection, access, offset, len, false)?;
|
||||
if write {
|
||||
inner.make_exec()?;
|
||||
}
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
pub fn map_mut(len: usize, file: &File, offset: u64, _populate: bool) -> io::Result<MmapInner> {
|
||||
let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READ);
|
||||
pub fn map_mut(
|
||||
len: usize,
|
||||
handle: RawHandle,
|
||||
offset: u64,
|
||||
_populate: bool,
|
||||
) -> io::Result<MmapInner> {
|
||||
let exec = protection_supported(handle, PAGE_EXECUTE_READ);
|
||||
let mut access = FILE_MAP_READ | FILE_MAP_WRITE;
|
||||
let protection = if exec {
|
||||
access |= FILE_MAP_EXECUTE;
|
||||
@ -236,7 +307,7 @@ impl MmapInner {
|
||||
PAGE_READWRITE
|
||||
};
|
||||
|
||||
let mut inner = MmapInner::new(file, protection, access, offset, len, false)?;
|
||||
let mut inner = MmapInner::new(handle, protection, access, offset, len, false)?;
|
||||
if exec {
|
||||
inner.make_mut()?;
|
||||
}
|
||||
@ -245,11 +316,11 @@ impl MmapInner {
|
||||
|
||||
pub fn map_copy(
|
||||
len: usize,
|
||||
file: &File,
|
||||
handle: RawHandle,
|
||||
offset: u64,
|
||||
_populate: bool,
|
||||
) -> io::Result<MmapInner> {
|
||||
let exec = protection_supported(file.as_raw_handle(), PAGE_EXECUTE_READWRITE);
|
||||
let exec = protection_supported(handle, PAGE_EXECUTE_READWRITE);
|
||||
let mut access = FILE_MAP_COPY;
|
||||
let protection = if exec {
|
||||
access |= FILE_MAP_EXECUTE;
|
||||
@ -258,7 +329,7 @@ impl MmapInner {
|
||||
PAGE_WRITECOPY
|
||||
};
|
||||
|
||||
let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
|
||||
let mut inner = MmapInner::new(handle, protection, access, offset, len, true)?;
|
||||
if exec {
|
||||
inner.make_mut()?;
|
||||
}
|
||||
@ -267,12 +338,12 @@ impl MmapInner {
|
||||
|
||||
pub fn map_copy_read_only(
|
||||
len: usize,
|
||||
file: &File,
|
||||
handle: RawHandle,
|
||||
offset: u64,
|
||||
_populate: bool,
|
||||
) -> 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 write = protection_supported(handle, PAGE_READWRITE);
|
||||
let exec = protection_supported(handle, PAGE_EXECUTE_READ);
|
||||
let mut access = FILE_MAP_COPY;
|
||||
let protection = if exec {
|
||||
access |= FILE_MAP_EXECUTE;
|
||||
@ -281,7 +352,7 @@ impl MmapInner {
|
||||
PAGE_WRITECOPY
|
||||
};
|
||||
|
||||
let mut inner = MmapInner::new(file, protection, access, offset, len, true)?;
|
||||
let mut inner = MmapInner::new(handle, protection, access, offset, len, true)?;
|
||||
if write || exec {
|
||||
inner.make_read_only()?;
|
||||
}
|
||||
@ -289,36 +360,38 @@ impl MmapInner {
|
||||
}
|
||||
|
||||
pub fn map_anon(len: usize, _stack: bool) -> io::Result<MmapInner> {
|
||||
// Ensure a non-zero length for the underlying mapping
|
||||
let mapped_len = len.max(1);
|
||||
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(
|
||||
let mapping = CreateFileMappingW(
|
||||
INVALID_HANDLE_VALUE,
|
||||
ptr::null_mut(),
|
||||
PAGE_EXECUTE_READWRITE,
|
||||
(len >> 16 >> 16) as DWORD,
|
||||
(len & 0xffffffff) as DWORD,
|
||||
(mapped_len >> 16 >> 16) as DWORD,
|
||||
(mapped_len & 0xffffffff) as DWORD,
|
||||
ptr::null(),
|
||||
);
|
||||
if handle.is_null() {
|
||||
if mapping.is_null() {
|
||||
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);
|
||||
let ptr = MapViewOfFile(mapping, access, 0, 0, mapped_len as SIZE_T);
|
||||
CloseHandle(mapping);
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let mut old = 0;
|
||||
let result = VirtualProtect(ptr, len as SIZE_T, PAGE_READWRITE, &mut old);
|
||||
let result = VirtualProtect(ptr, mapped_len as SIZE_T, PAGE_READWRITE, &mut old);
|
||||
if result != 0 {
|
||||
Ok(MmapInner {
|
||||
file: None,
|
||||
handle: None,
|
||||
ptr,
|
||||
len: len as usize,
|
||||
copy: false,
|
||||
@ -331,13 +404,21 @@ impl MmapInner {
|
||||
|
||||
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()?;
|
||||
|
||||
if let Some(handle) = self.handle {
|
||||
let ok = unsafe { FlushFileBuffers(handle) };
|
||||
if ok == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn flush_async(&self, offset: usize, len: usize) -> io::Result<()> {
|
||||
if self.ptr == empty_slice_ptr() {
|
||||
return Ok(());
|
||||
}
|
||||
let result = unsafe { FlushViewOfFile(self.ptr.add(offset), len as SIZE_T) };
|
||||
if result != 0 {
|
||||
Ok(())
|
||||
@ -347,6 +428,9 @@ impl MmapInner {
|
||||
}
|
||||
|
||||
fn virtual_protect(&mut self, protect: DWORD) -> io::Result<()> {
|
||||
if self.ptr == empty_slice_ptr() {
|
||||
return Ok(());
|
||||
}
|
||||
unsafe {
|
||||
let alignment = self.ptr as usize % allocation_granularity();
|
||||
let ptr = self.ptr.offset(-(alignment as isize));
|
||||
@ -401,14 +485,20 @@ impl MmapInner {
|
||||
|
||||
impl Drop for MmapInner {
|
||||
fn drop(&mut self) {
|
||||
if self.ptr == empty_slice_ptr() {
|
||||
return;
|
||||
}
|
||||
let alignment = self.ptr as usize % allocation_granularity();
|
||||
// Any errors during unmapping/closing are ignored as the only way
|
||||
// to report them would be through panicking which is highly discouraged
|
||||
// in Drop impls, c.f. https://github.com/rust-lang/lang-team/issues/97
|
||||
unsafe {
|
||||
let ptr = self.ptr.offset(-(alignment as isize));
|
||||
assert!(
|
||||
UnmapViewOfFile(ptr) != 0,
|
||||
"unable to unmap mmap: {}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
UnmapViewOfFile(ptr);
|
||||
|
||||
if let Some(handle) = self.handle {
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,11 +508,11 @@ 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.is_null() {
|
||||
let mapping = CreateFileMappingW(handle, ptr::null_mut(), protection, 0, 0, ptr::null());
|
||||
if mapping.is_null() {
|
||||
return false;
|
||||
}
|
||||
CloseHandle(handle);
|
||||
CloseHandle(mapping);
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -435,6 +525,17 @@ fn allocation_granularity() -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_len(file: &File) -> io::Result<u64> {
|
||||
Ok(file.metadata()?.len())
|
||||
pub fn file_len(handle: RawHandle) -> io::Result<u64> {
|
||||
let info = unsafe {
|
||||
let mut info = mem::MaybeUninit::<BY_HANDLE_FILE_INFORMATION>::uninit();
|
||||
|
||||
let ok = GetFileInformationByHandle(handle, info.as_mut_ptr());
|
||||
if ok == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
info.assume_init()
|
||||
};
|
||||
|
||||
Ok((info.nFileSizeHigh as u64) << 32 | info.nFileSizeLow as u64)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
authors = ["Markus Stange <mstange@themasta.com>"]
|
||||
|
||||
[dependencies]
|
||||
memmap2 = "0.3"
|
||||
memmap2 = "0.5"
|
||||
rustc-demangle = "0.1"
|
||||
uuid = "0.8"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user