Bug 1773399 - Update tempfile to 3.3.0 and parking_lot to 0.11.2. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D148736
This commit is contained in:
Mike Hommey 2022-06-11 20:34:19 +00:00
Родитель 604213514b
Коммит 2aee1dac71
62 изменённых файлов: 3403 добавлений и 786 удалений

40
Cargo.lock сгенерированный
Просмотреть файл

@ -1634,6 +1634,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "ffi-support"
version = "0.4.4"
@ -3954,9 +3963,9 @@ dependencies = [
[[package]]
name = "parking_lot"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
@ -3967,14 +3976,14 @@ dependencies = [
name = "parking_lot"
version = "0.12.999"
dependencies = [
"parking_lot 0.11.1",
"parking_lot 0.11.2",
]
[[package]]
name = "parking_lot_core"
version = "0.8.1"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if 1.0.0",
"instant",
@ -4404,9 +4413,12 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.1.57"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
@ -4805,7 +4817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
dependencies = [
"lazy_static",
"parking_lot 0.11.1",
"parking_lot 0.11.2",
"serial_test_derive",
]
@ -5020,7 +5032,7 @@ dependencies = [
"num-traits",
"num_cpus",
"owning_ref",
"parking_lot 0.11.1",
"parking_lot 0.11.2",
"precomputed-hash",
"rayon",
"regex",
@ -5160,13 +5172,13 @@ checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
[[package]]
name = "tempfile"
version = "3.1.0"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if 0.1.999",
"cfg-if 1.0.0",
"fastrand",
"libc",
"rand 0.7.999",
"redox_syscall",
"remove_dir_all",
"winapi",
@ -6128,7 +6140,7 @@ version = "0.1.0"
dependencies = [
"bincode",
"log",
"parking_lot 0.11.1",
"parking_lot 0.11.2",
"serde",
"wgpu-core",
"wgpu-hal",

Просмотреть файл

@ -513,6 +513,10 @@ criteria = "safe-to-deploy"
version = "0.4.4"
criteria = "safe-to-deploy"
[[unaudited.fastrand]]
version = "1.7.0"
criteria = "safe-to-deploy"
[[unaudited.ffi-support]]
version = "0.4.4"
criteria = "safe-to-deploy"
@ -1030,11 +1034,11 @@ version = "0.4.1"
criteria = "safe-to-deploy"
[[unaudited.parking_lot]]
version = "0.11.1"
version = "0.11.2"
criteria = "safe-to-deploy"
[[unaudited.parking_lot_core]]
version = "0.8.1"
version = "0.8.5"
criteria = "safe-to-deploy"
[[unaudited.paste]]
@ -1186,7 +1190,7 @@ version = "1.9.3"
criteria = "safe-to-deploy"
[[unaudited.redox_syscall]]
version = "0.1.57"
version = "0.2.13"
criteria = "safe-to-deploy"
[[unaudited.regalloc]]
@ -1410,7 +1414,7 @@ version = "0.12.4"
criteria = "safe-to-deploy"
[[unaudited.tempfile]]
version = "3.1.0"
version = "3.3.0"
criteria = "safe-to-deploy"
[[unaudited.termcolor]]

1
third_party/rust/fastrand/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"64b93943521b0ee7266f0d95d7ebdd0b8d1ff0bb4bebda9e445ec55dc641b232","Cargo.toml":"d4c2645fe37d1d484b8aa9cd64beb37e9c8a763f5b9e6c5ed775e6400745c7f8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"dec6b96d3549746937d7e0e62e35e206e6f5b7e2d1886451281905f4edf096d4","benches/bench.rs":"8a8a38a032c4b0442aeccfeb5444e6824ad5e50143c9feec88803d6558312232","src/lib.rs":"6daab127f3f55166041c5a6f80384899597696e5bf12f80b87a0f3abaf1cf873","tests/char.rs":"a530b41837f5bf43701d983ef0267d9b44779d455f24cbf30b881cd348de9ee1","tests/smoke.rs":"10631fa1facee3243e12a8fc56856f2bddfc7090be17b3364edbbac9973692d9"},"package":"c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"}

77
third_party/rust/fastrand/CHANGELOG.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,77 @@
# Version 1.7.0
- Add `char()` and `Rng::char()` (#25)
# Version 1.6.0
- Implement `PartialEq` and `Eq` for `Rng` (#23)
# Version 1.5.0
- Switch to Wyrand (#14)
# Version 1.4.1
- Fix bug when generating a signed integer within a range (#16)
# Version 1.4.0
- Add wasm support.
# Version 1.3.5
- Reword docs.
- Add `Rng::with_seed()`.
# Version 1.3.4
- Implement `Clone` for `Rng`.
# Version 1.3.3
- Forbid unsafe code.
# Version 1.3.2
- Support older Rust versions.
# Version 1.3.1
- Tweak Cargo keywords.
# Version 1.3.0
- Add `f32()` and `f64()`.
- Add `lowercase()`, `uppercase()`, `alphabetic()`, and `digit()`.
# Version 1.2.4
- Switch to PCG XSH RR 64/32.
- Fix a bug in `gen_mod_u128`.
- Fix bias in ranges.
# Version 1.2.3
- Support Rust 1.32.0
# Version 1.2.2
- Use `std::$t::MAX` rather than `$t::MAX` to support older Rust versions.
# Version 1.2.1
- Inline all functions.
# Version 1.2.0
- Add `Rng` struct.
# Version 1.1.0
- Switch to PCG implementation.
- Add `alphanumeric()`.
- Add `seed()`.
# Version 1.0.0
- Initial version

43
third_party/rust/fastrand/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,43 @@
# 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 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"
rust-version = "1.34"
name = "fastrand"
version = "1.7.0"
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
exclude = ["/.*"]
description = "A simple and fast random number generator"
keywords = ["simple", "fast", "rand", "random", "wyrand"]
categories = ["algorithms"]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/smol-rs/fastrand"
[dev-dependencies.getrandom]
version = "0.2"
[dev-dependencies.rand]
version = "0.8"
[dev-dependencies.wyhash]
version = "0.5"
[target."cfg(target_arch = \"wasm32\")".dependencies.instant]
version = "0.1"
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.getrandom]
version = "0.2"
features = ["js"]
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.instant]
version = "0.1"
features = ["wasm-bindgen"]
[target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test]
version = "0.3"

201
third_party/rust/fastrand/LICENSE-APACHE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,201 @@
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 [yyyy] [name of copyright owner]
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.

23
third_party/rust/fastrand/LICENSE-MIT поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
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.

92
third_party/rust/fastrand/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,92 @@
# fastrand
[![Build](https://github.com/smol-rs/fastrand/workflows/Build%20and%20test/badge.svg)](
https://github.com/smol-rs/fastrand/actions)
[![License](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)](
https://github.com/smol-rs/fastrand)
[![Cargo](https://img.shields.io/crates/v/fastrand.svg)](
https://crates.io/crates/fastrand)
[![Documentation](https://docs.rs/fastrand/badge.svg)](
https://docs.rs/fastrand)
A simple and fast random number generator.
The implementation uses [Wyrand](https://github.com/wangyi-fudan/wyhash), a simple and fast
generator but **not** cryptographically secure.
## Examples
Flip a coin:
```rust
if fastrand::bool() {
println!("heads");
} else {
println!("tails");
}
```
Generate a random `i32`:
```rust
let num = fastrand::i32(..);
```
Choose a random element in an array:
```rust
let v = vec![1, 2, 3, 4, 5];
let i = fastrand::usize(..v.len());
let elem = v[i];
```
Shuffle an array:
```rust
let mut v = vec![1, 2, 3, 4, 5];
fastrand::shuffle(&mut v);
```
Generate a random `Vec` or `String`:
```rust
use std::iter::repeat_with;
let v: Vec<i32> = repeat_with(|| fastrand::i32(..)).take(10).collect();
let s: String = repeat_with(fastrand::alphanumeric).take(10).collect();
```
To get reproducible results on every run, initialize the generator with a seed:
```rust
// Pick an arbitrary number as seed.
fastrand::seed(7);
// Now this prints the same number on every run:
println!("{}", fastrand::u32(..));
```
To be more efficient, create a new `Rng` instance instead of using the thread-local
generator:
```rust
use std::iter::repeat_with;
let rng = fastrand::Rng::new();
let mut bytes: Vec<u8> = repeat_with(|| rng.u8(..)).take(10_000).collect();
```
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
#### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

75
third_party/rust/fastrand/benches/bench.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,75 @@
#![feature(test)]
extern crate test;
use rand::prelude::*;
use test::Bencher;
use wyhash::WyRng;
#[bench]
fn shuffle_wyhash(b: &mut Bencher) {
let mut rng = WyRng::from_rng(thread_rng()).unwrap();
let mut x = (0..100).collect::<Vec<usize>>();
b.iter(|| {
x.shuffle(&mut rng);
x[0]
})
}
#[bench]
fn shuffle_fastrand(b: &mut Bencher) {
let rng = fastrand::Rng::new();
let mut x = (0..100).collect::<Vec<usize>>();
b.iter(|| {
rng.shuffle(&mut x);
x[0]
})
}
#[bench]
fn u8_wyhash(b: &mut Bencher) {
let mut rng = WyRng::from_rng(thread_rng()).unwrap();
b.iter(|| {
let mut sum = 0u8;
for _ in 0..10_000 {
sum = sum.wrapping_add(rng.gen::<u8>());
}
sum
})
}
#[bench]
fn u8_fastrand(b: &mut Bencher) {
let rng = fastrand::Rng::new();
b.iter(|| {
let mut sum = 0u8;
for _ in 0..10_000 {
sum = sum.wrapping_add(rng.u8(..));
}
sum
})
}
#[bench]
fn u32_wyhash(b: &mut Bencher) {
let mut rng = WyRng::from_rng(thread_rng()).unwrap();
b.iter(|| {
let mut sum = 0u32;
for _ in 0..10_000 {
sum = sum.wrapping_add(rng.gen::<u32>());
}
sum
})
}
#[bench]
fn u32_fastrand(b: &mut Bencher) {
let rng = fastrand::Rng::new();
b.iter(|| {
let mut sum = 0u32;
for _ in 0..10_000 {
sum = sum.wrapping_add(rng.u32(..));
}
sum
})
}

668
third_party/rust/fastrand/src/lib.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,668 @@
//! A simple and fast random number generator.
//!
//! The implementation uses [Wyrand](https://github.com/wangyi-fudan/wyhash), a simple and fast
//! generator but **not** cryptographically secure.
//!
//! # Examples
//!
//! Flip a coin:
//!
//! ```
//! if fastrand::bool() {
//! println!("heads");
//! } else {
//! println!("tails");
//! }
//! ```
//!
//! Generate a random `i32`:
//!
//! ```
//! let num = fastrand::i32(..);
//! ```
//!
//! Choose a random element in an array:
//!
//! ```
//! let v = vec![1, 2, 3, 4, 5];
//! let i = fastrand::usize(..v.len());
//! let elem = v[i];
//! ```
//!
//! Shuffle an array:
//!
//! ```
//! let mut v = vec![1, 2, 3, 4, 5];
//! fastrand::shuffle(&mut v);
//! ```
//!
//! Generate a random [`Vec`] or [`String`]:
//!
//! ```
//! use std::iter::repeat_with;
//!
//! let v: Vec<i32> = repeat_with(|| fastrand::i32(..)).take(10).collect();
//! let s: String = repeat_with(fastrand::alphanumeric).take(10).collect();
//! ```
//!
//! To get reproducible results on every run, initialize the generator with a seed:
//!
//! ```
//! // Pick an arbitrary number as seed.
//! fastrand::seed(7);
//!
//! // Now this prints the same number on every run:
//! println!("{}", fastrand::u32(..));
//! ```
//!
//! To be more efficient, create a new [`Rng`] instance instead of using the thread-local
//! generator:
//!
//! ```
//! use std::iter::repeat_with;
//!
//! let rng = fastrand::Rng::new();
//! let mut bytes: Vec<u8> = repeat_with(|| rng.u8(..)).take(10_000).collect();
//! ```
#![forbid(unsafe_code)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
use std::cell::Cell;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::ops::{Bound, RangeBounds};
use std::thread;
#[cfg(target_arch = "wasm32")]
use instant::Instant;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
/// A random number generator.
#[derive(Debug, PartialEq, Eq)]
pub struct Rng(Cell<u64>);
impl Default for Rng {
#[inline]
fn default() -> Rng {
Rng::new()
}
}
impl Clone for Rng {
/// Clones the generator by deterministically deriving a new generator based on the initial
/// seed.
///
/// # Example
///
/// ```
/// // Seed two generators equally, and clone both of them.
/// let base1 = fastrand::Rng::new();
/// base1.seed(0x4d595df4d0f33173);
/// base1.bool(); // Use the generator once.
///
/// let base2 = fastrand::Rng::new();
/// base2.seed(0x4d595df4d0f33173);
/// base2.bool(); // Use the generator once.
///
/// let rng1 = base1.clone();
/// let rng2 = base2.clone();
///
/// assert_eq!(rng1.u64(..), rng2.u64(..), "the cloned generators are identical");
/// ```
fn clone(&self) -> Rng {
Rng::with_seed(self.gen_u64())
}
}
impl Rng {
/// Generates a random `u32`.
#[inline]
fn gen_u32(&self) -> u32 {
self.gen_u64() as u32
}
/// Generates a random `u64`.
#[inline]
fn gen_u64(&self) -> u64 {
let s = self.0.get().wrapping_add(0xA0761D6478BD642F);
self.0.set(s);
let t = u128::from(s) * u128::from(s ^ 0xE7037ED1A0B428DB);
(t as u64) ^ (t >> 64) as u64
}
/// Generates a random `u128`.
#[inline]
fn gen_u128(&self) -> u128 {
(u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64())
}
/// Generates a random `u32` in `0..n`.
#[inline]
fn gen_mod_u32(&self, n: u32) -> u32 {
// Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
let mut r = self.gen_u32();
let mut hi = mul_high_u32(r, n);
let mut lo = r.wrapping_mul(n);
if lo < n {
let t = n.wrapping_neg() % n;
while lo < t {
r = self.gen_u32();
hi = mul_high_u32(r, n);
lo = r.wrapping_mul(n);
}
}
hi
}
/// Generates a random `u64` in `0..n`.
#[inline]
fn gen_mod_u64(&self, n: u64) -> u64 {
// Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
let mut r = self.gen_u64();
let mut hi = mul_high_u64(r, n);
let mut lo = r.wrapping_mul(n);
if lo < n {
let t = n.wrapping_neg() % n;
while lo < t {
r = self.gen_u64();
hi = mul_high_u64(r, n);
lo = r.wrapping_mul(n);
}
}
hi
}
/// Generates a random `u128` in `0..n`.
#[inline]
fn gen_mod_u128(&self, n: u128) -> u128 {
// Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
let mut r = self.gen_u128();
let mut hi = mul_high_u128(r, n);
let mut lo = r.wrapping_mul(n);
if lo < n {
let t = n.wrapping_neg() % n;
while lo < t {
r = self.gen_u128();
hi = mul_high_u128(r, n);
lo = r.wrapping_mul(n);
}
}
hi
}
}
thread_local! {
static RNG: Rng = Rng(Cell::new({
let mut hasher = DefaultHasher::new();
Instant::now().hash(&mut hasher);
thread::current().id().hash(&mut hasher);
let hash = hasher.finish();
(hash << 1) | 1
}));
}
/// Computes `(a * b) >> 32`.
#[inline]
fn mul_high_u32(a: u32, b: u32) -> u32 {
(((a as u64) * (b as u64)) >> 32) as u32
}
/// Computes `(a * b) >> 64`.
#[inline]
fn mul_high_u64(a: u64, b: u64) -> u64 {
(((a as u128) * (b as u128)) >> 64) as u64
}
/// Computes `(a * b) >> 128`.
#[inline]
fn mul_high_u128(a: u128, b: u128) -> u128 {
// Adapted from: https://stackoverflow.com/a/28904636
let a_lo = a as u64 as u128;
let a_hi = (a >> 64) as u64 as u128;
let b_lo = b as u64 as u128;
let b_hi = (b >> 64) as u64 as u128;
let carry = (a_lo * b_lo) >> 64;
let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64;
a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry
}
macro_rules! rng_integer {
($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => {
#[doc = $doc]
///
/// Panics if the range is empty.
#[inline]
pub fn $t(&self, range: impl RangeBounds<$t>) -> $t {
let panic_empty_range = || {
panic!(
"empty range: {:?}..{:?}",
range.start_bound(),
range.end_bound()
)
};
let low = match range.start_bound() {
Bound::Unbounded => std::$t::MIN,
Bound::Included(&x) => x,
Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
};
let high = match range.end_bound() {
Bound::Unbounded => std::$t::MAX,
Bound::Included(&x) => x,
Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
};
if low > high {
panic_empty_range();
}
if low == std::$t::MIN && high == std::$t::MAX {
self.$gen() as $t
} else {
let len = high.wrapping_sub(low).wrapping_add(1);
low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t)
}
}
};
}
impl Rng {
/// Creates a new random number generator.
#[inline]
pub fn new() -> Rng {
Rng::with_seed(
RNG.try_with(|rng| rng.u64(..))
.unwrap_or(0x4d595df4d0f33173),
)
}
/// Creates a new random number generator with the initial seed.
#[inline]
pub fn with_seed(seed: u64) -> Self {
let rng = Rng(Cell::new(0));
rng.seed(seed);
rng
}
/// Generates a random `char` in ranges a-z and A-Z.
#[inline]
pub fn alphabetic(&self) -> char {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let len = CHARS.len() as u8;
let i = self.u8(..len);
CHARS[i as usize] as char
}
/// Generates a random `char` in ranges a-z, A-Z and 0-9.
#[inline]
pub fn alphanumeric(&self) -> char {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let len = CHARS.len() as u8;
let i = self.u8(..len);
CHARS[i as usize] as char
}
/// Generates a random `bool`.
#[inline]
pub fn bool(&self) -> bool {
self.u8(..) % 2 == 0
}
/// Generates a random digit in the given `base`.
///
/// Digits are represented by `char`s in ranges 0-9 and a-z.
///
/// Panics if the base is zero or greater than 36.
#[inline]
pub fn digit(&self, base: u32) -> char {
if base == 0 {
panic!("base cannot be zero");
}
if base > 36 {
panic!("base cannot be larger than 36");
}
let num = self.u8(..base as u8);
if num < 10 {
(b'0' + num) as char
} else {
(b'a' + num - 10) as char
}
}
/// Generates a random `f32` in range `0..1`.
pub fn f32(&self) -> f32 {
let b = 32;
let f = std::f32::MANTISSA_DIGITS - 1;
f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0
}
/// Generates a random `f64` in range `0..1`.
pub fn f64(&self) -> f64 {
let b = 64;
let f = std::f64::MANTISSA_DIGITS - 1;
f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0
}
rng_integer!(
i8,
u8,
gen_u32,
gen_mod_u32,
"Generates a random `i8` in the given range."
);
rng_integer!(
i16,
u16,
gen_u32,
gen_mod_u32,
"Generates a random `i16` in the given range."
);
rng_integer!(
i32,
u32,
gen_u32,
gen_mod_u32,
"Generates a random `i32` in the given range."
);
rng_integer!(
i64,
u64,
gen_u64,
gen_mod_u64,
"Generates a random `i64` in the given range."
);
rng_integer!(
i128,
u128,
gen_u128,
gen_mod_u128,
"Generates a random `i128` in the given range."
);
#[cfg(target_pointer_width = "16")]
rng_integer!(
isize,
usize,
gen_u32,
gen_mod_u32,
"Generates a random `isize` in the given range."
);
#[cfg(target_pointer_width = "32")]
rng_integer!(
isize,
usize,
gen_u32,
gen_mod_u32,
"Generates a random `isize` in the given range."
);
#[cfg(target_pointer_width = "64")]
rng_integer!(
isize,
usize,
gen_u64,
gen_mod_u64,
"Generates a random `isize` in the given range."
);
/// Generates a random `char` in range a-z.
#[inline]
pub fn lowercase(&self) -> char {
const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
let len = CHARS.len() as u8;
let i = self.u8(..len);
CHARS[i as usize] as char
}
/// Initializes this generator with the given seed.
#[inline]
pub fn seed(&self, seed: u64) {
self.0.set(seed);
}
/// Shuffles a slice randomly.
#[inline]
pub fn shuffle<T>(&self, slice: &mut [T]) {
for i in 1..slice.len() {
slice.swap(i, self.usize(..=i));
}
}
rng_integer!(
u8,
u8,
gen_u32,
gen_mod_u32,
"Generates a random `u8` in the given range."
);
rng_integer!(
u16,
u16,
gen_u32,
gen_mod_u32,
"Generates a random `u16` in the given range."
);
rng_integer!(
u32,
u32,
gen_u32,
gen_mod_u32,
"Generates a random `u32` in the given range."
);
rng_integer!(
u64,
u64,
gen_u64,
gen_mod_u64,
"Generates a random `u64` in the given range."
);
rng_integer!(
u128,
u128,
gen_u128,
gen_mod_u128,
"Generates a random `u128` in the given range."
);
#[cfg(target_pointer_width = "16")]
rng_integer!(
usize,
usize,
gen_u32,
gen_mod_u32,
"Generates a random `usize` in the given range."
);
#[cfg(target_pointer_width = "32")]
rng_integer!(
usize,
usize,
gen_u32,
gen_mod_u32,
"Generates a random `usize` in the given range."
);
#[cfg(target_pointer_width = "64")]
rng_integer!(
usize,
usize,
gen_u64,
gen_mod_u64,
"Generates a random `usize` in the given range."
);
#[cfg(target_pointer_width = "128")]
rng_integer!(
usize,
usize,
gen_u128,
gen_mod_u128,
"Generates a random `usize` in the given range."
);
/// Generates a random `char` in range A-Z.
#[inline]
pub fn uppercase(&self) -> char {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let len = CHARS.len() as u8;
let i = self.u8(..len);
CHARS[i as usize] as char
}
/// Generates a random `char` in the given range.
///
/// Panics if the range is empty.
#[inline]
pub fn char(&self, range: impl RangeBounds<char>) -> char {
use std::convert::{TryFrom, TryInto};
let panic_empty_range = || {
panic!(
"empty range: {:?}..{:?}",
range.start_bound(),
range.end_bound()
)
};
let surrogate_start = 0xd800u32;
let surrogate_len = 0x800u32;
let low = match range.start_bound() {
Bound::Unbounded => 0u8 as char,
Bound::Included(&x) => x,
Bound::Excluded(&x) => {
let scalar = if x as u32 == surrogate_start - 1 {
surrogate_start + surrogate_len
} else {
x as u32 + 1
};
char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
}
};
let high = match range.end_bound() {
Bound::Unbounded => std::char::MAX,
Bound::Included(&x) => x,
Bound::Excluded(&x) => {
let scalar = if x as u32 == surrogate_start + surrogate_len {
surrogate_start - 1
} else {
(x as u32).wrapping_sub(1)
};
char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
}
};
if low > high {
panic_empty_range();
}
let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start {
surrogate_len
} else {
0
};
let range = high as u32 - low as u32 - gap;
let mut val = self.u32(0..=range) + low as u32;
if val >= surrogate_start {
val += gap;
}
val.try_into().unwrap()
}
}
/// Initializes the thread-local generator with the given seed.
#[inline]
pub fn seed(seed: u64) {
RNG.with(|rng| rng.seed(seed))
}
/// Generates a random `bool`.
#[inline]
pub fn bool() -> bool {
RNG.with(|rng| rng.bool())
}
/// Generates a random `char` in ranges a-z and A-Z.
#[inline]
pub fn alphabetic() -> char {
RNG.with(|rng| rng.alphabetic())
}
/// Generates a random `char` in ranges a-z, A-Z and 0-9.
#[inline]
pub fn alphanumeric() -> char {
RNG.with(|rng| rng.alphanumeric())
}
/// Generates a random `char` in range a-z.
#[inline]
pub fn lowercase() -> char {
RNG.with(|rng| rng.lowercase())
}
/// Generates a random `char` in range A-Z.
#[inline]
pub fn uppercase() -> char {
RNG.with(|rng| rng.uppercase())
}
/// Generates a random digit in the given `base`.
///
/// Digits are represented by `char`s in ranges 0-9 and a-z.
///
/// Panics if the base is zero or greater than 36.
#[inline]
pub fn digit(base: u32) -> char {
RNG.with(|rng| rng.digit(base))
}
/// Shuffles a slice randomly.
#[inline]
pub fn shuffle<T>(slice: &mut [T]) {
RNG.with(|rng| rng.shuffle(slice))
}
macro_rules! integer {
($t:tt, $doc:tt) => {
#[doc = $doc]
///
/// Panics if the range is empty.
#[inline]
pub fn $t(range: impl RangeBounds<$t>) -> $t {
RNG.with(|rng| rng.$t(range))
}
};
}
integer!(u8, "Generates a random `u8` in the given range.");
integer!(i8, "Generates a random `i8` in the given range.");
integer!(u16, "Generates a random `u16` in the given range.");
integer!(i16, "Generates a random `i16` in the given range.");
integer!(u32, "Generates a random `u32` in the given range.");
integer!(i32, "Generates a random `i32` in the given range.");
integer!(u64, "Generates a random `u64` in the given range.");
integer!(i64, "Generates a random `i64` in the given range.");
integer!(u128, "Generates a random `u128` in the given range.");
integer!(i128, "Generates a random `i128` in the given range.");
integer!(usize, "Generates a random `usize` in the given range.");
integer!(isize, "Generates a random `isize` in the given range.");
integer!(char, "Generates a random `char` in the given range.");
/// Generates a random `f32` in range `0..1`.
pub fn f32() -> f32 {
RNG.with(|rng| rng.f32())
}
/// Generates a random `f64` in range `0..1`.
pub fn f64() -> f64 {
RNG.with(|rng| rng.f64())
}

44
third_party/rust/fastrand/tests/char.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
use std::convert::TryFrom;
use std::ops::RangeBounds;
fn test_char_coverage<R>(n: usize, range: R)
where
R: Iterator<Item = char> + RangeBounds<char> + Clone,
{
use std::collections::HashSet;
let all: HashSet<char> = range.clone().collect();
let mut covered = HashSet::new();
for _ in 0..n {
let c = fastrand::char(range.clone());
assert!(all.contains(&c));
covered.insert(c);
}
assert_eq!(covered, all);
}
#[test]
fn test_char() {
// ASCII control chars.
let nul = 0u8 as char;
let soh = 1u8 as char;
let stx = 2u8 as char;
// Some undefined Hangul Jamo codepoints just before
// the surrogate area.
let last_jamo = char::try_from(0xd7ffu32).unwrap();
let penultimate_jamo = char::try_from(last_jamo as u32 - 1).unwrap();
// Private-use codepoints just after the surrogate area.
let first_private = char::try_from(0xe000u32).unwrap();
let second_private = char::try_from(first_private as u32 + 1).unwrap();
// Private-use codepoints at the end of Unicode space.
let last_private = std::char::MAX;
let penultimate_private = char::try_from(last_private as u32 - 1).unwrap();
test_char_coverage(100, nul..stx);
test_char_coverage(100, nul..=soh);
test_char_coverage(400, penultimate_jamo..second_private);
test_char_coverage(400, penultimate_jamo..=second_private);
test_char_coverage(100, penultimate_private..=last_private);
}

117
third_party/rust/fastrand/tests/smoke.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,117 @@
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn bool() {
for x in &[false, true] {
while fastrand::bool() != *x {}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn u8() {
for x in 0..10 {
while fastrand::u8(..10) != x {}
}
for x in 200..=u8::MAX {
while fastrand::u8(200..) != x {}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn i8() {
for x in -128..-120 {
while fastrand::i8(..-120) != x {}
}
for x in 120..=127 {
while fastrand::i8(120..) != x {}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn u32() {
for n in 1u32..10_000 {
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
if n != 0 {
for _ in 0..1000 {
assert!(fastrand::u32(..n) < n);
}
}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn u64() {
for n in 1u64..10_000 {
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
if n != 0 {
for _ in 0..1000 {
assert!(fastrand::u64(..n) < n);
}
}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn u128() {
for n in 1u128..10_000 {
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
let n = n.wrapping_mul(n);
if n != 0 {
for _ in 0..1000 {
assert!(fastrand::u128(..n) < n);
}
}
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn rng() {
let r = fastrand::Rng::new();
assert_ne!(r.u64(..), r.u64(..));
r.seed(7);
let a = r.u64(..);
r.seed(7);
let b = r.u64(..);
assert_eq!(a, b);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn rng_init() {
let a = fastrand::Rng::new();
let b = fastrand::Rng::new();
assert_ne!(a.u64(..), b.u64(..));
a.seed(7);
b.seed(7);
assert_eq!(a.u64(..), b.u64(..));
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn with_seed() {
let a = fastrand::Rng::with_seed(7);
let b = fastrand::Rng::new();
b.seed(7);
assert_eq!(a.u64(..), b.u64(..));
}

Просмотреть файл

@ -1 +1 @@
{"files":{"CHANGELOG.md":"f9559e40e966a870d64367a75e41b233ee1bc1746f6f242501b9462e69b4db12","Cargo.toml":"a7cce7f9fbc2cb0a5c388384073f9b2e820d6b47f314ef0dcccb5613741b8202","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"93e21ceae3fe1b6cf9f6c2ebcbf09211a08b446f849048900d8d7efe52751614","bors.toml":"938b40da0516dd1e18f6ab893d43a3c6a011836124696157568380f3ce784958","src/condvar.rs":"bace2ee6e97eab088833a22a511029fb188e5f6bc9289bfcd5d41e3915de921d","src/deadlock.rs":"7d3ebb5b4f63658435df277bb983e352e4bc651a92c4fd48ae68bf103e452d0d","src/elision.rs":"9aceb0b27fd3cdaf4ef76bda63435a96ec2fdef24be098b9e4edbc39db000765","src/fair_mutex.rs":"d0a032e8207919da04b85f1422dfb14aa2af7aad78843c708d2fe3e0478e401a","src/lib.rs":"d83b9e6c70d2c6167d55dc2c4cf2b02abf4b11bfa092949750bc0cdafd38a45c","src/mutex.rs":"9fff878238ef798bfe2f48b410ca3074914826005a12df4f9b96619b2d3e6409","src/once.rs":"a1c38a5d87077e3d112d57e065ee126a24ab19f04fba9cb1f2cb43bc82caf33c","src/raw_fair_mutex.rs":"316f954d9673ac5b8d6bf4c19f2444800f63daf801c224d986e2d6dac810643c","src/raw_mutex.rs":"a24262800d61b8486ef0cfb1b72ead748c544ca2a551ec48346036ebb4fc385b","src/raw_rwlock.rs":"d0d93b096e68da3213da49d51849baf4ec241552eaa9b791f38314eb36c4e1a9","src/remutex.rs":"7a0de55161cd57497bb52d3aecca69a89eff2e71cdb2d762df53579e0607b489","src/rwlock.rs":"68584dffeb4368839774c0ee987481affc0547c38977a17970514f072a582d61","src/util.rs":"26325483bcd23ab8ceb16bf47541152c5eb0bc394f247795c14698fa7b586692","tests/issue_203.rs":"5fbdf6ec63f391d86457df949678c203a1e81e8aa32d4e10037fa76e768702c0"},"package":"6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"}
{"files":{"CHANGELOG.md":"3ea666453fd8eae4b1b8d81f675f45e627115201a368890f0828cf895c58790f","Cargo.toml":"6217caca78eb5e8c0bb41beed960b735bde774ae60e752e584d7265a2e19f079","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"93e21ceae3fe1b6cf9f6c2ebcbf09211a08b446f849048900d8d7efe52751614","bors.toml":"938b40da0516dd1e18f6ab893d43a3c6a011836124696157568380f3ce784958","src/condvar.rs":"bace2ee6e97eab088833a22a511029fb188e5f6bc9289bfcd5d41e3915de921d","src/deadlock.rs":"7d3ebb5b4f63658435df277bb983e352e4bc651a92c4fd48ae68bf103e452d0d","src/elision.rs":"9aceb0b27fd3cdaf4ef76bda63435a96ec2fdef24be098b9e4edbc39db000765","src/fair_mutex.rs":"d0a032e8207919da04b85f1422dfb14aa2af7aad78843c708d2fe3e0478e401a","src/lib.rs":"d83b9e6c70d2c6167d55dc2c4cf2b02abf4b11bfa092949750bc0cdafd38a45c","src/mutex.rs":"9fff878238ef798bfe2f48b410ca3074914826005a12df4f9b96619b2d3e6409","src/once.rs":"a1c38a5d87077e3d112d57e065ee126a24ab19f04fba9cb1f2cb43bc82caf33c","src/raw_fair_mutex.rs":"316f954d9673ac5b8d6bf4c19f2444800f63daf801c224d986e2d6dac810643c","src/raw_mutex.rs":"a24262800d61b8486ef0cfb1b72ead748c544ca2a551ec48346036ebb4fc385b","src/raw_rwlock.rs":"f23b9d68b7048278f9987d81551ae9551894e5af47bbaaf8d86b8ee42cb7ed74","src/remutex.rs":"7a0de55161cd57497bb52d3aecca69a89eff2e71cdb2d762df53579e0607b489","src/rwlock.rs":"68584dffeb4368839774c0ee987481affc0547c38977a17970514f072a582d61","src/util.rs":"26325483bcd23ab8ceb16bf47541152c5eb0bc394f247795c14698fa7b586692","tests/issue_203.rs":"5fbdf6ec63f391d86457df949678c203a1e81e8aa32d4e10037fa76e768702c0"},"package":"7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"}

28
third_party/rust/parking_lot/CHANGELOG.md поставляемый
Просмотреть файл

@ -1,3 +1,31 @@
## parking_lot 0.11.2, parking_lot_core 0.8.4, lock_api 0.4.5 (2021-08-28)
- Fixed incorrect memory orderings on `RwLock` and `WordLock`. (#294, #292)
- Added `Arc`-based lock guards. (#291)
- Added workaround for TSan's lack of support for `fence`. (#292)
## lock_api 0.4.4 (2021-05-01)
- Update for latest nightly. (#281)
## lock_api 0.4.3 (2021-04-03)
- Added `[Raw]ReentrantMutex::is_owned`. (#280)
## parking_lot_core 0.8.3 (2021-02-12)
- Updated smallvec to 1.6. (#276)
## parking_lot_core 0.8.2 (2020-12-21)
- Fixed assertion failure on OpenBSD. (#270)
## parking_lot_core 0.8.1 (2020-12-04)
- Removed deprecated CloudABI support. (#263)
- Fixed build on wasm32-unknown-unknown. (#265)
- Relaxed dependency on `smallvec`. (#266)
## parking_lot 0.11.1, lock_api 0.4.2 (2020-11-18)
- Fix bounds on Send and Sync impls for lock guards. (#262)

22
third_party/rust/parking_lot/Cargo.toml поставляемый
Просмотреть файл

@ -3,17 +3,16 @@
# 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 = "parking_lot"
version = "0.11.1"
version = "0.11.2"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "More compact and efficient implementations of the standard synchronization primitives."
readme = "README.md"
@ -22,20 +21,21 @@ categories = ["concurrency"]
license = "Apache-2.0/MIT"
repository = "https://github.com/Amanieu/parking_lot"
[dependencies.instant]
version = "0.1.4"
version = "0.1.9"
[dependencies.lock_api]
version = "0.4.0"
version = "0.4.5"
[dependencies.parking_lot_core]
version = "0.8.0"
version = "0.8.4"
[dev-dependencies.bincode]
version = "1.3.0"
version = "1.3.3"
[dev-dependencies.rand]
version = "0.7.3"
version = "0.8.3"
[features]
arc_lock = ["lock_api/arc_lock"]
deadlock_detection = ["parking_lot_core/deadlock_detection"]
default = []
nightly = ["parking_lot_core/nightly", "lock_api/nightly"]

Просмотреть файл

@ -362,7 +362,7 @@ unsafe impl lock_api::RawRwLockUpgrade for RawRwLock {
unsafe fn upgrade(&self) {
let state = self.state.fetch_sub(
(ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
Ordering::Relaxed,
Ordering::Acquire,
);
if state & READERS_MASK != ONE_READER {
let result = self.upgrade_slow(None);
@ -377,7 +377,7 @@ unsafe impl lock_api::RawRwLockUpgrade for RawRwLock {
.compare_exchange_weak(
ONE_READER | UPGRADABLE_BIT,
WRITER_BIT,
Ordering::Relaxed,
Ordering::Acquire,
Ordering::Relaxed,
)
.is_ok()

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"5c6baed932139022eb9544cb9b2ea8434bd1dc4add567257bbc0245f52efaa85","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"7baf09034aafc28f7dbb1550cdde89221e4eb5dfda51b55aeb652ee8710c715d","src/parking_lot.rs":"58125667bd78399e8753b6bd8acef84f180f369f0bc174c573887176bab9f9d3","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"4a2c76b3dc09301ceb73d904460f49d91bc1a2492cc123ee26ca22ece3faae79","src/thread_parker/mod.rs":"9c675b7690bbde62e88d946fad218623d423edccff4e01e8e52b116d815c695c","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"8ff84ab0a629e8891b663226c8867ae4bb0fc63f0b3504e85b4583e7bf73a589","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"cf761157803256b18205e747bc99e30b18d5410c27121fa9595e12cb51bb6bef","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"2c030aedb340ae8ca564365206452c298fe29986d005d6a40e808c9760f91c95"},"package":"d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"}
{"files":{"Cargo.toml":"fdba14f9aee05b55ba008685e1d3a9050d14a56251608b23cc0970caa6b9fae4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"29e629057144d1238dcd8ea70ad6cbb6ec14ca742797af3fa9335710ff5cbaaa","src/lib.rs":"7baf09034aafc28f7dbb1550cdde89221e4eb5dfda51b55aeb652ee8710c715d","src/parking_lot.rs":"58125667bd78399e8753b6bd8acef84f180f369f0bc174c573887176bab9f9d3","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"4a2c76b3dc09301ceb73d904460f49d91bc1a2492cc123ee26ca22ece3faae79","src/thread_parker/mod.rs":"9c675b7690bbde62e88d946fad218623d423edccff4e01e8e52b116d815c695c","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"02a17ad1241e8547cc7ee096318757b01d328354b639d0f799fca66ff2f07439","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"cf761157803256b18205e747bc99e30b18d5410c27121fa9595e12cb51bb6bef","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"9ba49082359c35ad5b4e8d219fede1ffca75225f9ccb971cbba01f20e2ed2738"},"package":"d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"}

25
third_party/rust/parking_lot_core/Cargo.toml поставляемый
Просмотреть файл

@ -3,17 +3,16 @@
# 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 = "parking_lot_core"
version = "0.8.1"
version = "0.8.5"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
@ -21,33 +20,33 @@ categories = ["concurrency"]
license = "Apache-2.0/MIT"
repository = "https://github.com/Amanieu/parking_lot"
[dependencies.backtrace]
version = "0.3.49"
version = "0.3.60"
optional = true
[dependencies.cfg-if]
version = "1.0.0"
[dependencies.instant]
version = "0.1.4"
version = "0.1.9"
[dependencies.petgraph]
version = "0.5.1"
optional = true
[dependencies.smallvec]
version = "1.0"
version = "1.6.1"
[dependencies.thread-id]
version = "3.3.0"
version = "4.0.0"
optional = true
[features]
deadlock_detection = ["petgraph", "thread-id", "backtrace"]
nightly = []
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
version = "0.1.56"
version = "0.2.8"
[target."cfg(unix)".dependencies.libc]
version = "0.2.71"
version = "0.2.95"
[target."cfg(windows)".dependencies.winapi]
version = "0.3.8"
version = "0.3.9"
features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"]

10
third_party/rust/parking_lot_core/build.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
// Automatically detect tsan in a way that's compatible with both stable (which
// doesn't support sanitizers) and nightly (which does). Works because build
// scripts gets `cfg` info, even if the cfg is unstable.
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let santizer_list = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default();
if santizer_list.contains("thread") {
println!("cargo:rustc-cfg=tsan_enabled");
}
}

Просмотреть файл

@ -156,17 +156,9 @@ impl Drop for ThreadParker {
// this behaviour no longer occurs. The same applies to condvars.
unsafe {
let r = libc::pthread_mutex_destroy(self.mutex.get());
if cfg!(target_os = "dragonfly") {
debug_assert!(r == 0 || r == libc::EINVAL);
} else {
debug_assert_eq!(r, 0);
}
debug_assert!(r == 0 || r == libc::EINVAL);
let r = libc::pthread_cond_destroy(self.condvar.get());
if cfg!(target_os = "dragonfly") {
debug_assert!(r == 0 || r == libc::EINVAL);
} else {
debug_assert_eq!(r, 0);
}
debug_assert!(r == 0 || r == libc::EINVAL);
}
}
}

Просмотреть файл

@ -154,7 +154,7 @@ impl WordLock {
if let Err(x) = self.state.compare_exchange_weak(
state,
state.with_queue_head(thread_data),
Ordering::Release,
Ordering::AcqRel,
Ordering::Relaxed,
) {
return x;
@ -238,7 +238,7 @@ impl WordLock {
}
// Need an acquire fence before reading the new queue
fence(Ordering::Acquire);
fence_acquire(&self.state);
continue;
}
@ -263,7 +263,7 @@ impl WordLock {
continue;
} else {
// Need an acquire fence before reading the new queue
fence(Ordering::Acquire);
fence_acquire(&self.state);
continue 'outer;
}
}
@ -286,6 +286,17 @@ impl WordLock {
}
}
// Thread-Sanitizer only has partial fence support, so when running under it, we
// try and avoid false positives by using a discarded acquire load instead.
#[inline]
fn fence_acquire(a: &AtomicUsize) {
if cfg!(tsan_enabled) {
let _ = a.load(Ordering::Acquire);
} else {
fence(Ordering::Acquire);
}
}
trait LockState {
fn is_locked(self) -> bool;
fn is_queue_locked(self) -> bool;

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"9494475634c86ca0cfc30688aaf3e3961c0bdab1380e12a9e36597b24dece24c","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"5d9afb0813ca903cd5ac48add7f6f9b538d9e0346bc9bac0924d509d2004c07b","src/arch/arm.rs":"6f0eea58ea5dc7e87a66f335cb4264995bdf5352b379428dd0ba6a11887491a6","src/arch/nonredox.rs":"de54557f642218b34d451fc52fe3cff97e3e4307304ae02a678a900cab96cdb0","src/arch/x86.rs":"a433a3cfaf4fe2987e7516069e814f539172a1bb51d02bcfab74fa4c56dd9fdf","src/arch/x86_64.rs":"0bb1ebc3aba5d240b2ab813f6aa999b071d1230641849775d38d2074e2e4026a","src/call.rs":"b5b53aab18bb91bfef88d82f1708d05e210a30cde141fce0031dad543d988391","src/data.rs":"84f8beb9d40b753a8c1713b922e99ed9913d35e959694b2c849351b1a92d87c9","src/error.rs":"d832a641ccb1baf10315e2e1ce59b12c30d605a526fc65a31f63bb3a92c3a2f7","src/flag.rs":"1e944be3b134d3776725529e2190e2d1548dd67a631838281b8c5bc829523dbe","src/io/dma.rs":"740cd441f844718a14f77c2fe292d29b7c468d686505810d8b3281f9528a6fe7","src/io/io.rs":"1bcb36d1867e9bab6a8186cd6928efe70ae2655e9f9d0dd3def20bc0fb6a82f6","src/io/mmio.rs":"b9fdb37d37a25a48106d60f1a977c541cb5162b20b12507c7dcd6eb3dff0a2c8","src/io/mod.rs":"4df12af3e82e6b5fe22112c9f51552112ee4811b7d1131d2a43d608d8d1cac09","src/io/pio.rs":"39f4176a2995c7acfb32204b065af0ec14d7ff0d45dc51eff2679f3195c36ee2","src/lib.rs":"a5a56fa43f30d2d994075539425ffaa8da7106ccd77c3022950623eb82cd59b1","src/number.rs":"4718baa58a0f3e6b9b66d1f328cb2a145e9b1f807654c3079a13b226c4085a29","src/scheme/generate.sh":"b022adacb74f2af1470e691341c37acc1582f428e9b8b6b9dccb790dde594b40","src/scheme/mod.rs":"2679272397bf0247e1a4695853465243ca02960feb4ced1124969f67ebd3e3ce","src/scheme/scheme.rs":"879728e4d4e7d8f3057df5a3a6af1636079135652594ee50ca1b665e876be595","src/scheme/scheme_block.rs":"a8ea17b1101548e9b36f6c9000f68fd5438a796069252f948bde7dda44088a7f","src/scheme/scheme_block_mut.rs":"8b881f84a54e2477967d43eb68dac7c578ff6451dba59eba0d517037b2ac4def","src/scheme/scheme_mut.rs":"30f9b0750437b7f55d5bb24da546fd4afcb3c27b0af06d5f681b8f1c4877e7b4","src/tests.rs":"b9d60e419f7e57bb942756e8011e19704cfd46fb6ec96ffa925fb7deb35c5d43"},"package":"41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"}
{"files":{"Cargo.toml":"69f08bb56c6fc199b61cbe959b6e9f93df554f5d4e87d5e64551116cedf15067","LICENSE":"efcfee7981ff72431fffb06925cad00a23dce079ed4354f61030ad5abdb78829","README.md":"9161f18ba7f69b4ca51e844aee8ffb8237513a468c5c3b1f3a5f989044f895ac","src/arch/aarch64.rs":"61b5811b47a29257c3b5e15e7d9d15e7143bad99fbe29f0cb17ead9cbc17186f","src/arch/nonredox.rs":"9eac0fa2cf9eae07f0cafa2dd63c4a820791897a3de9ad1a933ab4f53458dbd8","src/arch/riscv64.rs":"20bf9a8db779059773b113643d0cb3737fbb5d57f45ee39b8ae9d3396b6ef636","src/arch/x86_64.rs":"f40bad2680fd5e7f100ee1afaa805f33dd0e12ec8786b956d47204f66771801d","src/call.rs":"0d3e32e33ecdf75963e5d244f9e86e94047d155c5de5fa3c0085faf18ed97b33","src/daemon.rs":"11cd633298fe2eb89906a4d8c12ab34e4ee355f759e1216cee536f24c7c679b2","src/data.rs":"bd4545d4c2fcc59ff26ae52ad7f773a697d5ccf639a2ffc253cece6b31e94d51","src/error.rs":"ef20f3817f997a1aeb7114628407f19cb8bc13c555d4e093918f38a5d098f798","src/flag.rs":"f07d6a7aa6766d30d0a303c7b3bda5bb4c473dd9dd51687cf8e0631b1bf3ec9d","src/io/dma.rs":"fbc46e924d5913f5a3fb723751d7a9dd1b079ccf058500fde4957aaf9fa7dd1c","src/io/io.rs":"e1d454ff47efac70fdaa709251a5a9c1c5637f931994ba3bf6a38c6db9145822","src/io/mmio.rs":"12d0fb4d4f45097bf2c14f73cb1ce21325eae193b537e9f18af73ed5281b5e63","src/io/mod.rs":"62438ff452c266692ea8fcfc4b6aad73184a1f67276327a4d5f71c4fbbaeab55","src/io/pio.rs":"9ee6f2229b700d1c45b4c8c6242bd99fe69634e16dcd5843d9e8d1c958047406","src/lib.rs":"d30eec6d2480c6dbc74221a10cc662a649bd24dc3ac640bbcdab9e416aab727f","src/number.rs":"fe7b47b06566aa1f8a75f50b685801259df03a1a5c85b91817b4552583cd7862","src/scheme/generate.sh":"dde4e30f4e0223fb1a24ed486a6c36e624c854dbf890862cb6866f4fa3c7a6eb","src/scheme/mod.rs":"cb622405deb0aef4ab04499ea1adfd338c9c5dd9c31a1fe9989786dbf69b49d8","src/scheme/scheme.rs":"30263996f0b4930edd76dace5f5750e48229066bc888bc13365846688d0a870b","src/scheme/scheme_block.rs":"b7a761e4349eb87d106c8af14894e8c4272769b9eb235cd500b075ac1f823683","src/scheme/scheme_block_mut.rs":"4a4fc03bce14757b64006b9bc3fa2779e95382b2d99579870146ee0c3be3f46c","src/scheme/scheme_mut.rs":"e6f0671b77f1bf5263e497c69dec553352249b75d52af62ac19477ba5127f803","src/scheme/seek.rs":"94e044de47b0f00eb0c2aea3fb21001ac2b9aa1e4b20d73fd54163fe92fa63f7","src/tests.rs":"416a428ba6a9c5f0d8f4c3dbe91d9aa940a04472ec9a2d17bc5a66c455b4416f"},"package":"62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"}

15
third_party/rust/redox_syscall/Cargo.toml поставляемый
Просмотреть файл

@ -3,16 +3,16 @@
# 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 = "redox_syscall"
version = "0.1.57"
version = "0.2.13"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
description = "A Rust library to access raw Redox system calls"
documentation = "https://docs.rs/redox_syscall"
@ -21,3 +21,6 @@ repository = "https://gitlab.redox-os.org/redox-os/syscall"
[lib]
name = "syscall"
[dependencies.bitflags]
version = "1.1.0"

Просмотреть файл

@ -1,77 +1,132 @@
use core::{mem, slice};
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a)
: "x0", "x8"
: "volatile");
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
let ret: usize;
Error::demux(a)
core::arch::asm!(
"svc 0",
in("x8") $a,
$(
in("x0") $b,
$(
in("x1") $c,
$(
in("x2") $d,
$(
in("x3") $e,
$(
in("x4") $f,
)?
)?
)?
)?
)?
lateout("x0") ret,
options(nostack),
);
Error::demux(ret)
}
)+
};
}
pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b)
: "x0", "x8"
: "volatile");
Error::demux(a)
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
// Clobbers all registers - special for clone
pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b)
: "memory",
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
"x16", "x17","x18", "x19", "x20", "x21", "x22", "x23",
"x24", "x25", "x26", "x27", "x28", "x29", "x30"
: "volatile");
Error::demux(a)
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
pub elr_el1: usize,
pub tpidr_el0: usize,
pub tpidrro_el0: usize,
pub spsr_el1: usize,
pub esr_el1: usize,
pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1
pub padding: usize, // To keep the struct even number aligned
pub x30: usize,
pub x29: usize,
pub x28: usize,
pub x27: usize,
pub x26: usize,
pub x25: usize,
pub x24: usize,
pub x23: usize,
pub x22: usize,
pub x21: usize,
pub x20: usize,
pub x19: usize,
pub x18: usize,
pub x17: usize,
pub x16: usize,
pub x15: usize,
pub x14: usize,
pub x13: usize,
pub x12: usize,
pub x11: usize,
pub x10: usize,
pub x9: usize,
pub x8: usize,
pub x7: usize,
pub x6: usize,
pub x5: usize,
pub x4: usize,
pub x3: usize,
pub x2: usize,
pub x1: usize,
pub x0: usize
}
pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b), "{x1}"(c)
: "x0", "x1", "x8"
: "volatile");
Error::demux(a)
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::<IntRegisters>())
}
}
}
pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d)
: "x0", "x1", "x2", "x8"
: "volatile");
Error::demux(a)
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::<IntRegisters>())
}
}
}
pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e)
: "x0", "x1", "x2", "x3", "x8"
: "volatile");
Error::demux(a)
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct FloatRegisters {
pub fp_simd_regs: [u128; 32],
pub fpsr: u32,
pub fpcr: u32
}
pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-> Result<usize> {
llvm_asm!("svc 0"
: "={x0}"(a)
: "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e), "{x4}"(f)
: "x0", "x1", "x2", "x3", "x4", "x8"
: "volatile");
Error::demux(a)
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::<FloatRegisters>())
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::<FloatRegisters>())
}
}
}

Просмотреть файл

@ -1,73 +0,0 @@
use super::error::{Error, Result};
pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a)
: "memory"
: "volatile");
Error::demux(a)
}
pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b)
: "memory"
: "volatile");
Error::demux(a)
}
// Clobbers all registers - special for clone
pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b)
: "memory", "r0", "r1", "r2", "r3", "r4"
: "volatile");
Error::demux(a)
}
pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b), "{r1}"(c)
: "memory"
: "volatile");
Error::demux(a)
}
pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d)
: "memory"
: "volatile");
Error::demux(a)
}
pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e)
: "memory"
: "volatile");
Error::demux(a)
}
pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-> Result<usize> {
llvm_asm!("swi $$0"
: "={r0}"(a)
: "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f)
: "memory"
: "volatile");
Error::demux(a)
}

Просмотреть файл

@ -8,11 +8,6 @@ pub unsafe fn syscall1(_a: usize, _b: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
// Clobbers all registers - special for clone
pub unsafe fn syscall1_clobber(_a: usize, _b: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}
pub unsafe fn syscall2(_a: usize, _b: usize, _c: usize) -> Result<usize> {
Err(Error::new(ENOSYS))
}

93
third_party/rust/redox_syscall/src/arch/riscv64.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,93 @@
use core::{mem, slice};
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name($a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
let ret: usize;
asm!(
"ecall",
in("a7") $a,
$(
in("a0") $b,
$(
in("a1") $c,
$(
in("a2") $d,
$(
in("a3") $e,
$(
in("a4") $f,
)?
)?
)?
)?
)?
lateout("a0") ret,
options(nostack),
);
Error::demux(ret)
}
)+
};
}
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
//TODO
}
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::<IntRegisters>())
}
}
}
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::<IntRegisters>())
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct FloatRegisters {
//TODO
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::<FloatRegisters>())
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::<FloatRegisters>())
}
}
}

Просмотреть файл

@ -1,73 +0,0 @@
use super::error::{Error, Result};
pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a)
: "memory"
: "intel", "volatile");
Error::demux(a)
}
pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b)
: "memory"
: "intel", "volatile");
Error::demux(a)
}
// Clobbers all registers - special for clone
pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b)
: "memory", "ebx", "ecx", "edx", "esi", "edi"
: "intel", "volatile");
Error::demux(a)
}
pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b), "{ecx}"(c)
: "memory"
: "intel", "volatile");
Error::demux(a)
}
pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d)
: "memory"
: "intel", "volatile");
Error::demux(a)
}
pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e)
: "memory"
: "intel", "volatile");
Error::demux(a)
}
pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-> Result<usize> {
llvm_asm!("int 0x80"
: "={eax}"(a)
: "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f)
: "memory"
: "intel", "volatile");
Error::demux(a)
}

Просмотреть файл

@ -1,74 +1,155 @@
use core::{mem, slice};
use core::arch::asm;
use core::ops::{Deref, DerefMut};
use super::error::{Error, Result};
pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a)
: "rcx", "r11", "memory"
: "intel", "volatile");
macro_rules! syscall {
($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => {
$(
pub unsafe fn $name(mut $a: usize, $($b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result<usize> {
asm!(
"syscall",
inout("rax") $a,
$(
in("rdi") $b,
$(
in("rsi") $c,
$(
in("rdx") $d,
$(
in("r10") $e,
$(
in("r8") $f,
)?
)?
)?
)?
)?
out("rcx") _,
out("r11") _,
options(nostack),
);
Error::demux(a)
Error::demux($a)
}
)+
};
}
pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b)
: "rcx", "r11", "memory"
: "intel", "volatile");
Error::demux(a)
syscall! {
syscall0(a,);
syscall1(a, b,);
syscall2(a, b, c,);
syscall3(a, b, c, d,);
syscall4(a, b, c, d, e,);
syscall5(a, b, c, d, e, f,);
}
// Clobbers all registers - special for clone
pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b)
: "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
"r9", "r10", "r11", "r12", "r13", "r14", "r15"
: "intel", "volatile");
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IntRegisters {
// TODO: Some of these don't get set by Redox yet. Should they?
Error::demux(a)
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub rbp: usize,
pub rbx: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rax: usize,
pub rcx: usize,
pub rdx: usize,
pub rsi: usize,
pub rdi: usize,
// pub orig_rax: usize,
pub rip: usize,
pub cs: usize,
pub rflags: usize,
pub rsp: usize,
pub ss: usize,
// pub fs_base: usize,
// pub gs_base: usize,
// pub ds: usize,
// pub es: usize,
pub fs: usize,
// pub gs: usize
}
pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b), "{rsi}"(c)
: "rcx", "r11", "memory"
: "intel", "volatile");
Error::demux(a)
impl Deref for IntRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::<IntRegisters>())
}
}
}
pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b), "{rsi}"(c), "{rdx}"(d)
: "rcx", "r11", "memory"
: "intel", "volatile");
Error::demux(a)
impl DerefMut for IntRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::<IntRegisters>())
}
}
}
pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b), "{rsi}"(c), "{rdx}"(d), "{r10}"(e)
: "rcx", "r11", "memory"
: "intel", "volatile");
Error::demux(a)
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct FloatRegisters {
pub fcw: u16,
pub fsw: u16,
pub ftw: u8,
pub _reserved: u8,
pub fop: u16,
pub fip: u64,
pub fdp: u64,
pub mxcsr: u32,
pub mxcsr_mask: u32,
pub st_space: [u128; 8],
pub xmm_space: [u128; 16],
// TODO: YMM/ZMM
}
pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
-> Result<usize> {
llvm_asm!("syscall"
: "={rax}"(a)
: "{rax}"(a), "{rdi}"(b), "{rsi}"(c), "{rdx}"(d), "{r10}"(e), "{r8}"(f)
: "rcx", "r11", "memory"
: "intel", "volatile");
Error::demux(a)
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::<FloatRegisters>())
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::<FloatRegisters>())
}
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(packed)]
pub struct EnvRegisters {
pub fsbase: u64,
pub gsbase: u64,
// TODO: PKRU?
}
impl Deref for EnvRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const EnvRegisters as *const u8, mem::size_of::<EnvRegisters>())
}
}
}
impl DerefMut for EnvRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut EnvRegisters as *mut u8, mem::size_of::<EnvRegisters>())
}
}
}

93
third_party/rust/redox_syscall/src/call.rs поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
use super::arch::*;
use super::data::{Map, SigAction, Stat, StatVfs, TimeSpec};
use super::error::Result;
use super::flag::*;
use super::number::*;
use core::{mem, ptr};
@ -11,20 +12,6 @@ extern "C" fn restorer() -> ! {
unreachable!();
}
/// Set the end of the process's heap
///
/// When `addr` is `0`, this function will return the current break.
///
/// When `addr` is nonzero, this function will attempt to set the end of the process's
/// heap to `addr` and return the new program break. The new program break should be
/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page
/// boundary.
///
/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available
pub unsafe fn brk(addr: usize) -> Result<usize> {
syscall1(SYS_BRK, addr)
}
/// Change the process's working directory
///
/// This function will attempt to set the process's working directory to `path`, which can be
@ -39,7 +26,7 @@ pub unsafe fn brk(addr: usize) -> Result<usize> {
/// * `EIO` - an I/O error occurred
/// * `ENOENT` - `path` does not exit
/// * `ENOTDIR` - `path` is not a directory
pub fn chdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
pub fn chdir<T: AsRef<str>>(path: T) -> Result<usize> {
unsafe { syscall2(SYS_CHDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
@ -47,13 +34,13 @@ pub fn chdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
since = "0.1.55",
note = "use fchmod instead"
)]
pub fn chmod<T: AsRef<[u8]>>(path: T, mode: usize) -> Result<usize> {
pub fn chmod<T: AsRef<str>>(path: T, mode: usize) -> Result<usize> {
unsafe { syscall3(SYS_CHMOD, path.as_ref().as_ptr() as usize, path.as_ref().len(), mode) }
}
/// Produce a fork of the current process, or a new process thread
pub unsafe fn clone(flags: usize) -> Result<usize> {
syscall1_clobber(SYS_CLONE, flags)
pub unsafe fn clone(flags: CloneFlags) -> Result<usize> {
syscall1(SYS_CLONE, flags.bits())
}
/// Close a file
@ -103,14 +90,23 @@ pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usiz
unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), vars.as_ptr() as usize, vars.len()) }
}
/// Map a file into memory
/// Map a file into memory, but with the ability to set the address to map into, either as a hint
/// or as a requirement of the map.
///
/// # Errors
/// `EACCES` - the file descriptor was not open for reading
/// `EBADF` - if the file descriptor was invalid
/// `ENODEV` - mmapping was not supported
/// `EINVAL` - invalid combination of flags
/// `EEXIST` - if [`MapFlags::MAP_FIXED`] was set, and the address specified was already in use.
///
pub unsafe fn fmap(fd: usize, map: &Map) -> Result<usize> {
syscall3(SYS_FMAP, fd, map as *const Map as usize, mem::size_of::<Map>())
}
/// Unmap a memory-mapped file
pub unsafe fn funmap(addr: usize) -> Result<usize> {
syscall1(SYS_FUNMAP, addr)
/// Unmap whole (or partial) continous memory-mapped files
pub unsafe fn funmap(addr: usize, len: usize) -> Result<usize> {
syscall2(SYS_FUNMAP, addr, len)
}
/// Retrieve the canonical path of a file
@ -119,7 +115,7 @@ pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
}
/// Rename a file
pub fn frename<T: AsRef<[u8]>>(fd: usize, path: T) -> Result<usize> {
pub fn frename<T: AsRef<str>>(fd: usize, path: T) -> Result<usize> {
unsafe { syscall3(SYS_FRENAME, fd, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
@ -235,8 +231,8 @@ pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
}
/// Change mapping flags
pub unsafe fn mprotect(addr: usize, size: usize, flags: usize) -> Result<usize> {
syscall3(SYS_MPROTECT, addr, size, flags)
pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result<usize> {
syscall3(SYS_MPROTECT, addr, size, flags.bits())
}
/// Sleep for the time specified in `req`
@ -246,11 +242,11 @@ pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
}
/// Open a file
pub fn open<T: AsRef<[u8]>>(path: T, flags: usize) -> Result<usize> {
pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
unsafe { syscall3(SYS_OPEN, path.as_ref().as_ptr() as usize, path.as_ref().len(), flags) }
}
/// Allocate pages, linearly in physical memory
/// Allocate frames, linearly in physical memory.
///
/// # Errors
///
@ -260,6 +256,37 @@ pub unsafe fn physalloc(size: usize) -> Result<usize> {
syscall1(SYS_PHYSALLOC, size)
}
/// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
/// [`PARTIAL_ALLOC`], this will result in `physalloc3` with `min = 1`.
///
/// Refer to the simpler [`physalloc`] and the more complex [`physalloc3`], that this convenience
/// function is based on.
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
pub unsafe fn physalloc2(size: usize, flags: usize) -> Result<usize> {
let mut ret = 1usize;
physalloc3(size, flags, &mut ret)
}
/// Allocate frames, linearly in physical memory, with an extra set of flags. If the flags contain
/// [`PARTIAL_ALLOC`], the `min` parameter specifies the number of frames that have to be allocated
/// for this operation to succeed. The return value is the offset of the first frame, and `min` is
/// overwritten with the number of frames actually allocated.
///
/// Refer to the simpler [`physalloc`] and the simpler library function [`physalloc2`].
///
/// # Errors
///
/// * `EPERM` - `uid != 0`
/// * `ENOMEM` - the system has run out of available memory
/// * `EINVAL` - `min = 0`
pub unsafe fn physalloc3(size: usize, flags: usize, min: &mut usize) -> Result<usize> {
syscall3(SYS_PHYSALLOC3, size, flags, min as *mut usize as usize)
}
/// Free physically allocated pages
///
/// # Errors
@ -274,8 +301,8 @@ pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
/// # Errors
///
/// * `EPERM` - `uid != 0`
pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
syscall3(SYS_PHYSMAP, physical_address, size, flags)
pub unsafe fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
syscall3(SYS_PHYSMAP, physical_address, size, flags.bits())
}
/// Unmap previously mapped physical memory
@ -299,7 +326,7 @@ pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
}
/// Remove a directory
pub fn rmdir<T: AsRef<[u8]>>(path: T) -> Result<usize> {
pub fn rmdir<T: AsRef<str>>(path: T) -> Result<usize> {
unsafe { syscall2(SYS_RMDIR, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
@ -349,7 +376,7 @@ pub fn umask(mask: usize) -> Result<usize> {
}
/// Remove a file
pub fn unlink<T: AsRef<[u8]>>(path: T) -> Result<usize> {
pub fn unlink<T: AsRef<str>>(path: T) -> Result<usize> {
unsafe { syscall2(SYS_UNLINK, path.as_ref().as_ptr() as usize, path.as_ref().len()) }
}
@ -363,8 +390,8 @@ pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
}
/// Check if a child process has exited or received a signal
pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> {
unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) }
pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result<usize> {
unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options.bits()) }
}
/// Write a buffer to a file descriptor

62
third_party/rust/redox_syscall/src/daemon.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,62 @@
use core::convert::Infallible;
use super::{
clone,
CloneFlags,
close,
EIO,
Error,
exit,
pipe2,
read,
Result,
write,
};
#[must_use = "Daemon::ready must be called"]
pub struct Daemon {
write_pipe: usize,
}
impl Daemon {
pub fn new<F: FnOnce(Daemon) -> Infallible>(f: F) -> Result<Infallible> {
let mut pipes = [0; 2];
pipe2(&mut pipes, 0)?;
let [read_pipe, write_pipe] = pipes;
if unsafe { clone(CloneFlags::empty())? } == 0 {
let _ = close(read_pipe);
f(Daemon {
write_pipe,
});
// TODO: Replace Infallible with the never type once it is stabilized.
unreachable!();
} else {
let _ = close(write_pipe);
let mut data = [0];
let res = read(read_pipe, &mut data);
let _ = close(read_pipe);
if res? == 1 {
exit(data[0] as usize)?;
unreachable!();
} else {
Err(Error::new(EIO))
}
}
}
pub fn ready(self) -> Result<()> {
let res = write(self.write_pipe, &[0]);
let _ = close(self.write_pipe);
if res? == 1 {
Ok(())
} else {
Err(Error::new(EIO))
}
}
}

188
third_party/rust/redox_syscall/src/data.rs поставляемый
Просмотреть файл

@ -1,11 +1,12 @@
use core::ops::{Deref, DerefMut};
use core::{mem, slice};
use crate::flag::{EventFlags, MapFlags, PtraceFlags, SigActionFlags};
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Event {
pub id: usize,
pub flags: usize,
pub flags: EventFlags,
pub data: usize
}
@ -13,7 +14,7 @@ impl Deref for Event {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>()) as &[u8]
slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>())
}
}
}
@ -21,7 +22,7 @@ impl Deref for Event {
impl DerefMut for Event {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>()) as &mut [u8]
slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>())
}
}
}
@ -38,7 +39,7 @@ impl Deref for ITimerSpec {
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const ITimerSpec as *const u8,
mem::size_of::<ITimerSpec>()) as &[u8]
mem::size_of::<ITimerSpec>())
}
}
}
@ -47,24 +48,58 @@ impl DerefMut for ITimerSpec {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut ITimerSpec as *mut u8,
mem::size_of::<ITimerSpec>()) as &mut [u8]
mem::size_of::<ITimerSpec>())
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Map {
pub struct OldMap {
pub offset: usize,
pub size: usize,
pub flags: usize,
pub flags: MapFlags,
}
impl Deref for OldMap {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const OldMap as *const u8, mem::size_of::<OldMap>())
}
}
}
impl DerefMut for OldMap {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut OldMap as *mut u8, mem::size_of::<OldMap>())
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Map {
/// The offset inside the file that is being mapped.
pub offset: usize,
/// The size of the memory map.
pub size: usize,
/// Contains both prot and map flags.
pub flags: MapFlags,
/// Functions as a hint to where in the virtual address space of the running process, to place
/// the memory map. If [`MapFlags::MAP_FIXED`] is set, then this address must be the address to
/// map to.
pub address: usize,
}
impl Deref for Map {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const Map as *const u8, mem::size_of::<Map>()) as &[u8]
slice::from_raw_parts(self as *const Map as *const u8, mem::size_of::<Map>())
}
}
}
@ -72,7 +107,7 @@ impl Deref for Map {
impl DerefMut for Map {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut Map as *mut u8, mem::size_of::<Map>()) as &mut [u8]
slice::from_raw_parts_mut(self as *mut Map as *mut u8, mem::size_of::<Map>())
}
}
}
@ -94,7 +129,7 @@ impl Deref for Packet {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::<Packet>()) as &[u8]
slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::<Packet>())
}
}
}
@ -102,30 +137,29 @@ impl Deref for Packet {
impl DerefMut for Packet {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::<Packet>()) as &mut [u8]
slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::<Packet>())
}
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct SigAction {
pub sa_handler: extern "C" fn(usize),
pub sa_handler: Option<extern "C" fn(usize)>,
pub sa_mask: [u64; 2],
pub sa_flags: usize,
pub sa_flags: SigActionFlags,
}
impl Default for SigAction {
fn default() -> Self {
Self {
sa_handler: unsafe { mem::transmute(0usize) },
sa_mask: [0; 2],
sa_flags: 0,
}
}
#[allow(dead_code)]
unsafe fn _assert_size_of_function_is_sane() {
// Transmuting will complain *at compile time* if sizes differ.
// Rust forbids a fn-pointer from being 0 so to allow SIG_DFL to
// exist, we use Option<extern "C" fn(usize)> which will mean 0
// becomes None
let _ = mem::transmute::<Option<extern "C" fn(usize)>, usize>(None);
}
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Stat {
pub st_dev: u64,
@ -150,7 +184,7 @@ impl Deref for Stat {
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const Stat as *const u8,
mem::size_of::<Stat>()) as &[u8]
mem::size_of::<Stat>())
}
}
}
@ -159,12 +193,12 @@ impl DerefMut for Stat {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut Stat as *mut u8,
mem::size_of::<Stat>()) as &mut [u8]
mem::size_of::<Stat>())
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct StatVfs {
pub f_bsize: u32,
@ -178,7 +212,7 @@ impl Deref for StatVfs {
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const StatVfs as *const u8,
mem::size_of::<StatVfs>()) as &[u8]
mem::size_of::<StatVfs>())
}
}
}
@ -187,7 +221,7 @@ impl DerefMut for StatVfs {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8,
mem::size_of::<StatVfs>()) as &mut [u8]
mem::size_of::<StatVfs>())
}
}
}
@ -204,7 +238,7 @@ impl Deref for TimeSpec {
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const TimeSpec as *const u8,
mem::size_of::<TimeSpec>()) as &[u8]
mem::size_of::<TimeSpec>())
}
}
}
@ -213,97 +247,51 @@ impl DerefMut for TimeSpec {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut TimeSpec as *mut u8,
mem::size_of::<TimeSpec>()) as &mut [u8]
mem::size_of::<TimeSpec>())
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
#[cfg(target_arch = "x86_64")]
pub struct IntRegisters {
pub r15: usize,
pub r14: usize,
pub r13: usize,
pub r12: usize,
pub rbp: usize,
pub rbx: usize,
pub r11: usize,
pub r10: usize,
pub r9: usize,
pub r8: usize,
pub rax: usize,
pub rcx: usize,
pub rdx: usize,
pub rsi: usize,
pub rdi: usize,
// pub orig_rax: usize,
pub rip: usize,
pub cs: usize,
pub eflags: usize,
pub rsp: usize,
pub ss: usize,
pub fs_base: usize,
pub gs_base: usize,
pub ds: usize,
pub es: usize,
pub fs: usize,
pub gs: usize
pub struct PtraceEvent {
pub cause: PtraceFlags,
pub a: usize,
pub b: usize,
pub c: usize,
pub d: usize,
pub e: usize,
pub f: usize
}
impl Deref for IntRegisters {
impl Deref for PtraceEvent {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::<IntRegisters>()) as &[u8]
slice::from_raw_parts(self as *const PtraceEvent as *const u8, mem::size_of::<PtraceEvent>())
}
}
}
impl DerefMut for IntRegisters {
impl DerefMut for PtraceEvent {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::<IntRegisters>()) as &mut [u8]
slice::from_raw_parts_mut(self as *mut PtraceEvent as *mut u8, mem::size_of::<PtraceEvent>())
}
}
}
#[derive(Clone, Copy)]
#[repr(C)]
#[cfg(target_arch = "x86_64")]
pub struct FloatRegisters {
pub cwd: u16,
pub swd: u16,
pub ftw: u16,
pub fop: u16,
pub rip: u64,
pub rdp: u64,
pub mxcsr: u32,
pub mxcr_mask: u32,
pub st_space: [u32; 32],
pub xmm_space: [u32; 64]
}
impl Default for FloatRegisters {
fn default() -> Self {
// xmm_space is not Default until const generics
unsafe { mem::zeroed() }
}
}
impl Deref for FloatRegisters {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::<FloatRegisters>()) as &[u8]
}
}
}
impl DerefMut for FloatRegisters {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::<FloatRegisters>()) as &mut [u8]
#[macro_export]
macro_rules! ptrace_event {
($cause:expr $(, $a:expr $(, $b:expr $(, $c:expr)?)?)?) => {
$crate::data::PtraceEvent {
cause: $cause,
$(a: $a,
$(b: $b,
$(c: $c,)?
)?
)?
..Default::default()
}
}
}

2
third_party/rust/redox_syscall/src/error.rs поставляемый
Просмотреть файл

@ -5,7 +5,7 @@ pub struct Error {
pub errno: i32,
}
pub type Result<T> = result::Result<T, Error>;
pub type Result<T, E = Error> = result::Result<T, E>;
impl Error {
pub fn new(errno: i32) -> Error {

251
third_party/rust/redox_syscall/src/flag.rs поставляемый
Просмотреть файл

@ -1,17 +1,59 @@
pub const CLONE_VM: usize = 0x100;
pub const CLONE_FS: usize = 0x200;
pub const CLONE_FILES: usize = 0x400;
pub const CLONE_SIGHAND: usize = 0x800;
pub const CLONE_VFORK: usize = 0x4000;
pub const CLONE_THREAD: usize = 0x10000;
pub const CLONE_STACK: usize = 0x1000_0000;
use bitflags::bitflags as inner_bitflags;
use core::{mem, ops::Deref, slice};
macro_rules! bitflags {
(
$(#[$outer:meta])*
pub struct $BitFlags:ident: $T:ty {
$(
$(#[$inner:ident $($args:tt)*])*
const $Flag:ident = $value:expr;
)+
}
) => {
// First, use the inner bitflags
inner_bitflags! {
#[derive(Default)]
$(#[$outer])*
pub struct $BitFlags: $T {
$(
$(#[$inner $($args)*])*
const $Flag = $value;
)+
}
}
// Secondly, re-export all inner constants
// (`pub use self::Struct::*` doesn't work)
$(
$(#[$inner $($args)*])*
pub const $Flag: $BitFlags = $BitFlags::$Flag;
)+
}
}
bitflags! {
pub struct CloneFlags: usize {
const CLONE_VM = 0x100;
const CLONE_FS = 0x200;
const CLONE_FILES = 0x400;
const CLONE_SIGHAND = 0x800;
const CLONE_VFORK = 0x4000;
const CLONE_THREAD = 0x10000;
const CLONE_STACK = 0x1000_0000;
}
}
pub const CLOCK_REALTIME: usize = 1;
pub const CLOCK_MONOTONIC: usize = 4;
pub const EVENT_NONE: usize = 0;
pub const EVENT_READ: usize = 1;
pub const EVENT_WRITE: usize = 2;
bitflags! {
pub struct EventFlags: usize {
const EVENT_NONE = 0;
const EVENT_READ = 1;
const EVENT_WRITE = 2;
}
}
pub const F_DUPFD: usize = 0;
pub const F_GETFD: usize = 1;
@ -22,9 +64,23 @@ pub const F_SETFL: usize = 4;
pub const FUTEX_WAIT: usize = 0;
pub const FUTEX_WAKE: usize = 1;
pub const FUTEX_REQUEUE: usize = 2;
pub const FUTEX_WAIT64: usize = 3;
pub const MAP_SHARED: usize = 0x0001;
pub const MAP_PRIVATE: usize = 0x0002;
bitflags! {
pub struct MapFlags: usize {
const PROT_NONE = 0x0000_0000;
const PROT_EXEC = 0x0001_0000;
const PROT_WRITE = 0x0002_0000;
const PROT_READ = 0x0004_0000;
const MAP_SHARED = 0x0001;
const MAP_PRIVATE = 0x0002;
/// Only accepted for mmap2(2).
const MAP_FIXED = 0x0004;
const MAP_FIXED_NOREPLACE = 0x000C;
}
}
pub const MODE_TYPE: u16 = 0xF000;
pub const MODE_DIR: u16 = 0x4000;
@ -56,21 +112,129 @@ pub const O_SYMLINK: usize = 0x4000_0000;
pub const O_NOFOLLOW: usize = 0x8000_0000;
pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR;
pub const PHYSMAP_WRITE: usize = 0x0000_0001;
pub const PHYSMAP_WRITE_COMBINE: usize = 0x0000_0002;
pub const PHYSMAP_NO_CACHE: usize = 0x0000_0004;
bitflags! {
pub struct PhysmapFlags: usize {
const PHYSMAP_WRITE = 0x0000_0001;
const PHYSMAP_WRITE_COMBINE = 0x0000_0002;
const PHYSMAP_NO_CACHE = 0x0000_0004;
}
}
bitflags! {
/// Extra flags for [`physalloc2`] or [`physalloc3`].
///
/// [`physalloc2`]: ../call/fn.physalloc2.html
/// [`physalloc3`]: ../call/fn.physalloc3.html
pub struct PhysallocFlags: usize {
/// Only allocate memory within the 32-bit physical memory space. This is necessary for
/// some devices may not support 64-bit memory.
const SPACE_32 = 0x0000_0001;
pub const PROT_NONE: usize = 0x0000_0000;
pub const PROT_EXEC: usize = 0x0001_0000;
pub const PROT_WRITE: usize = 0x0002_0000;
pub const PROT_READ: usize = 0x0004_0000;
/// The frame that will be allocated, is going to reside anywhere in 64-bit space. This
/// flag is redundant for the most part, except when overriding some other default.
const SPACE_64 = 0x0000_0002;
pub const PTRACE_CONT: u8 = 0b0000_0001;
pub const PTRACE_SINGLESTEP: u8 = 0b0000_0010;
pub const PTRACE_SYSCALL: u8 = 0b0000_0011;
pub const PTRACE_WAIT: u8 = 0b0000_0100;
pub const PTRACE_OPERATIONMASK: u8 = 0b0000_1111;
pub const PTRACE_SYSEMU: u8 = 0b0001_0000;
/// Do a "partial allocation", which means that not all of the frames specified in the
/// frame count `size` actually have to be allocated. This means that if the allocator was
/// unable to find a physical memory range large enough, it can instead return whatever
/// range it decides is optimal. Thus, instead of letting one driver get an expensive
/// 128MiB physical memory range when the physical memory has become fragmented, and
/// failing, it can instead be given a more optimal range. If the device supports
/// scatter-gather lists, then the driver only has to allocate more ranges, and the device
/// will do vectored I/O.
///
/// PARTIAL_ALLOC supports different allocation strategies, refer to
/// [`Optimal`], [`GreatestRange`].
///
/// [`Optimal`]: ./enum.PartialAllocStrategy.html
/// [`GreatestRange`]: ./enum.PartialAllocStrategy.html
const PARTIAL_ALLOC = 0x0000_0004;
}
}
/// The bitmask of the partial allocation strategy. Currently four different strategies are
/// supported. If [`PARTIAL_ALLOC`] is not set, this bitmask is no longer reserved.
pub const PARTIAL_ALLOC_STRATEGY_MASK: usize = 0x0003_0000;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(usize)]
pub enum PartialAllocStrategy {
/// The allocator decides itself the size of the memory range, based on e.g. free memory ranges
/// and other processes which require large physical memory chunks.
Optimal = 0x0001_0000,
/// The allocator returns the absolute greatest range it can find.
GreatestRange = 0x0002_0000,
/// The allocator returns the first range that fits the minimum count, without searching extra.
Greedy = 0x0003_0000,
}
impl Default for PartialAllocStrategy {
fn default() -> Self {
Self::Optimal
}
}
impl PartialAllocStrategy {
pub fn from_raw(raw: usize) -> Option<Self> {
match raw {
0x0001_0000 => Some(Self::Optimal),
0x0002_0000 => Some(Self::GreatestRange),
0x0003_0000 => Some(Self::Greedy),
_ => None,
}
}
}
// The top 48 bits of PTRACE_* are reserved, for now
bitflags! {
pub struct PtraceFlags: u64 {
/// Stop before a syscall is handled. Send PTRACE_FLAG_IGNORE to not
/// handle the syscall.
const PTRACE_STOP_PRE_SYSCALL = 0x0000_0000_0000_0001;
/// Stop after a syscall is handled.
const PTRACE_STOP_POST_SYSCALL = 0x0000_0000_0000_0002;
/// Stop after exactly one instruction. TODO: This may not handle
/// fexec/signal boundaries. Should it?
const PTRACE_STOP_SINGLESTEP = 0x0000_0000_0000_0004;
/// Stop before a signal is handled. Send PTRACE_FLAG_IGNORE to not
/// handle signal.
const PTRACE_STOP_SIGNAL = 0x0000_0000_0000_0008;
/// Stop on a software breakpoint, such as the int3 instruction for
/// x86_64.
const PTRACE_STOP_BREAKPOINT = 0x0000_0000_0000_0010;
/// Stop just before exiting for good.
const PTRACE_STOP_EXIT = 0x0000_0000_0000_0020;
const PTRACE_STOP_MASK = 0x0000_0000_0000_00FF;
/// Sent when a child is cloned, giving you the opportunity to trace it.
/// If you don't catch this, the child is started as normal.
const PTRACE_EVENT_CLONE = 0x0000_0000_0000_0100;
const PTRACE_EVENT_MASK = 0x0000_0000_0000_0F00;
/// Special meaning, depending on the event. Usually, when fired before
/// an action, it will skip performing that action.
const PTRACE_FLAG_IGNORE = 0x0000_0000_0000_1000;
const PTRACE_FLAG_MASK = 0x0000_0000_0000_F000;
}
}
impl Deref for PtraceFlags {
type Target = [u8];
fn deref(&self) -> &Self::Target {
// Same as to_ne_bytes but in-place
unsafe {
slice::from_raw_parts(
&self.bits as *const _ as *const u8,
mem::size_of::<u64>()
)
}
}
}
pub const SEEK_SET: usize = 0;
pub const SEEK_CUR: usize = 1;
@ -115,18 +279,33 @@ pub const SIG_BLOCK: usize = 0;
pub const SIG_UNBLOCK: usize = 1;
pub const SIG_SETMASK: usize = 2;
pub const SA_NOCLDSTOP: usize = 0x00000001;
pub const SA_NOCLDWAIT: usize = 0x00000002;
pub const SA_SIGINFO: usize = 0x00000004;
pub const SA_RESTORER: usize = 0x04000000;
pub const SA_ONSTACK: usize = 0x08000000;
pub const SA_RESTART: usize = 0x10000000;
pub const SA_NODEFER: usize = 0x40000000;
pub const SA_RESETHAND: usize = 0x80000000;
bitflags! {
pub struct SigActionFlags: usize {
const SA_NOCLDSTOP = 0x00000001;
const SA_NOCLDWAIT = 0x00000002;
const SA_SIGINFO = 0x00000004;
const SA_RESTORER = 0x04000000;
const SA_ONSTACK = 0x08000000;
const SA_RESTART = 0x10000000;
const SA_NODEFER = 0x40000000;
const SA_RESETHAND = 0x80000000;
}
}
pub const WNOHANG: usize = 0x01;
pub const WUNTRACED: usize = 0x02;
pub const WCONTINUED: usize = 0x08;
// Auxiliery vector types
pub const AT_NULL: usize = 0;
pub const AT_PHDR: usize = 3;
pub const AT_PHENT: usize = 4;
pub const AT_PHNUM: usize = 5;
pub const AT_ENTRY: usize = 9;
bitflags! {
pub struct WaitFlags: usize {
const WNOHANG = 0x01;
const WUNTRACED = 0x02;
const WCONTINUED = 0x08;
}
}
/// True if status indicates the child is stopped.
pub fn wifstopped(status: usize) -> bool {

188
third_party/rust/redox_syscall/src/io/dma.rs поставляемый
Просмотреть файл

@ -1,76 +1,200 @@
use core::{mem, ptr};
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::{ptr, slice};
use Result;
use crate::Result;
use crate::{PartialAllocStrategy, PhysallocFlags};
struct PhysBox {
/// An RAII guard of a physical memory allocation. Currently all physically allocated memory are
/// page-aligned and take up at least 4k of space (on x86_64).
#[derive(Debug)]
pub struct PhysBox {
address: usize,
size: usize
}
impl PhysBox {
fn new(size: usize) -> Result<PhysBox> {
let address = unsafe { ::physalloc(size)? };
Ok(PhysBox {
address: address,
size: size
/// Construct a PhysBox from an address and a size.
///
/// # Safety
/// This function is unsafe because when dropping, Self has to a valid allocation.
pub unsafe fn from_raw_parts(address: usize, size: usize) -> Self {
Self {
address,
size,
}
}
/// Retrieve the byte address in physical memory, of this allocation.
pub fn address(&self) -> usize {
self.address
}
/// Retrieve the size in bytes of the alloc.
pub fn size(&self) -> usize {
self.size
}
/// Allocate physical memory that must reside in 32-bit space.
pub fn new_in_32bit_space(size: usize) -> Result<Self> {
Self::new_with_flags(size, PhysallocFlags::SPACE_32)
}
pub fn new_with_flags(size: usize, flags: PhysallocFlags) -> Result<Self> {
assert!(!flags.contains(PhysallocFlags::PARTIAL_ALLOC));
let address = unsafe { crate::physalloc2(size, flags.bits())? };
Ok(Self {
address,
size,
})
}
/// "Partially" allocate physical memory, in the sense that the allocation may be smaller than
/// expected, but still with a minimum limit. This is particularly useful when the physical
/// memory space is fragmented, and a device supports scatter-gather I/O. In that case, the
/// driver can optimistically request e.g. 1 alloc of 1 MiB, with the minimum of 512 KiB. If
/// that first allocation only returns half the size, the driver can do another allocation
/// and then let the device use both buffers.
pub fn new_partial_allocation(size: usize, flags: PhysallocFlags, strategy: Option<PartialAllocStrategy>, mut min: usize) -> Result<Self> {
debug_assert!(!(flags.contains(PhysallocFlags::PARTIAL_ALLOC) && strategy.is_none()));
let address = unsafe { crate::physalloc3(size, flags.bits() | strategy.map(|s| s as usize).unwrap_or(0), &mut min)? };
Ok(Self {
address,
size: min,
})
}
pub fn new(size: usize) -> Result<Self> {
let address = unsafe { crate::physalloc(size)? };
Ok(Self {
address,
size,
})
}
}
impl Drop for PhysBox {
fn drop(&mut self) {
let _ = unsafe { ::physfree(self.address, self.size) };
let _ = unsafe { crate::physfree(self.address, self.size) };
}
}
pub struct Dma<T> {
pub struct Dma<T: ?Sized> {
phys: PhysBox,
virt: *mut T
virt: *mut T,
}
impl<T> Dma<T> {
pub fn new(value: T) -> Result<Dma<T>> {
let phys = PhysBox::new(mem::size_of::<T>())?;
let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T;
unsafe { ptr::write(virt, value); }
pub fn from_physbox_uninit(phys: PhysBox) -> Result<Dma<MaybeUninit<T>>> {
let virt = unsafe { crate::physmap(phys.address, phys.size, crate::PHYSMAP_WRITE)? } as *mut MaybeUninit<T>;
Ok(Dma {
phys: phys,
virt: virt
phys,
virt,
})
}
pub fn from_physbox_zeroed(phys: PhysBox) -> Result<Dma<MaybeUninit<T>>> {
let this = Self::from_physbox_uninit(phys)?;
unsafe { ptr::write_bytes(this.virt as *mut MaybeUninit<u8>, 0, this.phys.size) }
Ok(this)
}
pub fn from_physbox(phys: PhysBox, value: T) -> Result<Self> {
let this = Self::from_physbox_uninit(phys)?;
Ok(unsafe {
ptr::write(this.virt, MaybeUninit::new(value));
this.assume_init()
})
}
pub fn zeroed() -> Result<Dma<T>> {
pub fn new(value: T) -> Result<Self> {
let phys = PhysBox::new(mem::size_of::<T>())?;
let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T;
unsafe { ptr::write_bytes(virt as *mut u8, 0, phys.size); }
Ok(Dma {
phys: phys,
virt: virt
})
Self::from_physbox(phys, value)
}
pub fn physical(&self) -> usize {
self.phys.address
pub fn zeroed() -> Result<Dma<MaybeUninit<T>>> {
let phys = PhysBox::new(mem::size_of::<T>())?;
Self::from_physbox_zeroed(phys)
}
}
impl<T> Deref for Dma<T> {
impl<T> Dma<MaybeUninit<T>> {
pub unsafe fn assume_init(self) -> Dma<T> {
let &Dma { phys: PhysBox { address, size }, virt } = &self;
mem::forget(self);
Dma {
phys: PhysBox { address, size },
virt: virt as *mut T,
}
}
}
impl<T: ?Sized> Dma<T> {
pub fn physical(&self) -> usize {
self.phys.address()
}
pub fn size(&self) -> usize {
self.phys.size()
}
pub fn phys(&self) -> &PhysBox {
&self.phys
}
}
impl<T> Dma<[T]> {
pub fn from_physbox_uninit_unsized(phys: PhysBox, len: usize) -> Result<Dma<[MaybeUninit<T>]>> {
let max_len = phys.size() / mem::size_of::<T>();
assert!(len <= max_len);
Ok(Dma {
virt: unsafe { slice::from_raw_parts_mut(crate::physmap(phys.address, phys.size, crate::PHYSMAP_WRITE)? as *mut MaybeUninit<T>, len) } as *mut [MaybeUninit<T>],
phys,
})
}
pub fn from_physbox_zeroed_unsized(phys: PhysBox, len: usize) -> Result<Dma<[MaybeUninit<T>]>> {
let this = Self::from_physbox_uninit_unsized(phys, len)?;
unsafe { ptr::write_bytes(this.virt as *mut MaybeUninit<u8>, 0, this.phys.size()) }
Ok(this)
}
/// Creates a new DMA buffer with a size only known at runtime.
/// ## Safety
/// * `T` must be properly aligned.
/// * `T` must be valid as zeroed (i.e. no NonNull pointers).
pub unsafe fn zeroed_unsized(count: usize) -> Result<Self> {
let phys = PhysBox::new(mem::size_of::<T>() * count)?;
Ok(Self::from_physbox_zeroed_unsized(phys, count)?.assume_init())
}
}
impl<T> Dma<[MaybeUninit<T>]> {
pub unsafe fn assume_init(self) -> Dma<[T]> {
let &Dma { phys: PhysBox { address, size }, virt } = &self;
mem::forget(self);
Dma {
phys: PhysBox { address, size },
virt: virt as *mut [T],
}
}
}
impl<T: ?Sized> Deref for Dma<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.virt }
}
}
impl<T> DerefMut for Dma<T> {
impl<T: ?Sized> DerefMut for Dma<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.virt }
}
}
impl<T> Drop for Dma<T> {
impl<T: ?Sized> Drop for Dma<T> {
fn drop(&mut self) {
unsafe { drop(ptr::read(self.virt)); }
let _ = unsafe { ::physunmap(self.virt as usize) };
unsafe { ptr::drop_in_place(self.virt) }
let _ = unsafe { crate::physunmap(self.virt as *mut u8 as usize) };
}
}

12
third_party/rust/redox_syscall/src/io/io.rs поставляемый
Просмотреть файл

@ -22,17 +22,19 @@ pub trait Io {
}
}
pub struct ReadOnly<I: Io> {
pub struct ReadOnly<I> {
inner: I
}
impl<I: Io> ReadOnly<I> {
impl<I> ReadOnly<I> {
pub const fn new(inner: I) -> ReadOnly<I> {
ReadOnly {
inner: inner
}
}
}
impl<I: Io> ReadOnly<I> {
#[inline(always)]
pub fn read(&self) -> I::Value {
self.inner.read()
@ -44,17 +46,19 @@ impl<I: Io> ReadOnly<I> {
}
}
pub struct WriteOnly<I: Io> {
pub struct WriteOnly<I> {
inner: I
}
impl<I: Io> WriteOnly<I> {
impl<I> WriteOnly<I> {
pub const fn new(inner: I) -> WriteOnly<I> {
WriteOnly {
inner: inner
}
}
}
impl<I: Io> WriteOnly<I> {
#[inline(always)]
pub fn write(&mut self, value: I::Value) {
self.inner.write(value)

28
third_party/rust/redox_syscall/src/io/mmio.rs поставляемый
Просмотреть файл

@ -1,19 +1,33 @@
use core::ptr::{read_volatile, write_volatile};
use core::mem::uninitialized;
use core::ptr::{read_volatile, write_volatile, addr_of, addr_of_mut};
use core::mem::MaybeUninit;
use core::ops::{BitAnd, BitOr, Not};
use super::io::Io;
#[repr(packed)]
pub struct Mmio<T> {
value: T,
value: MaybeUninit<T>,
}
impl<T> Mmio<T> {
/// Create a new Mmio without initializing
#[deprecated = "unsound because it's possible to read even though it's uninitialized"]
pub fn new() -> Self {
Mmio {
value: unsafe { uninitialized() }
unsafe { Self::uninit() }
}
pub unsafe fn zeroed() -> Self {
Self {
value: MaybeUninit::zeroed(),
}
}
pub unsafe fn uninit() -> Self {
Self {
value: MaybeUninit::uninit(),
}
}
pub const fn from(value: T) -> Self {
Self {
value: MaybeUninit::new(value),
}
}
}
@ -22,10 +36,10 @@ impl<T> Io for Mmio<T> where T: Copy + PartialEq + BitAnd<Output = T> + BitOr<Ou
type Value = T;
fn read(&self) -> T {
unsafe { read_volatile(&self.value) }
unsafe { read_volatile(addr_of!(self.value).cast::<T>()) }
}
fn write(&mut self, value: T) {
unsafe { write_volatile(&mut self.value, value) };
unsafe { write_volatile(addr_of_mut!(self.value).cast::<T>(), value) };
}
}

Просмотреть файл

@ -3,9 +3,13 @@
pub use self::dma::*;
pub use self::io::*;
pub use self::mmio::*;
#[cfg(target_arch = "x86_64")]
pub use self::pio::*;
mod dma;
mod io;
mod mmio;
#[cfg(target_arch = "x86_64")]
mod pio;

15
third_party/rust/redox_syscall/src/io/pio.rs поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
use core::arch::asm;
use core::marker::PhantomData;
use super::io::Io;
@ -13,7 +14,7 @@ impl<T> Pio<T> {
/// Create a PIO from a given port
pub const fn new(port: u16) -> Self {
Pio::<T> {
port: port,
port,
value: PhantomData,
}
}
@ -28,7 +29,7 @@ impl Io for Pio<u8> {
fn read(&self) -> u8 {
let value: u8;
unsafe {
llvm_asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("in al, dx", in("dx") self.port, out("al") value, options(nostack, nomem, preserves_flags));
}
value
}
@ -37,7 +38,7 @@ impl Io for Pio<u8> {
#[inline(always)]
fn write(&mut self, value: u8) {
unsafe {
llvm_asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("out dx, al", in("dx") self.port, in("al") value, options(nostack, nomem, preserves_flags));
}
}
}
@ -51,7 +52,7 @@ impl Io for Pio<u16> {
fn read(&self) -> u16 {
let value: u16;
unsafe {
llvm_asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("in ax, dx", in("dx") self.port, out("ax") value, options(nostack, nomem, preserves_flags));
}
value
}
@ -60,7 +61,7 @@ impl Io for Pio<u16> {
#[inline(always)]
fn write(&mut self, value: u16) {
unsafe {
llvm_asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("out dx, ax", in("dx") self.port, in("ax") value, options(nostack, nomem, preserves_flags));
}
}
}
@ -74,7 +75,7 @@ impl Io for Pio<u32> {
fn read(&self) -> u32 {
let value: u32;
unsafe {
llvm_asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("in eax, dx", in("dx") self.port, out("eax") value, options(nostack, nomem, preserves_flags));
}
value
}
@ -83,7 +84,7 @@ impl Io for Pio<u32> {
#[inline(always)]
fn write(&mut self, value: u32) {
unsafe {
llvm_asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile");
asm!("out dx, eax", in("dx") self.port, in("eax") value, options(nostack, nomem, preserves_flags));
}
}
}

24
third_party/rust/redox_syscall/src/lib.rs поставляемый
Просмотреть файл

@ -1,5 +1,3 @@
#![feature(llvm_asm)]
#![feature(const_fn)]
#![cfg_attr(not(test), no_std)]
#[cfg(test)]
@ -7,6 +5,7 @@ extern crate core;
pub use self::arch::*;
pub use self::call::*;
pub use self::daemon::*;
pub use self::data::*;
pub use self::error::*;
pub use self::flag::*;
@ -14,23 +13,27 @@ pub use self::io::*;
pub use self::number::*;
pub use self::scheme::*;
#[cfg(all(target_os = "redox", target_arch = "arm"))]
#[path="arch/arm.rs"]
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "arm"))]
#[path="arch/nonredox.rs"]
mod arch;
#[cfg(all(target_os = "redox", target_arch = "aarch64"))]
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "aarch64"))]
#[path="arch/aarch64.rs"]
mod arch;
#[cfg(all(target_os = "redox", target_arch = "x86"))]
#[path="arch/x86.rs"]
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "riscv64"))]
#[path="arch/riscv64.rs"]
mod arch;
#[cfg(all(target_os = "redox", target_arch = "x86_64"))]
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "x86"))]
#[path="arch/nonredox.rs"]
mod arch;
#[cfg(all(any(target_os = "none", target_os = "redox"), target_arch = "x86_64"))]
#[path="arch/x86_64.rs"]
mod arch;
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "none", target_os = "redox")))]
#[path="arch/nonredox.rs"]
mod arch;
@ -40,6 +43,9 @@ pub mod call;
/// Complex structures that are used for some system calls
pub mod data;
/// Wrapper to make daemons easier to write
pub mod daemon;
/// All errors that can be generated by a system call
pub mod error;

44
third_party/rust/redox_syscall/src/number.rs поставляемый
Просмотреть файл

@ -16,28 +16,29 @@ pub const SYS_CHMOD: usize = SYS_CLASS_PATH | 15;
pub const SYS_RMDIR: usize = SYS_CLASS_PATH | 84;
pub const SYS_UNLINK: usize = SYS_CLASS_PATH | 10;
pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6;
pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41;
pub const SYS_DUP2: usize = SYS_CLASS_FILE | SYS_RET_FILE | 63;
pub const SYS_READ: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
pub const SYS_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
pub const SYS_LSEEK: usize = SYS_CLASS_FILE | 19;
pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94;
pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207;
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11;
pub const SYS_FMAP: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 90;
pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91;
pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
pub const SYS_FRENAME: usize = SYS_CLASS_FILE | SYS_ARG_PATH | 38;
pub const SYS_FSTAT: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
pub const SYS_FSYNC: usize = SYS_CLASS_FILE | 118;
pub const SYS_FTRUNCATE: usize =SYS_CLASS_FILE | 93;
pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320;
pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6;
pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41;
pub const SYS_DUP2: usize = SYS_CLASS_FILE | SYS_RET_FILE | 63;
pub const SYS_READ: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
pub const SYS_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
pub const SYS_LSEEK: usize = SYS_CLASS_FILE | 19;
pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94;
pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207;
pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55;
pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927;
pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11;
pub const SYS_FMAP_OLD: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 90;
pub const SYS_FMAP: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 900;
pub const SYS_FUNMAP_OLD: usize = SYS_CLASS_FILE | 91;
pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 92;
pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
pub const SYS_FRENAME: usize = SYS_CLASS_FILE | SYS_ARG_PATH | 38;
pub const SYS_FSTAT: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
pub const SYS_FSYNC: usize = SYS_CLASS_FILE | 118;
pub const SYS_FTRUNCATE: usize = SYS_CLASS_FILE | 93;
pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320;
pub const SYS_BRK: usize = 45;
pub const SYS_CHDIR: usize = 12;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const SYS_CLONE: usize = 120;
@ -59,6 +60,7 @@ pub const SYS_MPROTECT: usize = 125;
pub const SYS_MKNS: usize = 984;
pub const SYS_NANOSLEEP: usize =162;
pub const SYS_PHYSALLOC: usize =945;
pub const SYS_PHYSALLOC3: usize=9453;
pub const SYS_PHYSFREE: usize = 946;
pub const SYS_PHYSMAP: usize = 947;
pub const SYS_PHYSUNMAP: usize =948;

Просмотреть файл

@ -11,7 +11,10 @@ echo "Generating SchemeBlock from Scheme"
sed 's/trait Scheme/trait SchemeBlock/' scheme.rs \
| sed 's/fn handle(\&self, packet: \&mut Packet)/fn handle(\&self, packet: \&Packet) -> Option<usize>/' \
| sed 's/packet.a = Error::mux(res);/res.transpose().map(Error::mux)/' \
| sed 's/Result<usize>/Result<Option<usize>>/g' \
| sed 's/\.map(|f| f\.bits())/\.map(|f| f.map(|f| f.bits()))/' \
| sed 's/\.map(|o| o as usize)/.map(|o| o.map(|o| o as usize))/' \
| sed 's/Ok(0)/Ok(Some(0))/g' \
| sed 's/Result<\([^>]\+\)>/Result<Option<\1>>/g' \
> scheme_block.rs
echo "Generating SchemeBlockMut from SchemeBlock"

Просмотреть файл

@ -1,9 +1,18 @@
use core::{slice, str};
pub use self::scheme::Scheme;
pub use self::scheme_mut::SchemeMut;
pub use self::scheme_block::SchemeBlock;
pub use self::scheme_block_mut::SchemeBlockMut;
pub use self::seek::*;
unsafe fn str_from_raw_parts(ptr: *const u8, len: usize) -> Option<&'static str> {
let slice = slice::from_raw_parts(ptr, len);
str::from_utf8(slice).ok()
}
mod scheme;
mod scheme_mut;
mod scheme_block;
mod scheme_block_mut;
mod seek;

Просмотреть файл

@ -1,33 +1,61 @@
use core::{mem, slice};
use data::*;
use error::*;
use number::*;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::str_from_raw_parts;
pub trait Scheme {
fn handle(&self, packet: &mut Packet) {
let res = match packet.a {
SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid),
SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid),
SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_OPEN => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.open(path, packet.d, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_CHMOD => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.chmod(path, packet.d as u16, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_RMDIR => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_UNLINK => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
SYS_LSEEK => self.seek(packet.b, packet.c as isize, packet.d).map(|o| o as usize),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self.fevent(packet.b, packet.c),
SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.bits()),
SYS_FMAP_OLD => if packet.d >= mem::size_of::<OldMap>() {
self.fmap_old(packet.b, unsafe { &*(packet.c as *const OldMap) })
} else {
Err(Error::new(EFAULT))
},
SYS_FMAP => if packet.d >= mem::size_of::<Map>() {
self.fmap(packet.b, unsafe { &*(packet.c as *const Map) })
} else {
Err(Error::new(EFAULT))
},
SYS_FUNMAP => self.funmap(packet.b),
SYS_FUNMAP_OLD => self.funmap_old(packet.b),
SYS_FUNMAP => self.funmap(packet.b, packet.c),
SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_FRENAME => self.frename(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }, packet.uid, packet.gid),
SYS_FRENAME => if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_FSTAT => if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
@ -55,22 +83,22 @@ pub trait Scheme {
/* Scheme operations */
#[allow(unused_variables)]
fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result<usize> {
fn chmod(&self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&self, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn rmdir(&self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&self, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn unlink(&self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
@ -91,7 +119,7 @@ pub trait Scheme {
}
#[allow(unused_variables)]
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
Err(Error::new(EBADF))
}
@ -111,18 +139,34 @@ pub trait Scheme {
}
#[allow(unused_variables)]
fn fevent(&self, id: usize, flags: usize) -> Result<usize> {
fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap_old(&self, id: usize, map: &OldMap) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap(&self, id: usize, map: &Map) -> Result<usize> {
Err(Error::new(EBADF))
if map.flags.contains(MapFlags::MAP_FIXED) {
return Err(Error::new(EINVAL));
}
self.fmap_old(id, &OldMap {
offset: map.offset,
size: map.size,
flags: map.flags,
})
}
#[allow(unused_variables)]
fn funmap(&self, address: usize) -> Result<usize> {
Err(Error::new(EBADF))
fn funmap_old(&self, address: usize) -> Result<usize> {
Ok(0)
}
#[allow(unused_variables)]
fn funmap(&self, address: usize, length: usize) -> Result<usize> {
Ok(0)
}
#[allow(unused_variables)]
@ -131,7 +175,7 @@ pub trait Scheme {
}
#[allow(unused_variables)]
fn frename(&self, id: usize, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn frename(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}

Просмотреть файл

@ -1,33 +1,61 @@
use core::{mem, slice};
use data::*;
use error::*;
use number::*;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::str_from_raw_parts;
pub trait SchemeBlock {
fn handle(&self, packet: &Packet) -> Option<usize> {
let res = match packet.a {
SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid),
SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid),
SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_OPEN => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.open(path, packet.d, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_CHMOD => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.chmod(path, packet.d as u16, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_RMDIR => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_UNLINK => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
SYS_LSEEK => self.seek(packet.b, packet.c as isize, packet.d).map(|o| o.map(|o| o as usize)),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self.fevent(packet.b, packet.c),
SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.map(|f| f.bits())),
SYS_FMAP_OLD => if packet.d >= mem::size_of::<OldMap>() {
self.fmap_old(packet.b, unsafe { &*(packet.c as *const OldMap) })
} else {
Err(Error::new(EFAULT))
},
SYS_FMAP => if packet.d >= mem::size_of::<Map>() {
self.fmap(packet.b, unsafe { &*(packet.c as *const Map) })
} else {
Err(Error::new(EFAULT))
},
SYS_FUNMAP => self.funmap(packet.b),
SYS_FUNMAP_OLD => self.funmap_old(packet.b),
SYS_FUNMAP => self.funmap(packet.b, packet.c),
SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_FRENAME => self.frename(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }, packet.uid, packet.gid),
SYS_FRENAME => if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_FSTAT => if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
@ -55,22 +83,22 @@ pub trait SchemeBlock {
/* Scheme operations */
#[allow(unused_variables)]
fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
fn open(&self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
fn chmod(&self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&self, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn rmdir(&self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&self, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn unlink(&self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
@ -91,7 +119,7 @@ pub trait SchemeBlock {
}
#[allow(unused_variables)]
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<Option<usize>> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
Err(Error::new(EBADF))
}
@ -111,18 +139,34 @@ pub trait SchemeBlock {
}
#[allow(unused_variables)]
fn fevent(&self, id: usize, flags: usize) -> Result<Option<usize>> {
fn fevent(&self, id: usize, flags: EventFlags) -> Result<Option<EventFlags>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap_old(&self, id: usize, map: &OldMap) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap(&self, id: usize, map: &Map) -> Result<Option<usize>> {
Err(Error::new(EBADF))
if map.flags.contains(MapFlags::MAP_FIXED) {
return Err(Error::new(EINVAL));
}
self.fmap_old(id, &OldMap {
offset: map.offset,
size: map.size,
flags: map.flags,
})
}
#[allow(unused_variables)]
fn funmap(&self, address: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
fn funmap_old(&self, address: usize) -> Result<Option<usize>> {
Ok(Some(0))
}
#[allow(unused_variables)]
fn funmap(&self, address: usize, length: usize) -> Result<Option<usize>> {
Ok(Some(0))
}
#[allow(unused_variables)]
@ -131,7 +175,7 @@ pub trait SchemeBlock {
}
#[allow(unused_variables)]
fn frename(&self, id: usize, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn frename(&self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}

Просмотреть файл

@ -1,33 +1,61 @@
use core::{mem, slice};
use data::*;
use error::*;
use number::*;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::str_from_raw_parts;
pub trait SchemeBlockMut {
fn handle(&mut self, packet: &Packet) -> Option<usize> {
let res = match packet.a {
SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid),
SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid),
SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_OPEN => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.open(path, packet.d, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_CHMOD => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.chmod(path, packet.d as u16, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_RMDIR => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_UNLINK => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
SYS_LSEEK => self.seek(packet.b, packet.c as isize, packet.d).map(|o| o.map(|o| o as usize)),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self.fevent(packet.b, packet.c),
SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.map(|f| f.bits())),
SYS_FMAP_OLD => if packet.d >= mem::size_of::<OldMap>() {
self.fmap_old(packet.b, unsafe { &*(packet.c as *const OldMap) })
} else {
Err(Error::new(EFAULT))
},
SYS_FMAP => if packet.d >= mem::size_of::<Map>() {
self.fmap(packet.b, unsafe { &*(packet.c as *const Map) })
} else {
Err(Error::new(EFAULT))
},
SYS_FUNMAP => self.funmap(packet.b),
SYS_FUNMAP_OLD => self.funmap_old(packet.b),
SYS_FUNMAP => self.funmap(packet.b, packet.c),
SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_FRENAME => self.frename(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }, packet.uid, packet.gid),
SYS_FRENAME => if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_FSTAT => if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
@ -55,22 +83,22 @@ pub trait SchemeBlockMut {
/* Scheme operations */
#[allow(unused_variables)]
fn open(&mut self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn chmod(&mut self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
fn chmod(&mut self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&mut self, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn rmdir(&mut self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&mut self, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn unlink(&mut self, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(ENOENT))
}
@ -91,7 +119,7 @@ pub trait SchemeBlockMut {
}
#[allow(unused_variables)]
fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<Option<usize>> {
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
Err(Error::new(EBADF))
}
@ -111,18 +139,34 @@ pub trait SchemeBlockMut {
}
#[allow(unused_variables)]
fn fevent(&mut self, id: usize, flags: usize) -> Result<Option<usize>> {
fn fevent(&mut self, id: usize, flags: EventFlags) -> Result<Option<EventFlags>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap_old(&mut self, id: usize, map: &OldMap) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap(&mut self, id: usize, map: &Map) -> Result<Option<usize>> {
Err(Error::new(EBADF))
if map.flags.contains(MapFlags::MAP_FIXED) {
return Err(Error::new(EINVAL));
}
self.fmap_old(id, &OldMap {
offset: map.offset,
size: map.size,
flags: map.flags,
})
}
#[allow(unused_variables)]
fn funmap(&mut self, address: usize) -> Result<Option<usize>> {
Err(Error::new(EBADF))
fn funmap_old(&mut self, address: usize) -> Result<Option<usize>> {
Ok(Some(0))
}
#[allow(unused_variables)]
fn funmap(&mut self, address: usize, length: usize) -> Result<Option<usize>> {
Ok(Some(0))
}
#[allow(unused_variables)]
@ -131,7 +175,7 @@ pub trait SchemeBlockMut {
}
#[allow(unused_variables)]
fn frename(&mut self, id: usize, path: &[u8], uid: u32, gid: u32) -> Result<Option<usize>> {
fn frename(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<Option<usize>> {
Err(Error::new(EBADF))
}

Просмотреть файл

@ -1,33 +1,61 @@
use core::{mem, slice};
use data::*;
use error::*;
use number::*;
use crate::data::*;
use crate::error::*;
use crate::flag::*;
use crate::number::*;
use crate::scheme::str_from_raw_parts;
pub trait SchemeMut {
fn handle(&mut self, packet: &mut Packet) {
let res = match packet.a {
SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid),
SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid),
SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
SYS_OPEN => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.open(path, packet.d, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_CHMOD => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.chmod(path, packet.d as u16, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_RMDIR => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.rmdir(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_UNLINK => if let Some(path) = unsafe { str_from_raw_parts(packet.b as *const u8, packet.c) } {
self.unlink(path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
SYS_LSEEK => self.seek(packet.b, packet.c as isize, packet.d).map(|o| o as usize),
SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16),
SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32),
SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d),
SYS_FEVENT => self.fevent(packet.b, packet.c),
SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.bits()),
SYS_FMAP_OLD => if packet.d >= mem::size_of::<OldMap>() {
self.fmap_old(packet.b, unsafe { &*(packet.c as *const OldMap) })
} else {
Err(Error::new(EFAULT))
},
SYS_FMAP => if packet.d >= mem::size_of::<Map>() {
self.fmap(packet.b, unsafe { &*(packet.c as *const Map) })
} else {
Err(Error::new(EFAULT))
},
SYS_FUNMAP => self.funmap(packet.b),
SYS_FUNMAP_OLD => self.funmap_old(packet.b),
SYS_FUNMAP => self.funmap(packet.b, packet.c),
SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
SYS_FRENAME => self.frename(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }, packet.uid, packet.gid),
SYS_FRENAME => if let Some(path) = unsafe { str_from_raw_parts(packet.c as *const u8, packet.d) } {
self.frename(packet.b, path, packet.uid, packet.gid)
} else {
Err(Error::new(EINVAL))
},
SYS_FSTAT => if packet.d >= mem::size_of::<Stat>() {
self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) })
} else {
@ -55,22 +83,22 @@ pub trait SchemeMut {
/* Scheme operations */
#[allow(unused_variables)]
fn open(&mut self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
fn open(&mut self, path: &str, flags: usize, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn chmod(&mut self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result<usize> {
fn chmod(&mut self, path: &str, mode: u16, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn rmdir(&mut self, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn rmdir(&mut self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
#[allow(unused_variables)]
fn unlink(&mut self, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn unlink(&mut self, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(ENOENT))
}
@ -91,7 +119,7 @@ pub trait SchemeMut {
}
#[allow(unused_variables)]
fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<isize> {
Err(Error::new(EBADF))
}
@ -111,18 +139,34 @@ pub trait SchemeMut {
}
#[allow(unused_variables)]
fn fevent(&mut self, id: usize, flags: usize) -> Result<usize> {
fn fevent(&mut self, id: usize, flags: EventFlags) -> Result<EventFlags> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap_old(&mut self, id: usize, map: &OldMap) -> Result<usize> {
Err(Error::new(EBADF))
}
#[allow(unused_variables)]
fn fmap(&mut self, id: usize, map: &Map) -> Result<usize> {
Err(Error::new(EBADF))
if map.flags.contains(MapFlags::MAP_FIXED) {
return Err(Error::new(EINVAL));
}
self.fmap_old(id, &OldMap {
offset: map.offset,
size: map.size,
flags: map.flags,
})
}
#[allow(unused_variables)]
fn funmap(&mut self, address: usize) -> Result<usize> {
Err(Error::new(EBADF))
fn funmap_old(&mut self, address: usize) -> Result<usize> {
Ok(0)
}
#[allow(unused_variables)]
fn funmap(&mut self, address: usize, length: usize) -> Result<usize> {
Ok(0)
}
#[allow(unused_variables)]
@ -131,7 +175,7 @@ pub trait SchemeMut {
}
#[allow(unused_variables)]
fn frename(&mut self, id: usize, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
fn frename(&mut self, id: usize, path: &str, uid: u32, gid: u32) -> Result<usize> {
Err(Error::new(EBADF))
}

33
third_party/rust/redox_syscall/src/scheme/seek.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
use core::cmp;
use core::convert::TryFrom;
use crate::error::*;
use crate::flag::*;
/// Helper for seek calls
/// In most cases it's easier to use a usize to track the offset and buffer size internally,
/// but the seek interface uses isize. This wrapper ensures EOVERFLOW errors are returned
/// as appropriate if the value in the usize can't fit in the isize.
pub fn calc_seek_offset_usize(cur_offset: usize, pos: isize, whence: usize, buf_len: usize) -> Result<isize> {
let cur_offset = isize::try_from(cur_offset).or_else(|_| Err(Error::new(EOVERFLOW)))?;
let buf_len = isize::try_from(buf_len).or_else(|_| Err(Error::new(EOVERFLOW)))?;
calc_seek_offset_isize(cur_offset, pos, whence, buf_len)
}
/// Helper for seek calls
/// Result is guaranteed to be positive.
/// EOVERFLOW returned if the arguments would cause an overflow.
/// EINVAL returned if the new offset is out of bounds.
pub fn calc_seek_offset_isize(cur_offset: isize, pos: isize, whence: usize, buf_len: isize) -> Result<isize> {
let new_offset = match whence {
SEEK_CUR => pos.checked_add(cur_offset),
SEEK_END => pos.checked_add(buf_len),
SEEK_SET => Some(pos),
_ => None,
};
match new_offset {
Some(new_offset) if new_offset < 0 => Err(Error::new(EINVAL)),
Some(new_offset) => Ok(cmp::min(new_offset, buf_len)),
None => Err(Error::new(EOVERFLOW))
}
}

381
third_party/rust/redox_syscall/src/tests.rs поставляемый
Просмотреть файл

@ -1,17 +1,25 @@
#[test]
fn brk() {
unsafe {
let start = dbg!(crate::brk(0)).unwrap();
let end = start + 4 * 1024 * 1024;
assert_eq!(dbg!(crate::brk(end)), Ok(end));
}
}
#[test]
fn chdir() {
//TODO: Verify CWD
assert_eq!(dbg!(crate::chdir("file:/")), Ok(0));
assert_eq!(dbg!(crate::chdir("file:/root")), Ok(0));
use std::str;
let mut current_buf = [0; 4096];
let current_count = dbg!(crate::getcwd(&mut current_buf)).unwrap();
let current = dbg!(str::from_utf8(&current_buf[..current_count])).unwrap();
let new = "file:";
assert_eq!(dbg!(crate::chdir(dbg!(new))), Ok(0));
{
let mut buf = [0; 4096];
let count = dbg!(crate::getcwd(&mut buf)).unwrap();
assert_eq!(dbg!(str::from_utf8(&buf[..count])), Ok(new));
}
assert_eq!(dbg!(crate::chdir(current)), Ok(0));
{
let mut buf = [0; 4096];
let count = dbg!(crate::getcwd(&mut buf)).unwrap();
assert_eq!(dbg!(str::from_utf8(&buf[..count])), Ok(current));
}
}
//TODO: chmod
@ -19,14 +27,14 @@ fn chdir() {
#[test]
fn clone() {
let expected_status = 42;
let pid_res = unsafe { crate::clone(0) };
let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) };
if pid_res == Ok(0) {
crate::exit(expected_status).unwrap();
panic!("failed to exit");
} else {
let pid = dbg!(pid_res).unwrap();
let mut status = 0;
assert_eq!(dbg!(crate::waitpid(pid, &mut status, 0)), Ok(pid));
assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid));
assert_eq!(dbg!(crate::wifexited(status)), true);
assert_eq!(dbg!(crate::wexitstatus(status)), expected_status);
}
@ -61,7 +69,7 @@ fn clock_gettime() {
#[test]
fn fexec() {
let name = "/bin/ls";
let name = "file:/bin/ls";
let fd = dbg!(
crate::open(name, crate::O_RDONLY | crate::O_CLOEXEC)
@ -73,7 +81,7 @@ fn fexec() {
let vars = &[];
let pid_res = unsafe { crate::clone(0) };
let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) };
if pid_res == Ok(0) {
crate::fexec(fd, args, vars).unwrap();
panic!("failed to fexec");
@ -82,7 +90,7 @@ fn fexec() {
let pid = dbg!(pid_res).unwrap();
let mut status = 0;
assert_eq!(dbg!(crate::waitpid(pid, &mut status, 0)), Ok(pid));
assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid));
assert_eq!(dbg!(crate::wifexited(status)), true);
assert_eq!(dbg!(crate::wexitstatus(status)), 0);
}
@ -94,17 +102,20 @@ fn fmap() {
let fd = dbg!(
crate::open(
"/tmp/syscall-tests-fmap",
"file:/tmp/syscall-tests-fmap",
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let size = 128;
let map = unsafe {
slice::from_raw_parts_mut(
dbg!(
crate::fmap(fd, &crate::Map {
address: 0,
offset: 0,
size: 128,
size,
flags: crate::PROT_READ | crate::PROT_WRITE
})
).unwrap() as *mut u8,
@ -123,7 +134,337 @@ fn fmap() {
//TODO: add msync
unsafe {
assert_eq!(dbg!(
crate::funmap(map.as_mut_ptr() as usize)
crate::funmap(map.as_mut_ptr() as usize, size)
), Ok(0));
}
}
// funmap tested by fmap
#[test]
fn fpath() {
use std::str;
let path = "file:/tmp/syscall-tests-fpath";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut buf = [0; 4096];
let count = dbg!(
crate::fpath(fd, &mut buf)
).unwrap();
assert_eq!(dbg!(str::from_utf8(&buf[..count])), Ok(path));
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: frename
#[test]
fn fstat() {
let path = "file:/tmp/syscall-tests-fstat";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut stat = crate::Stat::default();
assert_eq!(dbg!(crate::fstat(fd, &mut stat)), Ok(0));
assert_ne!(dbg!(stat), crate::Stat::default());
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
#[test]
fn fstatvfs() {
let path = "file:/tmp/syscall-tests-fstatvfs";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
let mut statvfs = crate::StatVfs::default();
assert_eq!(dbg!(crate::fstatvfs(fd, &mut statvfs)), Ok(0));
assert_ne!(dbg!(statvfs), crate::StatVfs::default());
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: fsync
//TODO: ftruncate
//TODO: futimens
//TODO: futex
// getcwd tested by chdir
#[test]
fn getegid() {
assert_eq!(crate::getegid(), Ok(0));
}
#[test]
fn getens() {
assert_eq!(crate::getens(), Ok(1));
}
#[test]
fn geteuid() {
assert_eq!(crate::geteuid(), Ok(0));
}
#[test]
fn getgid() {
assert_eq!(crate::getgid(), Ok(0));
}
#[test]
fn getns() {
assert_eq!(crate::getns(), Ok(1));
}
//TODO: getpid
//TODO: getpgid
//TODO: getppid
#[test]
fn getuid() {
assert_eq!(crate::getuid(), Ok(0));
}
//TODO: iopl
//TODO: kill
//TODO: link (probably will not work)
#[test]
fn lseek() {
let path = "file:/tmp/syscall-tests-lseek";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
{
let mut buf = [0; 256];
for i in 0..buf.len() {
buf[i] = i as u8;
}
assert_eq!(dbg!(crate::write(fd, &buf)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_CUR)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_END)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
}
{
let mut buf = [0; 256];
assert_eq!(dbg!(crate::read(fd, &mut buf)), Ok(buf.len()));
for i in 0..buf.len() {
assert_eq!(buf[i], i as u8);
}
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_CUR)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_END)), Ok(buf.len()));
assert_eq!(dbg!(crate::lseek(fd, 0, crate::SEEK_SET)), Ok(0));
}
assert_eq!(dbg!(crate::close(fd)), Ok(0));
}
//TODO: mkns
//TODO: mprotect
#[test]
fn nanosleep() {
let req = crate::TimeSpec {
tv_sec: 0,
tv_nsec: 0,
};
let mut rem = crate::TimeSpec::default();
assert_eq!(crate::nanosleep(&req, &mut rem), Ok(0));
assert_eq!(rem, crate::TimeSpec::default());
}
//TODO: open
//TODO: physalloc
//TODO: physfree
//TODO: physmap
//TODO: physunmap
#[test]
fn pipe2() {
let mut fds = [0, 0];
assert_eq!(dbg!(crate::pipe2(&mut fds, crate::O_CLOEXEC)), Ok(0));
assert_ne!(dbg!(fds), [0, 0]);
{
let mut buf = [0; 256];
for i in 0..buf.len() {
buf[i] = i as u8;
}
assert_eq!(dbg!(crate::write(fds[1], &buf)), Ok(buf.len()));
}
{
let mut buf = [0; 256];
assert_eq!(dbg!(crate::read(fds[0], &mut buf)), Ok(buf.len()));
for i in 0..buf.len() {
assert_eq!(buf[i], i as u8);
}
}
assert_eq!(dbg!(crate::close(fds[0])), Ok(0));
assert_eq!(dbg!(crate::close(fds[1])), Ok(0));
}
//TODO: read
#[test]
fn rmdir() {
let path = "file:/tmp/syscall-tests-rmdir";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_DIRECTORY | crate::O_CLOEXEC
)
).unwrap();
assert_eq!(dbg!(crate::close(fd)), Ok(0));
assert_eq!(dbg!(crate::rmdir(path)), Ok(0));
}
//TODO: setpgid
//TODO: setregid
//TODO: setrens
//TODO: setreuid
//TODO: sigaction
//TODO: sigprocmask
//TODO: sigreturn
#[test]
fn umask() {
let old = dbg!(crate::umask(0o244)).unwrap();
assert_eq!(dbg!(crate::umask(old)), Ok(0o244));
}
#[test]
fn unlink() {
let path = "file:/tmp/syscall-tests-unlink";
let fd = dbg!(
crate::open(
dbg!(path),
crate::O_CREAT | crate::O_RDWR | crate::O_CLOEXEC
)
).unwrap();
assert_eq!(dbg!(crate::close(fd)), Ok(0));
assert_eq!(dbg!(crate::unlink(path)), Ok(0));
}
//TODO: virttophys
// waitpid tested by clone
//TODO: write
#[test]
fn sched_yield() {
assert_eq!(dbg!(crate::sched_yield()), Ok(0));
}
#[test]
fn sigaction() {
use std::{
mem,
sync::atomic::{AtomicBool, Ordering}
};
static SA_HANDLER_WAS_RAN: AtomicBool = AtomicBool::new(false);
static SA_HANDLER_2_WAS_IGNORED: AtomicBool = AtomicBool::new(false);
let child = unsafe { crate::clone(crate::CLONE_VM).unwrap() };
if child == 0 {
let pid = crate::getpid().unwrap();
extern "C" fn hello_im_a_signal_handler(signal: usize) {
assert_eq!(signal, crate::SIGUSR1);
SA_HANDLER_WAS_RAN.store(true, Ordering::SeqCst);
}
let my_signal_handler = crate::SigAction {
sa_handler: Some(hello_im_a_signal_handler),
..Default::default()
};
crate::sigaction(crate::SIGUSR1, Some(&my_signal_handler), None).unwrap();
crate::kill(pid, crate::SIGUSR1).unwrap(); // calls handler
let mut old_signal_handler = crate::SigAction::default();
crate::sigaction(
crate::SIGUSR1,
Some(&crate::SigAction {
sa_handler: unsafe { mem::transmute::<usize, Option<extern "C" fn(usize)>>(crate::SIG_IGN) },
..Default::default()
}),
Some(&mut old_signal_handler)
).unwrap();
assert_eq!(my_signal_handler, old_signal_handler);
crate::kill(pid, crate::SIGUSR1).unwrap(); // does nothing
SA_HANDLER_2_WAS_IGNORED.store(true, Ordering::SeqCst);
crate::sigaction(
crate::SIGUSR1,
Some(&crate::SigAction {
sa_handler: unsafe { mem::transmute::<usize, Option<extern "C" fn(usize)>>(crate::SIG_DFL) },
..Default::default()
}),
Some(&mut old_signal_handler)
).unwrap();
crate::kill(pid, crate::SIGUSR1).unwrap(); // actually exits
} else {
let mut status = 0;
dbg!(crate::waitpid(child, &mut status, crate::WaitFlags::empty())).unwrap();
assert!(crate::wifsignaled(status));
assert_eq!(crate::wtermsig(status), crate::SIGUSR1);
assert!(SA_HANDLER_WAS_RAN.load(Ordering::SeqCst));
assert!(SA_HANDLER_2_WAS_IGNORED.load(Ordering::SeqCst));
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"526cfadda74195985a5d860855ef4d8213661e9fcde075a2c128121aa7848003","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"e7da9558db65f61008aa9196066a18bcb16b4c7c4369766a67ea7ec9d52b632d","README.md":"2388f555712995933c80721d9de80fc9fe3428dd61609cc01cd26079bd543468","src/dir.rs":"50501bbbe44046d3f74c2fa1d590405cc898d5d52643f18f28964b7a82eafb80","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"bec50fb99c14cb4a49402bdbb7c5e6b5b8ff785b06b6fcb13267f35df8f3c8c2","src/file/imp/other.rs":"99c8f9f3251199fc31e7b88810134712e5725fb6fa14648696ed5cbea980fc5b","src/file/imp/unix.rs":"afc860978e362b1266b40722181fc3a509af72ce942a1b2dcd38ef1776897af3","src/file/imp/windows.rs":"03d81d71c404f0d448e1162825d6fbd57a78b4af8d4dc5287ec2e7c5a873d7cc","src/file/mod.rs":"ae7246a5c1445afa89765097742c11383ae996ea7046e8903f2dcbdb197bce53","src/lib.rs":"fb0c982c8dd2c6d0211c7d4542fa1c724d9ca45a8828ff5aeae866f4aa9d1507","src/spooled.rs":"34f5305923de710c58228d68c143133a11843e7ad5029ee31448ab4ab6172b74","src/util.rs":"25c62fb5d87411fd9508596db69ea489e9026b9ad0ffc9996db1ac8670b3da02","tests/namedtempfile.rs":"07ad89e54c9ce79d6b85d37d367d9687ec6f2cabc6cc44cdefd42731056afd6a","tests/spooled.rs":"29e797d486d867cb6ac46d4cf126eb5868a069a4070c3f50ffa02fbb0b887934","tests/tempdir.rs":"771d555d4eaa410207d212eb3744e016e0b5a22f1f1b7199636a4fac5daaf952","tests/tempfile.rs":"a1dacfd9b1ee3c40fdde5131b33995f3cfd62a212455c8664a98c735b9954ee6"},"package":"7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"}
{"files":{"Cargo.toml":"685243e302f6e014de9c8e9b95596e5f63c7bf7fde42e8e66a41a6bc7fd5e803","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"8b427f5bc501764575e52ba4f9d95673cf8f6d80a86d0d06599852e1a9a20a36","NEWS":"4255c86ac140a4d08423cd05cbd0aa42ff796bb4b38579dd19cde289ee3baecd","README.md":"db6717cbd0b3cbbce5f3cdb8a80d8f2d90b1be251b4c1c647557ae0f78ec9748","src/dir.rs":"4499ff439b740f8d2f01458664e2bf72bbfdd1206226780c6a91fb309ef15707","src/error.rs":"cc7d8eace0fff11cb342158d2885d5637bfb14b24ef30755e808554772039c5f","src/file/imp/mod.rs":"f6da9fcd93f11889670a251fdd8231b5f4614e5a971b7b183f52b44af68568d5","src/file/imp/other.rs":"99c8f9f3251199fc31e7b88810134712e5725fb6fa14648696ed5cbea980fc5b","src/file/imp/unix.rs":"cf8eeceecfddc37c9eaf95a1ebe088314dc468f07fe357961d80817eef619ca4","src/file/imp/windows.rs":"03d81d71c404f0d448e1162825d6fbd57a78b4af8d4dc5287ec2e7c5a873d7cc","src/file/mod.rs":"bda4ee3998106089a4c0ccbc8e46dc22b7d3aec427487fd4e414fb132b378736","src/lib.rs":"e2b0df7e17cc6680a5bb0829d0433f069c6bf9eede2007d21e3b01a595df41a8","src/spooled.rs":"51fa1d7639027234e257d343a5d3c95f2e47899ba6a24f0abec8d4d729eba6d6","src/util.rs":"2bd80ee69009e7e36b596d0105bb00184cff04e899e9fcce2e4cc21f23dda073","tests/namedtempfile.rs":"0031cb33ae6faf45be103869b4d98af63bef4040dc489b323212eb7a7ef72a9a","tests/spooled.rs":"29e797d486d867cb6ac46d4cf126eb5868a069a4070c3f50ffa02fbb0b887934","tests/tempdir.rs":"771d555d4eaa410207d212eb3744e016e0b5a22f1f1b7199636a4fac5daaf952","tests/tempfile.rs":"92078a1e20a39af77c1daa9a422345d20c41584dd2010b4829911c8741d1c628"},"package":"5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"}

28
third_party/rust/tempfile/Cargo.toml поставляемый
Просмотреть файл

@ -3,17 +3,16 @@
# 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 = "tempfile"
version = "3.1.0"
version = "3.3.0"
authors = ["Steven Allen <steven@stebalien.com>", "The Rust Project Developers", "Ashley Mannix <ashleymannix@live.com.au>", "Jason White <jasonaw0@gmail.com>"]
exclude = ["/.travis.yml", "/appveyor.yml"]
description = "A library for managing temporary files and directories."
@ -23,17 +22,22 @@ keywords = ["tempfile", "tmpfile", "filesystem"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/Stebalien/tempfile"
[dependencies.cfg-if]
version = "0.1"
version = "1"
[dependencies.rand]
version = "0.7"
[dependencies.fastrand]
version = "1.6.0"
[dependencies.remove_dir_all]
version = "0.5"
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
version = "0.1"
[target."cfg(unix)".dependencies.libc]
[dev-dependencies.doc-comment]
version = "0.3"
[features]
nightly = []
[target."cfg(any(unix, target_os = \"wasi\"))".dependencies.libc]
version = "0.2.27"
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
version = "0.2.9"
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
features = ["fileapi", "handleapi", "winbase"]

27
third_party/rust/tempfile/NEWS поставляемый
Просмотреть файл

@ -1,3 +1,30 @@
3.3.0
=====
Features:
* Replace rand with fastrand for a significantly smaller dependency tree. Cryptographic randomness
isn't necessary for temporary file names, and isn't all that helpful either.
* Add limited WASI support.
* Add a function to extract the inner data from a `SpooledTempFile`.
Bug Fixes:
* Make it possible to persist unnamed temporary files on linux by removing the `O_EXCL` flag.
* Fix redox minimum crate version.
3.2.0
=====
Features:
* Bump rand dependency to `0.8`.
* Bump cfg-if dependency to `1.0`
Other than that, this release mostly includes small cleanups and simplifications.
Breaking: The minimum rust version is now `1.40.0`.
3.1.0
=====

5
third_party/rust/tempfile/README.md поставляемый
Просмотреть файл

@ -2,8 +2,7 @@ tempfile
========
[![Crate](https://img.shields.io/crates/v/tempfile.svg)](https://crates.io/crates/tempfile)
[![Build Status](https://travis-ci.org/Stebalien/tempfile.svg?branch=master)](https://travis-ci.org/Stebalien/tempfile)
[![Build status](https://ci.appveyor.com/api/projects/status/5q00b8rvvg46i5tf/branch/master?svg=true)](https://ci.appveyor.com/project/Stebalien/tempfile/branch/master)
[![Build Status](https://github.com/Stebalien/tempfile/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Stebalien/tempfile/actions/workflows/ci.yml?query=branch%3Amaster)
A secure, cross-platform, temporary file library for Rust. In addition to creating
temporary files, this library also allows users to securely open multiple
@ -15,7 +14,7 @@ patterns and surprisingly difficult to implement securely).
Usage
-----
Minimum required Rust version: 1.32.0
Minimum required Rust version: 1.40.0
Add this to your `Cargo.toml`:
```toml

37
third_party/rust/tempfile/src/dir.rs поставляемый
Просмотреть файл

@ -9,6 +9,7 @@
// except according to those terms.
use remove_dir_all::remove_dir_all;
use std::mem;
use std::path::{self, Path, PathBuf};
use std::{fmt, fs, io};
@ -20,7 +21,7 @@ use crate::Builder;
/// The `tempdir` function creates a directory in the file system
/// and returns a [`TempDir`].
/// The directory will be automatically deleted when the `TempDir`s
/// desctructor is run.
/// destructor is run.
///
/// # Resource Leaking
///
@ -69,7 +70,7 @@ pub fn tempdir() -> io::Result<TempDir> {
/// The `tempdir` function creates a directory in the file system
/// and returns a [`TempDir`].
/// The directory will be automatically deleted when the `TempDir`s
/// desctructor is run.
/// destructor is run.
///
/// # Resource Leaking
///
@ -192,7 +193,7 @@ pub fn tempdir_in<P: AsRef<Path>>(dir: P) -> io::Result<TempDir> {
/// [`std::fs`]: http://doc.rust-lang.org/std/fs/index.html
/// [`std::process::exit()`]: http://doc.rust-lang.org/std/process/fn.exit.html
pub struct TempDir {
path: Option<PathBuf>,
path: Box<Path>,
}
impl TempDir {
@ -292,7 +293,7 @@ impl TempDir {
/// # }
/// ```
pub fn path(&self) -> &path::Path {
self.path.as_ref().unwrap()
self.path.as_ref()
}
/// Persist the temporary directory to disk, returning the [`PathBuf`] where it is located.
@ -322,11 +323,16 @@ impl TempDir {
/// # Ok(())
/// # }
/// ```
pub fn into_path(mut self) -> PathBuf {
self.path.take().unwrap()
pub fn into_path(self) -> PathBuf {
// Prevent the Drop impl from being called.
let mut this = mem::ManuallyDrop::new(self);
// replace this.path with an empty Box, since an empty Box does not
// allocate any heap memory.
mem::replace(&mut this.path, PathBuf::new().into_boxed_path()).into()
}
/// Closes and removes the temporary directory, returing a `Result`.
/// Closes and removes the temporary directory, returning a `Result`.
///
/// Although `TempDir` removes the directory on drop, in the destructor
/// any errors are ignored. To detect errors cleaning up the temporary
@ -369,8 +375,12 @@ impl TempDir {
pub fn close(mut self) -> io::Result<()> {
let result = remove_dir_all(self.path()).with_err_path(|| self.path());
// Prevent the Drop impl from removing the dir a second time.
self.path = None;
// Set self.path to empty Box to release the memory, since an empty
// Box does not allocate any heap memory.
self.path = PathBuf::new().into_boxed_path();
// Prevent the Drop impl from being called.
mem::forget(self);
result
}
@ -392,15 +402,14 @@ impl fmt::Debug for TempDir {
impl Drop for TempDir {
fn drop(&mut self) {
// Path is `None` if `close()` or `into_path()` has been called.
if let Some(ref p) = self.path {
let _ = remove_dir_all(p);
}
let _ = remove_dir_all(self.path());
}
}
pub(crate) fn create(path: PathBuf) -> io::Result<TempDir> {
fs::create_dir(&path)
.with_err_path(|| &path)
.map(|_| TempDir { path: Some(path) })
.map(|_| TempDir {
path: path.into_boxed_path(),
})
}

Просмотреть файл

@ -1,5 +1,5 @@
cfg_if! {
if #[cfg(any(unix, target_os = "redox"))] {
cfg_if::cfg_if! {
if #[cfg(any(unix, target_os = "redox", target_os = "wasi"))] {
mod unix;
pub use self::unix::*;
} else if #[cfg(windows)] {

Просмотреть файл

@ -2,10 +2,18 @@ use std::env;
use std::ffi::{CString, OsStr};
use std::fs::{self, File, OpenOptions};
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
use std::path::Path;
cfg_if::cfg_if! {
if #[cfg(not(target_os = "wasi"))] {
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
} else {
use std::os::wasi::ffi::OsStrExt;
#[cfg(feature = "nightly")]
use std::os::wasi::fs::MetadataExt;
}
}
use crate::util;
use std::path::Path;
#[cfg(not(target_os = "redox"))]
use libc::{c_char, c_int, link, rename, unlink};
@ -33,12 +41,14 @@ pub fn cstr(path: &Path) -> io::Result<CString> {
}
pub fn create_named(path: &Path, open_options: &mut OpenOptions) -> io::Result<File> {
open_options
.read(true)
.write(true)
.create_new(true)
.mode(0o600)
.open(path)
open_options.read(true).write(true).create_new(true);
#[cfg(not(target_os = "wasi"))]
{
open_options.mode(0o600);
}
open_options.open(path)
}
fn create_unlinked(path: &Path) -> io::Result<File> {
@ -60,11 +70,11 @@ fn create_unlinked(path: &Path) -> io::Result<File> {
#[cfg(target_os = "linux")]
pub fn create(dir: &Path) -> io::Result<File> {
use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_EXCL, O_TMPFILE};
use libc::{EISDIR, ENOENT, EOPNOTSUPP, O_TMPFILE};
OpenOptions::new()
.read(true)
.write(true)
.custom_flags(O_TMPFILE | O_EXCL) // do not mix with `create_new(true)`
.custom_flags(O_TMPFILE) // do not mix with `create_new(true)`
.open(dir)
.or_else(|e| {
match e.raw_os_error() {
@ -90,6 +100,7 @@ fn create_unix(dir: &Path) -> io::Result<File> {
)
}
#[cfg(any(not(target_os = "wasi"), feature = "nightly"))]
pub fn reopen(file: &File, path: &Path) -> io::Result<File> {
let new_file = OpenOptions::new().read(true).write(true).open(path)?;
let old_meta = file.metadata()?;
@ -103,6 +114,14 @@ pub fn reopen(file: &File, path: &Path) -> io::Result<File> {
Ok(new_file)
}
#[cfg(all(target_os = "wasi", not(feature = "nightly")))]
pub fn reopen(_file: &File, _path: &Path) -> io::Result<File> {
return Err(io::Error::new(
io::ErrorKind::Other,
"this operation is supported on WASI only on nightly Rust (with `nightly` feature enabled)",
));
}
#[cfg(not(target_os = "redox"))]
pub fn persist(old_path: &Path, new_path: &Path, overwrite: bool) -> io::Result<()> {
unsafe {

52
third_party/rust/tempfile/src/file/mod.rs поставляемый
Просмотреть файл

@ -1,4 +1,3 @@
use std;
use std::env;
use std::error;
use std::ffi::OsStr;
@ -139,7 +138,7 @@ impl error::Error for PathPersistError {
///
/// When dropped, the temporary file is deleted.
pub struct TempPath {
path: PathBuf,
path: Box<Path>,
}
impl TempPath {
@ -177,8 +176,8 @@ impl TempPath {
/// # }
/// ```
pub fn close(mut self) -> io::Result<()> {
let result = fs::remove_file(&self.path).with_err_path(|| &self.path);
mem::replace(&mut self.path, PathBuf::new());
let result = fs::remove_file(&self.path).with_err_path(|| &*self.path);
self.path = PathBuf::new().into_boxed_path();
mem::forget(self);
result
}
@ -189,7 +188,10 @@ impl TempPath {
/// If this method fails, it will return `self` in the resulting
/// [`PathPersistError`].
///
/// Note: Temporary files cannot be persisted across filesystems.
/// Note: Temporary files cannot be persisted across filesystems. Also
/// neither the file contents nor the containing directory are
/// synchronized, so the update may not yet have reached the disk when
/// `persist` returns.
///
/// # Security
///
@ -229,7 +231,7 @@ impl TempPath {
// Don't drop `self`. We don't want to try deleting the old
// temporary file path. (It'll fail, but the failure is never
// seen.)
mem::replace(&mut self.path, PathBuf::new());
self.path = PathBuf::new().into_boxed_path();
mem::forget(self);
Ok(())
}
@ -240,7 +242,7 @@ impl TempPath {
}
}
/// Persist the temporary file at the target path iff no file exists there.
/// Persist the temporary file at the target path if and only if no file exists there.
///
/// If a file exists at the target path, fail. If this method fails, it will
/// return `self` in the resulting [`PathPersistError`].
@ -291,7 +293,7 @@ impl TempPath {
// Don't drop `self`. We don't want to try deleting the old
// temporary file path. (It'll fail, but the failure is never
// seen.)
mem::replace(&mut self.path, PathBuf::new());
self.path = PathBuf::new().into_boxed_path();
mem::forget(self);
Ok(())
}
@ -339,10 +341,9 @@ impl TempPath {
// Don't drop `self`. We don't want to try deleting the old
// temporary file path. (It'll fail, but the failure is never
// seen.)
let mut path = PathBuf::new();
mem::swap(&mut self.path, &mut path);
let path = mem::replace(&mut self.path, PathBuf::new().into_boxed_path());
mem::forget(self);
Ok(path)
Ok(path.into())
}
Err(e) => Err(PathPersistError {
error: e,
@ -350,6 +351,18 @@ impl TempPath {
}),
}
}
/// Create a new TempPath from an existing path. This can be done even if no
/// file exists at the given path.
///
/// This is mostly useful for interacting with libraries and external
/// components that provide files to be consumed or expect a path with no
/// existing file to be given.
pub fn from_path(path: impl Into<PathBuf>) -> Self {
Self {
path: path.into().into_boxed_path(),
}
}
}
impl fmt::Debug for TempPath {
@ -584,7 +597,7 @@ impl NamedTempFile {
///
/// See [`NamedTempFile::new()`] for details.
///
/// [`NamedTempFile::new()`]: #method.new_in
/// [`NamedTempFile::new()`]: #method.new
pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
Builder::new().tempfile_in(dir)
}
@ -662,11 +675,14 @@ impl NamedTempFile {
/// If this method fails, it will return `self` in the resulting
/// [`PersistError`].
///
/// Note: Temporary files cannot be persisted across filesystems.
/// Note: Temporary files cannot be persisted across filesystems. Also
/// neither the file contents nor the containing directory are
/// synchronized, so the update may not yet have reached the disk when
/// `persist` returns.
///
/// # Security
///
/// This method persists the temporary file using it's path and may not be
/// This method persists the temporary file using its path and may not be
/// secure in the in all cases. Please read the security section on the top
/// level documentation of this type for details.
///
@ -709,7 +725,7 @@ impl NamedTempFile {
}
}
/// Persist the temporary file at the target path iff no file exists there.
/// Persist the temporary file at the target path if and only if no file exists there.
///
/// If a file exists at the target path, fail. If this method fails, it will
/// return `self` in the resulting PersistError.
@ -720,7 +736,7 @@ impl NamedTempFile {
///
/// # Security
///
/// This method persists the temporary file using it's path and may not be
/// This method persists the temporary file using its path and may not be
/// secure in the in all cases. Please read the security section on the top
/// level documentation of this type for details.
///
@ -949,7 +965,9 @@ pub(crate) fn create_named(
imp::create_named(&path, open_options)
.with_err_path(|| path.clone())
.map(|file| NamedTempFile {
path: TempPath { path },
path: TempPath {
path: path.into_boxed_path(),
},
file,
})
}

46
third_party/rust/tempfile/src/lib.rs поставляемый
Просмотреть файл

@ -27,6 +27,42 @@
//! rely on file paths for _some_ operations. See the security documentation on
//! the `NamedTempFile` type for more information.
//!
//! ## Early drop pitfall
//!
//! Because `TempDir` and `NamedTempFile` rely on their destructors for cleanup, this can lead
//! to an unexpected early removal of the directory/file, usually when working with APIs which are
//! generic over `AsRef<Path>`. Consider the following example:
//!
//! ```no_run
//! # use tempfile::tempdir;
//! # use std::io;
//! # use std::process::Command;
//! # fn main() {
//! # if let Err(_) = run() {
//! # ::std::process::exit(1);
//! # }
//! # }
//! # fn run() -> Result<(), io::Error> {
//! // Create a directory inside of `std::env::temp_dir()`.
//! let temp_dir = tempdir()?;
//!
//! // Spawn the `touch` command inside the temporary directory and collect the exit status
//! // Note that `temp_dir` is **not** moved into `current_dir`, but passed as a reference
//! let exit_status = Command::new("touch").arg("tmp").current_dir(&temp_dir).status()?;
//! assert!(exit_status.success());
//!
//! # Ok(())
//! # }
//! ```
//!
//! This works because a reference to `temp_dir` is passed to `current_dir`, resulting in the
//! destructor of `temp_dir` being run after the `Command` has finished execution. Moving the
//! `TempDir` into the `current_dir` call would result in the `TempDir` being converted into
//! an internal representation, with the original value being dropped and the directory thus
//! being deleted, before the command can be executed.
//!
//! The `touch` command would fail with an `No such file or directory` error.
//!
//! ## Examples
//!
//! Create a temporary file and write some data into it:
@ -124,9 +160,11 @@
)]
#![cfg_attr(test, deny(warnings))]
#![deny(rust_2018_idioms)]
#![allow(clippy::redundant_field_names)]
#![cfg_attr(feature = "nightly", feature(wasi_ext))]
#[macro_use]
extern crate cfg_if;
#[cfg(doctest)]
doc_comment::doctest!("../README.md");
const NUM_RETRIES: u32 = 1 << 31;
const NUM_RAND_CHARS: usize = 6;
@ -143,7 +181,9 @@ mod spooled;
mod util;
pub use crate::dir::{tempdir, tempdir_in, TempDir};
pub use crate::file::{tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath};
pub use crate::file::{
tempfile, tempfile_in, NamedTempFile, PathPersistError, PersistError, TempPath,
};
pub use crate::spooled::{spooled_tempfile, SpooledTempFile};
/// Create a new temporary file or directory with custom parameters.

42
third_party/rust/tempfile/src/spooled.rs поставляемый
Просмотреть файл

@ -2,8 +2,9 @@ use crate::file::tempfile;
use std::fs::File;
use std::io::{self, Cursor, Read, Seek, SeekFrom, Write};
/// A wrapper for the two states of a `SpooledTempFile`.
#[derive(Debug)]
enum SpooledInner {
pub enum SpooledData {
InMemory(Cursor<Vec<u8>>),
OnDisk(File),
}
@ -15,7 +16,7 @@ enum SpooledInner {
#[derive(Debug)]
pub struct SpooledTempFile {
max_size: usize,
inner: SpooledInner,
inner: SpooledData,
}
/// Create a new spooled temporary file.
@ -66,15 +67,15 @@ impl SpooledTempFile {
pub fn new(max_size: usize) -> SpooledTempFile {
SpooledTempFile {
max_size: max_size,
inner: SpooledInner::InMemory(Cursor::new(Vec::new())),
inner: SpooledData::InMemory(Cursor::new(Vec::new())),
}
}
/// Returns true if the file has been rolled over to disk.
pub fn is_rolled(&self) -> bool {
match self.inner {
SpooledInner::InMemory(_) => false,
SpooledInner::OnDisk(_) => true,
SpooledData::InMemory(_) => false,
SpooledData::OnDisk(_) => true,
}
}
@ -83,11 +84,11 @@ impl SpooledTempFile {
pub fn roll(&mut self) -> io::Result<()> {
if !self.is_rolled() {
let mut file = tempfile()?;
if let SpooledInner::InMemory(ref mut cursor) = self.inner {
if let SpooledData::InMemory(ref mut cursor) = self.inner {
file.write_all(cursor.get_ref())?;
file.seek(SeekFrom::Start(cursor.position()))?;
}
self.inner = SpooledInner::OnDisk(file);
self.inner = SpooledData::OnDisk(file);
}
Ok(())
}
@ -97,20 +98,25 @@ impl SpooledTempFile {
self.roll()?; // does nothing if already rolled over
}
match self.inner {
SpooledInner::InMemory(ref mut cursor) => {
SpooledData::InMemory(ref mut cursor) => {
cursor.get_mut().resize(size as usize, 0);
Ok(())
}
SpooledInner::OnDisk(ref mut file) => file.set_len(size),
SpooledData::OnDisk(ref mut file) => file.set_len(size),
}
}
/// Consumes and returns the inner `SpooledData` type.
pub fn into_inner(self) -> SpooledData {
self.inner
}
}
impl Read for SpooledTempFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.inner {
SpooledInner::InMemory(ref mut cursor) => cursor.read(buf),
SpooledInner::OnDisk(ref mut file) => file.read(buf),
SpooledData::InMemory(ref mut cursor) => cursor.read(buf),
SpooledData::OnDisk(ref mut file) => file.read(buf),
}
}
}
@ -119,7 +125,7 @@ impl Write for SpooledTempFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
// roll over to file if necessary
let mut rolling = false;
if let SpooledInner::InMemory(ref mut cursor) = self.inner {
if let SpooledData::InMemory(ref mut cursor) = self.inner {
rolling = cursor.position() as usize + buf.len() > self.max_size;
}
if rolling {
@ -128,16 +134,16 @@ impl Write for SpooledTempFile {
// write the bytes
match self.inner {
SpooledInner::InMemory(ref mut cursor) => cursor.write(buf),
SpooledInner::OnDisk(ref mut file) => file.write(buf),
SpooledData::InMemory(ref mut cursor) => cursor.write(buf),
SpooledData::OnDisk(ref mut file) => file.write(buf),
}
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
match self.inner {
SpooledInner::InMemory(ref mut cursor) => cursor.flush(),
SpooledInner::OnDisk(ref mut file) => file.flush(),
SpooledData::InMemory(ref mut cursor) => cursor.flush(),
SpooledData::OnDisk(ref mut file) => file.flush(),
}
}
}
@ -145,8 +151,8 @@ impl Write for SpooledTempFile {
impl Seek for SpooledTempFile {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
match self.inner {
SpooledInner::InMemory(ref mut cursor) => cursor.seek(pos),
SpooledInner::OnDisk(ref mut file) => file.seek(pos),
SpooledData::InMemory(ref mut cursor) => cursor.seek(pos),
SpooledData::OnDisk(ref mut file) => file.seek(pos),
}
}
}

23
third_party/rust/tempfile/src/util.rs поставляемый
Просмотреть файл

@ -1,23 +1,16 @@
use rand::distributions::Alphanumeric;
use rand::{self, Rng};
use fastrand;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::{io, str};
use std::{io, iter::repeat_with};
use crate::error::IoResultExt;
fn tmpname(prefix: &OsStr, suffix: &OsStr, rand_len: usize) -> OsString {
let mut buf = OsString::with_capacity(prefix.len() + suffix.len() + rand_len);
buf.push(prefix);
// Push each character in one-by-one. Unfortunately, this is the only
// safe(ish) simple way to do this without allocating a temporary
// String/Vec.
unsafe {
rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(rand_len)
.for_each(|b| buf.push(str::from_utf8_unchecked(&[b as u8])))
let mut char_buf = [0u8; 4];
for c in repeat_with(fastrand::alphanumeric).take(rand_len) {
buf.push(c.encode_utf8(&mut char_buf));
}
buf.push(suffix);
buf
@ -33,7 +26,11 @@ pub fn create_helper<F, R>(
where
F: Fn(PathBuf) -> io::Result<R>,
{
let num_retries = if random_len != 0 { crate::NUM_RETRIES } else { 1 };
let num_retries = if random_len != 0 {
crate::NUM_RETRIES
} else {
1
};
for _ in 0..num_retries {
let path = base.join(tmpname(prefix, suffix, random_len));

Просмотреть файл

@ -1,10 +1,11 @@
#![deny(rust_2018_idioms)]
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;
use tempfile::{Builder, NamedTempFile};
use std::path::{Path, PathBuf};
use tempfile::{tempdir, Builder, NamedTempFile, TempPath};
fn exists<P: AsRef<Path>>(path: P) -> bool {
std::fs::metadata(path.as_ref()).is_ok()
@ -216,6 +217,50 @@ fn test_temppath_persist_noclobber() {
std::fs::remove_file(&persist_path).unwrap();
}
#[test]
fn temp_path_from_existing() {
let tmp_dir = tempdir().unwrap();
let tmp_file_path_1 = tmp_dir.path().join("testfile1");
let tmp_file_path_2 = tmp_dir.path().join("testfile2");
File::create(&tmp_file_path_1).unwrap();
assert!(tmp_file_path_1.exists(), "Test file 1 hasn't been created");
File::create(&tmp_file_path_2).unwrap();
assert!(tmp_file_path_2.exists(), "Test file 2 hasn't been created");
let tmp_path = TempPath::from_path(&tmp_file_path_1);
assert!(
tmp_file_path_1.exists(),
"Test file has been deleted before dropping TempPath"
);
drop(tmp_path);
assert!(
!tmp_file_path_1.exists(),
"Test file exists after dropping TempPath"
);
assert!(
tmp_file_path_2.exists(),
"Test file 2 has been deleted before dropping TempDir"
);
}
#[test]
#[allow(unreachable_code)]
fn temp_path_from_argument_types() {
// This just has to compile
return;
TempPath::from_path("");
TempPath::from_path(String::new());
TempPath::from_path(OsStr::new(""));
TempPath::from_path(OsString::new());
TempPath::from_path(Path::new(""));
TempPath::from_path(PathBuf::new());
TempPath::from_path(PathBuf::new().into_boxed_path());
}
#[test]
fn test_write_after_close() {
let path = NamedTempFile::new().unwrap().into_temp_path();

2
third_party/rust/tempfile/tests/tempfile.rs поставляемый
Просмотреть файл

@ -26,6 +26,8 @@ fn test_cleanup() {
assert!(num_files == 0);
}
// Only run this test on Linux. MacOS doesn't like us creating so many files, apparently.
#[cfg(target_os = "linux")]
#[test]
fn test_pathological_cleaner() {
let tmpdir = tempfile::tempdir().unwrap();