Bug 1864000 - Update minidump-writer to version 0.8.3 r=glandium,supply-chain-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D194529
This commit is contained in:
Gabriele Svelto 2023-11-30 17:01:18 +00:00
Родитель 234b79048d
Коммит f86c830487
113 изменённых файлов: 8755 добавлений и 3313 удалений

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

@ -100,16 +100,6 @@ git = "https://github.com/rust-diplomat/diplomat"
rev = "8d125999893fedfdf30595e97334c21ec4b18da9"
replace-with = "vendored-sources"
[source."git+https://github.com/rust-minidump/minidump-writer.git?rev=491eb330e78e310c32927e5cc3bd2350af1e93f8"]
git = "https://github.com/rust-minidump/minidump-writer.git"
rev = "491eb330e78e310c32927e5cc3bd2350af1e93f8"
replace-with = "vendored-sources"
[source."git+https://github.com/rust-minidump/rust-minidump?rev=6ae42a7f992e8a88ebee661bc77bcedb95cd671f"]
git = "https://github.com/rust-minidump/rust-minidump"
rev = "6ae42a7f992e8a88ebee661bc77bcedb95cd671f"
replace-with = "vendored-sources"
[source."git+https://github.com/servo/rust-cssparser?rev=aaa966d9d6ae70c4b8a62bb5e3a14c068bb7dff0"]
git = "https://github.com/servo/rust-cssparser"
rev = "aaa966d9d6ae70c4b8a62bb5e3a14c068bb7dff0"

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

@ -265,7 +265,7 @@ dependencies = [
"iovec",
"libc",
"log",
"memmap2",
"memmap2 0.5.999",
"mio 0.8.8",
"scopeguard",
"serde",
@ -3305,7 +3305,7 @@ source = "git+https://github.com/jfkthame/mapped_hyph.git?rev=c7651a0cffff41996a
dependencies = [
"arrayref",
"log",
"memmap2",
"memmap2 0.5.999",
]
[[package]]
@ -3358,9 +3358,16 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
version = "0.5.9"
version = "0.5.999"
dependencies = [
"memmap2 0.8.0",
]
[[package]]
name = "memmap2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2"
checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
dependencies = [
"libc",
]
@ -3449,10 +3456,11 @@ dependencies = [
[[package]]
name = "minidump-common"
version = "0.17.0"
source = "git+https://github.com/rust-minidump/rust-minidump?rev=6ae42a7f992e8a88ebee661bc77bcedb95cd671f#6ae42a7f992e8a88ebee661bc77bcedb95cd671f"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2"
dependencies = [
"bitflags 1.999.999",
"bitflags 2.4.0",
"debugid",
"num-derive",
"num-traits",
@ -3463,8 +3471,9 @@ dependencies = [
[[package]]
name = "minidump-writer"
version = "0.8.1"
source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=491eb330e78e310c32927e5cc3bd2350af1e93f8#491eb330e78e310c32927e5cc3bd2350af1e93f8"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "017101620fe5d413ac2d98224ab8b1fff0d4bacaf2803c130ad4a6db3e5d3e70"
dependencies = [
"bitflags 2.4.0",
"byteorder",
@ -3473,10 +3482,10 @@ dependencies = [
"goblin 0.7.1",
"libc",
"mach2",
"memmap2",
"memmap2 0.8.0",
"memoffset 0.9.0",
"minidump-common",
"nix 0.26.2",
"nix 0.27.1",
"procfs-core",
"scroll",
"tempfile",
@ -3910,19 +3919,18 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
name = "nix"
version = "0.24.99"
dependencies = [
"nix 0.26.2",
"nix 0.27.1",
]
[[package]]
name = "nix"
version = "0.26.2"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
"bitflags 1.999.999",
"bitflags 2.4.0",
"cfg-if 1.0.0",
"libc",
"static_assertions",
]
[[package]]
@ -4407,9 +4415,9 @@ dependencies = [
[[package]]
name = "procfs-core"
version = "0.16.0-RC1"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ee00a90a41543fce203e6a8771bad043bfd6d88de8fd4e3118435a233d0c3c4"
checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29"
dependencies = [
"bitflags 2.4.0",
"hex",
@ -4427,7 +4435,7 @@ dependencies = [
name = "profiler_helper"
version = "0.1.0"
dependencies = [
"memmap2",
"memmap2 0.5.999",
"object",
"rustc-demangle",
"thin-vec",

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

@ -111,6 +111,9 @@ terminal_size = { path = "build/rust/terminal_size" }
# Patch bitflags 2.0 to 1.0 while not too many crates use 2.0 features
bitflags = { path = "build/rust/bitflags" }
# Patch memmap2 0.5.x to 0.8.0
memmap2 = { path = "build/rust/memmap2" }
# Patch cfg-if 0.1 to 1.0
cfg-if = { path = "build/rust/cfg-if" }
@ -142,7 +145,7 @@ bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
bindgen_0_64 = { package = "bindgen", path = "build/rust/bindgen-0.64" }
bindgen = { path = "build/rust/bindgen" }
# Patch nix 0.24 to 0.26
# Patch nix 0.24 to 0.27
nix = { path = "build/rust/nix" }
# Patch indexmap 2.0 to 1.0
@ -190,10 +193,6 @@ firefox-on-glean = { path = "toolkit/components/glean/api" }
icu_testdata = { path = "intl/icu_testdata" }
libudev-sys = { path = "dom/webauthn/libudev-sys" }
midir = { git = "https://github.com/mozilla/midir.git", rev = "519e651241e867af3391db08f9ae6400bc023e18" }
# Avoid the dependency on chrono and include Android support
minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "491eb330e78e310c32927e5cc3bd2350af1e93f8" }
# Bump some dependencies
minidump-common = { git = "https://github.com/rust-minidump/rust-minidump", rev = "6ae42a7f992e8a88ebee661bc77bcedb95cd671f" }
# warp 0.3.3 + https://github.com/seanmonstar/warp/pull/1007
warp = { git = "https://github.com/glandium/warp", rev = "4af45fae95bc98b0eba1ef0db17e1dac471bb23d" }
# Allow webrender to have a versioned dependency on the older crate on crates.io

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

@ -0,0 +1,11 @@
[package]
name = "memmap2"
version = "0.5.999"
edition = "2018"
license = "MPL-2.0"
[lib]
path = "lib.rs"
[dependencies.memmap2]
version = "0.8.0"

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

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
pub use memmap2::*;

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

@ -8,7 +8,7 @@ license = "MPL-2.0"
path = "lib.rs"
[dependencies.nix]
version = "0.26"
version = "0.27"
default-features = false
[features]

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

@ -2235,6 +2235,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.5.8 -> 0.5.9"
[[audits.memmap2]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.5.9 -> 0.8.0"
[[audits.memoffset]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
@ -2293,6 +2298,12 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.17.0 -> 0.17.0@git:87a29fba5e19cfae5ebf73a57ba31504a3872545"
[[audits.minidump-common]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.17.0 -> 0.19.1"
notes = "All the changes have been authored or reviewed by Mozilla employees"
[[audits.minidump-common]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -2321,6 +2332,12 @@ criteria = "safe-to-deploy"
delta = "0.8.1 -> 0.8.1@git:491eb330e78e310c32927e5cc3bd2350af1e93f8"
notes = "All the changes were written by a Mozilla employee (me)"
[[audits.minidump-writer]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.8.1 -> 0.8.3"
notes = "All changes were authored or reviewed by Mozilla employees"
[[audits.miniz_oxide]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -2436,6 +2453,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.25.1 -> 0.26.2"
[[audits.nix]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.26.2 -> 0.27.1"
[[audits.nom]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -2798,6 +2820,11 @@ who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
version = "0.16.0-RC1"
[[audits.procfs-core]]
who = "Gabriele Svelto <gsvelto@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.16.0-RC1 -> 0.16.0"
[[audits.profiling]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"

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

@ -116,14 +116,6 @@ notes = "This is a first-party crate which is also published to crates.io. We ce
audit-as-crates-io = true
notes = "This is a pinned version of the upstream code, presumably to get a fix that hadn't been released yet. We should consider switching to the latest official release."
[policy."minidump-common:0.17.0@git:6ae42a7f992e8a88ebee661bc77bcedb95cd671f"]
audit-as-crates-io = true
notes = "Unreleased upstream."
[policy.minidump-writer]
audit-as-crates-io = true
notes = "Unreleased upstream."
[policy."mio:0.6.23"]
audit-as-crates-io = true
notes = "Version 0.6.23 is a local fork of upstream which just twiddles some dependencies."

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

@ -1 +1 @@
{"files":{"CHANGELOG.md":"ec5972562a347a1be399c91584ccecb609578c003cf32a5897457a42d3011a6d","Cargo.lock":"48644099a4476d43e9c5a4735b2afe8ef5421e264a96b0dd1ab9c11674afbe69","Cargo.toml":"dc57d3ea17db4790f9dc1a7c7453e86e21e2e1b47b234c8c04cbc9878afd93f8","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"c7b3cd928f0d1a10faa255e2f84a2a06636e55ea3e7edd4f6334dd9215151205","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/advice.rs":"194bfd6a32495f6b0c739d083b06230ae656927767f15c1b49b245b63431cc4d","src/lib.rs":"43af9a94be23c31795b56af94614dc89c39b256b05b9a6b1afd3a836c0982c92","src/stub.rs":"f276bb5e4bc29c2129ebc660b01a1de173b9575e2e866ea5a34e0ee6318f1177","src/unix.rs":"ec544b17083e7737edec8588983461385abe3acfa793b07bb1342373ba540113","src/windows.rs":"bbb39200ac35b5517626c12efad4886f7b5d34e56256284914c556dec1567e38"},"package":"2af2c65375e552a67fe3829ca63e8a7c27a378a62824594f43b2851d682b5ec2"}
{"files":{"CHANGELOG.md":"d334fd0c52c9dd01592b62bb37e2bf4dd1ac176062aacfd915e90de9ffa5e376","Cargo.lock":"8634a29932d4af588c7ede3a939f725ba36455e63e2e4da76d4608e72dd8a6c2","Cargo.toml":"9e9bf7eea9db0f7d3f22aa8abaa040f7870ab8788b43d14b210f0e2ecf8f5e38","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"c7b3cd928f0d1a10faa255e2f84a2a06636e55ea3e7edd4f6334dd9215151205","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/advice.rs":"6e88b81dcf4e7c9315484c228fe5f5a4ce5c8c06e6d8cb866e50bdd9ea8b55ec","src/lib.rs":"19b739c03e43901ce3994818b5d070d844d5a46a9b50d7e22934511722281199","src/stub.rs":"691da940edbe807a815d4a6bb3233df01bca8ab12b306ce7d67c75b4baa14e26","src/unix.rs":"f79013879989364168186dc925446a1d1f9de11999103415ae9970319fb14491","src/windows.rs":"ba820e315a31cd74fee49fcf7606af0172c0817b4a0fe3b1d113024efa79684f"},"package":"43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"}

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

@ -6,6 +6,50 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [0.8.0] - 2023-09-25
### Changed
- The `Advice` type is a struct and not an enum now.
[@adamreichold](https://github.com/adamreichold)
### Fixed
- Some of the `Advise` variants were unsound and now require `unsafe` to be constructed.
[@adamreichold](https://github.com/adamreichold)
## [0.7.1] - 2023-06-24
### Fixed
- Mapping beyond 4GB offset on 32 bit glibc. Linux-only.
[@lvella](https://github.com/lvella)
## [0.7.0] - 2023-06-08
### Added
- `Mmap::remap`, `MmapMut::remap` and `MmapRaw::remap`. Linux-only.
[@Phantomical](https://github.com/Phantomical)
- `Advice::PopulateRead` and `Advice::PopulateWrite`. Linux-only.
[@Jesse-Bakker](https://github.com/Jesse-Bakker)
### Changed
- libc crate >= 0.2.143 is required now.
## [0.6.2] - 2023-05-24
### Fixed
- Alignment for empty files on Windows.
[@timvisee](https://github.com/timvisee)
## [0.6.1] - 2023-05-10
### Added
- Add `MmapOptions::map_raw_read_only` to avoid intermediate invalid `Mmap` instances.
[@adamreichold](https://github.com/adamreichold)
## [0.6.0] - 2023-05-09
### Changed
- `lock()` and `unlock` methods require `&self` and not `&mut self` now.
[@timvisee](https://github.com/timvisee)
## [0.5.10] - 2023-02-22
### Added
- `MmapOptions::map_anon` accounts for `populate` on Linux now.
[@jsgf](https://github.com/jsgf)
## [0.5.9] - 2023-02-17
### Added
- `From<Mmap> for MmapRaw` and `From<MmapMut> for MmapRaw`.
@ -130,7 +174,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Removed
- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89)
[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.9...HEAD
[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.8.0...HEAD
[0.8.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.7.1...v0.8.0
[0.7.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.6.2...v0.7.0
[0.6.2]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.10...v0.6.0
[0.5.10]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.9...v0.5.10
[0.5.9]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.8...v0.5.9
[0.5.8]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.7...v0.5.8
[0.5.7]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.6...v0.5.7

6
third_party/rust/memmap2/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -34,13 +34,13 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "memmap2"
version = "0.5.9"
version = "0.8.0"
dependencies = [
"libc",
"owning_ref",

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

@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "memmap2"
version = "0.5.9"
version = "0.8.0"
authors = [
"Dan Burkert <dan@danburkert.com>",
"Yevhenii Reizner <razrfalcon@gmail.com>",
@ -40,4 +40,4 @@ version = "0.4.1"
version = "3"
[target."cfg(unix)".dependencies.libc]
version = "0.2"
version = "0.2.143"

190
third_party/rust/memmap2/src/advice.rs поставляемый
Просмотреть файл

@ -1,35 +1,40 @@
// The use statement is needed for the `cargo docs`
#[allow(unused_imports)]
use crate::{Mmap, MmapMut};
/// Values supported by [Mmap::advise] and [MmapMut::advise] functions.
/// Values supported by [`Mmap::advise`][crate::Mmap::advise] and [`MmapMut::advise`][crate::MmapMut::advise] functions.
/// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
#[repr(i32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Advice {
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct Advice(pub(crate) libc::c_int);
impl Advice {
/// **MADV_NORMAL**
///
/// No special treatment. This is the default.
Normal = libc::MADV_NORMAL,
pub fn normal() -> Self {
Self(libc::MADV_NORMAL)
}
/// **MADV_RANDOM**
///
/// Expect page references in random order. (Hence, read
/// ahead may be less useful than normally.)
Random = libc::MADV_RANDOM,
pub fn random() -> Self {
Self(libc::MADV_RANDOM)
}
/// **MADV_SEQUENTIAL**
///
/// Expect page references in sequential order. (Hence, pages
/// in the given range can be aggressively read ahead, and may
/// be freed soon after they are accessed.)
Sequential = libc::MADV_SEQUENTIAL,
pub fn sequential() -> Self {
Self(libc::MADV_SEQUENTIAL)
}
/// **MADV_WILLNEED**
///
/// Expect access in the near future. (Hence, it might be a
/// good idea to read some pages ahead.)
WillNeed = libc::MADV_WILLNEED,
pub fn will_need() -> Self {
Self(libc::MADV_WILLNEED)
}
/// **MADV_DONTNEED**
///
@ -60,7 +65,15 @@ pub enum Advice {
/// not managed by the virtual memory subsystem. Such pages
/// are typically created by device drivers that map the pages
/// into user space.)
DontNeed = libc::MADV_DONTNEED,
///
/// # Safety
///
/// Using the returned value with conceptually write to the
/// mapped pages, i.e. borrowing the mapping when the pages
/// are freed results in undefined behaviour.
pub unsafe fn dont_need() -> Self {
Self(libc::MADV_DONTNEED)
}
//
// The rest are Linux-specific
@ -88,8 +101,16 @@ pub enum Advice {
/// 4.12, when freeing pages on a swapless system, the pages
/// in the given range are freed instantly, regardless of
/// memory pressure.
///
/// # Safety
///
/// Using the returned value with conceptually write to the
/// mapped pages, i.e. borrowing the mapping while the pages
/// are still being freed results in undefined behaviour.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios"))]
Free = libc::MADV_FREE,
pub unsafe fn free() -> Self {
Self(libc::MADV_FREE)
}
/// **MADV_REMOVE** - Linux only (since Linux 2.6.16)
///
@ -109,8 +130,16 @@ pub enum Advice {
/// supports MADV_REMOVE. Hugetlbfs fails with the error
/// EINVAL and other filesystems fail with the error
/// EOPNOTSUPP.
///
/// # Safety
///
/// Using the returned value with conceptually write to the
/// mapped pages, i.e. borrowing the mapping when the pages
/// are freed results in undefined behaviour.
#[cfg(target_os = "linux")]
Remove = libc::MADV_REMOVE,
pub unsafe fn remove() -> Self {
Self(libc::MADV_REMOVE)
}
/// **MADV_DONTFORK** - Linux only (since Linux 2.6.16)
///
@ -121,14 +150,18 @@ pub enum Advice {
/// relocations cause problems for hardware that DMAs into the
/// page.)
#[cfg(target_os = "linux")]
DontFork = libc::MADV_DONTFORK,
pub fn dont_fork() -> Self {
Self(libc::MADV_DONTFORK)
}
/// **MADV_DOFORK** - Linux only (since Linux 2.6.16)
///
/// Undo the effect of MADV_DONTFORK, restoring the default
/// behavior, whereby a mapping is inherited across fork(2).
#[cfg(target_os = "linux")]
DoFork = libc::MADV_DOFORK,
pub fn do_fork() -> Self {
Self(libc::MADV_DOFORK)
}
/// **MADV_MERGEABLE** - Linux only (since Linux 2.6.32)
///
@ -151,7 +184,9 @@ pub enum Advice {
/// available only if the kernel was configured with
/// CONFIG_KSM.
#[cfg(target_os = "linux")]
Mergeable = libc::MADV_MERGEABLE,
pub fn mergeable() -> Self {
Self(libc::MADV_MERGEABLE)
}
/// **MADV_UNMERGEABLE** - Linux only (since Linux 2.6.32)
///
@ -160,7 +195,9 @@ pub enum Advice {
/// it had merged in the address range specified by addr and
/// length.
#[cfg(target_os = "linux")]
Unmergeable = libc::MADV_UNMERGEABLE,
pub fn unmergeable() -> Self {
Self(libc::MADV_UNMERGEABLE)
}
/// **MADV_HUGEPAGE** - Linux only (since Linux 2.6.38)
///
@ -199,14 +236,18 @@ pub enum Advice {
/// available only if the kernel was configured with
/// CONFIG_TRANSPARENT_HUGEPAGE.
#[cfg(target_os = "linux")]
HugePage = libc::MADV_HUGEPAGE,
pub fn huge_page() -> Self {
Self(libc::MADV_HUGEPAGE)
}
/// **MADV_NOHUGEPAGE** - Linux only (since Linux 2.6.38)
///
/// Ensures that memory in the address range specified by addr
/// and length will not be backed by transparent hugepages.
#[cfg(target_os = "linux")]
NoHugePage = libc::MADV_NOHUGEPAGE,
pub fn no_huge_page() -> Self {
Self(libc::MADV_NOHUGEPAGE)
}
/// **MADV_DONTDUMP** - Linux only (since Linux 3.4)
///
@ -218,13 +259,17 @@ pub enum Advice {
/// set via the `/proc/[pid]/coredump_filter` file (see
/// core(5)).
#[cfg(target_os = "linux")]
DontDump = libc::MADV_DONTDUMP,
pub fn dont_dump() -> Self {
Self(libc::MADV_DONTDUMP)
}
/// **MADV_DODUMP** - Linux only (since Linux 3.4)
///
/// Undo the effect of an earlier MADV_DONTDUMP.
#[cfg(target_os = "linux")]
DoDump = libc::MADV_DODUMP,
pub fn do_dump() -> Self {
Self(libc::MADV_DODUMP)
}
/// **MADV_HWPOISON** - Linux only (since Linux 2.6.32)
///
@ -239,7 +284,80 @@ pub enum Advice {
/// handling code; it is available only if the kernel was
/// configured with CONFIG_MEMORY_FAILURE.
#[cfg(target_os = "linux")]
HwPoison = libc::MADV_HWPOISON,
pub fn hw_poison() -> Self {
Self(libc::MADV_HWPOISON)
}
/// **MADV_POPULATE_READ** - Linux only (since Linux 5.14)
///
/// Populate (prefault) page tables readable, faulting in all
/// pages in the range just as if manually reading from each
/// page; however, avoid the actual memory access that would have
/// been performed after handling the fault.
///
/// In contrast to MAP_POPULATE, MADV_POPULATE_READ does not hide
/// errors, can be applied to (parts of) existing mappings and
/// will always populate (prefault) page tables readable. One
/// example use case is prefaulting a file mapping, reading all
/// file content from disk; however, pages won't be dirtied and
/// consequently won't have to be written back to disk when
/// evicting the pages from memory.
///
/// Depending on the underlying mapping, map the shared zeropage,
/// preallocate memory or read the underlying file; files with
/// holes might or might not preallocate blocks. If populating
/// fails, a SIGBUS signal is not generated; instead, an error is
/// returned.
///
/// If MADV_POPULATE_READ succeeds, all page tables have been
/// populated (prefaulted) readable once. If MADV_POPULATE_READ
/// fails, some page tables might have been populated.
///
/// MADV_POPULATE_READ cannot be applied to mappings without read
/// permissions and special mappings, for example, mappings
/// marked with kernel-internal flags such as VM_PFNMAP or VM_IO,
/// or secret memory regions created using memfd_secret(2).
///
/// Note that with MADV_POPULATE_READ, the process can be killed
/// at any moment when the system runs out of memory.
#[cfg(target_os = "linux")]
pub fn populate_read() -> Self {
Self(libc::MADV_POPULATE_READ)
}
/// **MADV_POPULATE_WRITE** - Linux only (since Linux 5.14)
///
/// Populate (prefault) page tables writable, faulting in all
/// pages in the range just as if manually writing to each each
/// page; however, avoid the actual memory access that would have
/// been performed after handling the fault.
///
/// In contrast to MAP_POPULATE, MADV_POPULATE_WRITE does not
/// hide errors, can be applied to (parts of) existing mappings
/// and will always populate (prefault) page tables writable.
/// One example use case is preallocating memory, breaking any
/// CoW (Copy on Write).
///
/// Depending on the underlying mapping, preallocate memory or
/// read the underlying file; files with holes will preallocate
/// blocks. If populating fails, a SIGBUS signal is not gener
/// ated; instead, an error is returned.
///
/// If MADV_POPULATE_WRITE succeeds, all page tables have been
/// populated (prefaulted) writable once. If MADV_POPULATE_WRITE
/// fails, some page tables might have been populated.
///
/// MADV_POPULATE_WRITE cannot be applied to mappings without
/// write permissions and special mappings, for example, mappings
/// marked with kernel-internal flags such as VM_PFNMAP or VM_IO,
/// or secret memory regions created using memfd_secret(2).
///
/// Note that with MADV_POPULATE_WRITE, the process can be killed
/// at any moment when the system runs out of memory.
#[cfg(target_os = "linux")]
pub fn populate_write() -> Self {
Self(libc::MADV_POPULATE_WRITE)
}
/// **MADV_ZERO_WIRED_PAGES** - Darwin only
///
@ -248,21 +366,39 @@ pub enum Advice {
/// a munmap(2) without a preceding munlock(2) or the application quits). This is used
/// with madvise() system call.
#[cfg(any(target_os = "macos", target_os = "ios"))]
ZeroWiredPages = libc::MADV_ZERO_WIRED_PAGES,
pub fn zero_wired_pages() -> Self {
Self(libc::MADV_ZERO_WIRED_PAGES)
}
/// **MADV_FREE_REUSABLE** - Darwin only
///
/// Behaves like **MADV_FREE**, but the freed pages are accounted for in the RSS of the process.
///
/// # Safety
///
/// Using the returned value with conceptually write to the
/// mapped pages, i.e. borrowing the mapping while the pages
/// are still being freed results in undefined behaviour.
#[cfg(any(target_os = "macos", target_os = "ios"))]
FreeReusable = libc::MADV_FREE_REUSABLE,
pub unsafe fn free_reusable() -> Self {
Self(libc::MADV_FREE_REUSABLE)
}
/// **MADV_FREE_REUSE** - Darwin only
///
/// Marks a memory region previously freed by **MADV_FREE_REUSABLE** as non-reusable, accounts
/// for the pages in the RSS of the process. Pages that have been freed will be replaced by
/// zero-filled pages on demand, other pages will be left as is.
///
/// # Safety
///
/// Using the returned value with conceptually write to the
/// mapped pages, i.e. borrowing the mapping while the pages
/// are still being freed results in undefined behaviour.
#[cfg(any(target_os = "macos", target_os = "ios"))]
FreeReuse = libc::MADV_FREE_REUSE,
pub unsafe fn free_reuse() -> Self {
Self(libc::MADV_FREE_REUSE)
}
}
// Future expansion:

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

@ -4,7 +4,7 @@
//! which correspond to mapping a [`File`] to a [`&[u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
//! or [`&mut [u8]`](https://doc.rust-lang.org/std/primitive.slice.html)
//! respectively. Both function by dereferencing to a slice, allowing the
//! [`Mmap`]/[`MmapMut`] to be used in the same way you would the equivelant slice
//! [`Mmap`]/[`MmapMut`] to be used in the same way you would the equivalent slice
//! types.
//!
//! [`File`]: std::fs::File
@ -36,6 +36,8 @@
//! you can use [`MmapOptions`] in order to further configure a mapping
//! before you create it.
#![allow(clippy::len_without_is_empty, clippy::missing_safety_doc)]
#[cfg_attr(unix, path = "unix.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(not(any(unix, windows)), path = "stub.rs")]
@ -482,7 +484,7 @@ impl MmapOptions {
));
}
MmapInner::map_anon(len, self.stack).map(|inner| MmapMut { inner })
MmapInner::map_anon(len, self.stack, self.populate).map(|inner| MmapMut { inner })
}
/// Creates a raw memory map.
@ -497,6 +499,21 @@ impl MmapOptions {
MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate)
.map(|inner| MmapRaw { inner })
}
/// Creates a read-only raw memory map
///
/// This is primarily useful to avoid intermediate `Mmap` instances when
/// read-only access to files modified elsewhere are required.
///
/// # Errors
///
/// This method returns an error when the underlying system call fails
pub fn map_raw_read_only<T: MmapAsRawDesc>(&self, file: T) -> Result<MmapRaw> {
let desc = file.as_raw_desc();
MmapInner::map(self.get_len(&file)?, desc.0, self.offset, self.populate)
.map(|inner| MmapRaw { inner })
}
}
/// A handle to an immutable memory mapped buffer.
@ -514,7 +531,7 @@ impl MmapOptions {
/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
/// the mapped pages into physical memory) though the details of this are platform specific.
///
/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
/// `Mmap` is [`Sync`] and [`Send`].
///
/// ## Safety
///
@ -646,7 +663,7 @@ impl Mmap {
///
/// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
#[cfg(unix)]
pub fn lock(&mut self) -> Result<()> {
pub fn lock(&self) -> Result<()> {
self.inner.lock()
}
@ -654,9 +671,31 @@ impl Mmap {
///
/// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
#[cfg(unix)]
pub fn unlock(&mut self) -> Result<()> {
pub fn unlock(&self) -> Result<()> {
self.inner.unlock()
}
/// Adjust the size of the memory mapping.
///
/// This will try to resize the memory mapping in place. If
/// [`RemapOptions::may_move`] is specified it will move the mapping if it
/// could not resize in place, otherwise it will error.
///
/// Only supported on Linux.
///
/// See the [`mremap(2)`] man page.
///
/// # Safety
///
/// Resizing the memory mapping beyond the end of the mapped file will
/// result in UB should you happen to access memory beyond the end of the
/// file.
///
/// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
#[cfg(target_os = "linux")]
pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
self.inner.remap(new_len, options)
}
}
#[cfg(feature = "stable_deref_trait")]
@ -837,7 +876,7 @@ impl MmapRaw {
///
/// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
#[cfg(unix)]
pub fn lock(&mut self) -> Result<()> {
pub fn lock(&self) -> Result<()> {
self.inner.lock()
}
@ -845,9 +884,31 @@ impl MmapRaw {
///
/// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
#[cfg(unix)]
pub fn unlock(&mut self) -> Result<()> {
pub fn unlock(&self) -> Result<()> {
self.inner.unlock()
}
/// Adjust the size of the memory mapping.
///
/// This will try to resize the memory mapping in place. If
/// [`RemapOptions::may_move`] is specified it will move the mapping if it
/// could not resize in place, otherwise it will error.
///
/// Only supported on Linux.
///
/// See the [`mremap(2)`] man page.
///
/// # Safety
///
/// Resizing the memory mapping beyond the end of the mapped file will
/// result in UB should you happen to access memory beyond the end of the
/// file.
///
/// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
#[cfg(target_os = "linux")]
pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
self.inner.remap(new_len, options)
}
}
impl fmt::Debug for MmapRaw {
@ -887,7 +948,7 @@ impl From<MmapMut> for MmapRaw {
/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping
/// the mapped pages into physical memory) though the details of this are platform specific.
///
/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send).
/// `Mmap` is [`Sync`] and [`Send`].
///
/// See [`Mmap`] for the immutable version.
///
@ -1105,7 +1166,7 @@ impl MmapMut {
///
/// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
#[cfg(unix)]
pub fn lock(&mut self) -> Result<()> {
pub fn lock(&self) -> Result<()> {
self.inner.lock()
}
@ -1113,9 +1174,31 @@ impl MmapMut {
///
/// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
#[cfg(unix)]
pub fn unlock(&mut self) -> Result<()> {
pub fn unlock(&self) -> Result<()> {
self.inner.unlock()
}
/// Adjust the size of the memory mapping.
///
/// This will try to resize the memory mapping in place. If
/// [`RemapOptions::may_move`] is specified it will move the mapping if it
/// could not resize in place, otherwise it will error.
///
/// Only supported on Linux.
///
/// See the [`mremap(2)`] man page.
///
/// # Safety
///
/// Resizing the memory mapping beyond the end of the mapped file will
/// result in UB should you happen to access memory beyond the end of the
/// file.
///
/// [`mremap(2)`]: https://man7.org/linux/man-pages/man2/mremap.2.html
#[cfg(target_os = "linux")]
pub unsafe fn remap(&mut self, new_len: usize, options: RemapOptions) -> Result<()> {
self.inner.remap(new_len, options)
}
}
#[cfg(feature = "stable_deref_trait")]
@ -1160,14 +1243,60 @@ impl fmt::Debug for MmapMut {
}
}
/// Options for [`Mmap::remap`] and [`MmapMut::remap`].
#[derive(Copy, Clone, Default, Debug)]
#[cfg(target_os = "linux")]
pub struct RemapOptions {
may_move: bool,
}
#[cfg(target_os = "linux")]
impl RemapOptions {
/// Creates a mew set of options for resizing a memory map.
pub fn new() -> Self {
Self::default()
}
/// Controls whether the memory map can be moved if it is not possible to
/// resize it in place.
///
/// If false then the memory map is guaranteed to remain at the same
/// address when being resized but attempting to resize will return an
/// error if the new memory map would overlap with something else in the
/// current process' memory.
///
/// By default this is false.
///
/// # `may_move` and `StableDeref`
/// If the `stable_deref_trait` feature is enabled then [`Mmap`] and
/// [`MmapMut`] implement `StableDeref`. `StableDeref` promises that the
/// memory map dereferences to a fixed address, however, calling `remap`
/// with `may_move` set may result in the backing memory of the mapping
/// being moved to a new address. This may cause UB in other code
/// depending on the `StableDeref` guarantees.
pub fn may_move(mut self, may_move: bool) -> Self {
self.may_move = may_move;
self
}
pub(crate) fn into_flags(self) -> libc::c_int {
if self.may_move {
libc::MREMAP_MAYMOVE
} else {
0
}
}
}
#[cfg(test)]
mod test {
extern crate tempfile;
#[cfg(unix)]
use crate::advice::Advice;
use std::fs::OpenOptions;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::mem;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(windows)]
@ -1188,7 +1317,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(expected_len as u64).unwrap();
@ -1221,7 +1350,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(expected_len as u64).unwrap();
@ -1253,12 +1382,14 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
let mmap = unsafe { Mmap::map(&file).unwrap() };
assert!(mmap.is_empty());
assert_eq!(mmap.as_ptr().align_offset(mem::size_of::<usize>()), 0);
let mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
assert!(mmap.is_empty());
assert_eq!(mmap.as_ptr().align_offset(mem::size_of::<usize>()), 0);
}
#[test]
@ -1306,7 +1437,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(128).unwrap();
@ -1330,7 +1461,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(128).unwrap();
let write = b"abc123";
@ -1356,7 +1487,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(128).unwrap();
@ -1392,7 +1523,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(128).unwrap();
@ -1417,10 +1548,10 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
let offset = u32::max_value() as u64 + 2;
let offset = u32::MAX as u64 + 2;
let len = 5432;
file.set_len(offset + len as u64).unwrap();
@ -1482,7 +1613,7 @@ mod test {
let mmap = mmap.make_exec().expect("make_exec");
let jitfn: extern "C" fn() -> u8 = unsafe { std::mem::transmute(mmap.as_ptr()) };
let jitfn: extern "C" fn() -> u8 = unsafe { mem::transmute(mmap.as_ptr()) };
assert_eq!(jitfn(), 0xab);
}
@ -1504,7 +1635,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&tempdir.path().join("jit_x86"))
.open(tempdir.path().join("jit_x86"))
.expect("open");
file.set_len(4096).expect("set_len");
@ -1524,7 +1655,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.expect("open");
file.set_len(256_u64).expect("set_len");
@ -1570,7 +1701,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.expect("open");
file.set_len(256_u64).expect("set_len");
@ -1624,7 +1755,7 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.expect("open");
file.write_all(b"abc123").unwrap();
let mmap = MmapOptions::new().map_raw(&file).unwrap();
@ -1633,6 +1764,22 @@ mod test {
assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
}
#[test]
fn raw_read_only() {
let tempdir = tempfile::tempdir().unwrap();
let path = tempdir.path().join("mmaprawro");
File::create(&path).unwrap().write_all(b"abc123").unwrap();
let mmap = MmapOptions::new()
.map_raw_read_only(&File::open(&path).unwrap())
.unwrap();
assert_eq!(mmap.len(), 6);
assert!(!mmap.as_ptr().is_null());
assert_eq!(unsafe { std::ptr::read(mmap.as_ptr()) }, b'a');
}
/// Something that relies on StableDeref
#[test]
#[cfg(feature = "stable_deref_trait")]
@ -1662,14 +1809,14 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(expected_len as u64).unwrap();
// Test MmapMut::advise
let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
mmap.advise(Advice::Random)
mmap.advise(Advice::random())
.expect("mmap advising should be supported on unix");
let len = mmap.len();
@ -1681,7 +1828,7 @@ mod test {
// check that the mmap is empty
assert_eq!(&zeros[..], &mmap[..]);
mmap.advise_range(Advice::Sequential, 0, mmap.len())
mmap.advise_range(Advice::sequential(), 0, mmap.len())
.expect("mmap advising should be supported on unix");
// write values into the mmap
@ -1693,13 +1840,28 @@ mod test {
// Set advice and Read from the read-only map
let mmap = unsafe { Mmap::map(&file).unwrap() };
mmap.advise(Advice::Random)
mmap.advise(Advice::random())
.expect("mmap advising should be supported on unix");
// read values back
assert_eq!(&incr[..], &mmap[..]);
}
#[test]
#[cfg(target_os = "linux")]
fn advise_writes_unsafely() {
let mut mmap = MmapMut::map_anon(4096).unwrap();
mmap.as_mut().fill(255);
let mmap = mmap.make_read_only().unwrap();
let a = mmap.as_ref()[0];
mmap.advise(unsafe { Advice::dont_need() }).unwrap();
let b = mmap.as_ref()[0];
assert_eq!(a, 255);
assert_eq!(b, 0);
}
/// Returns true if a non-zero amount of memory is locked.
#[cfg(target_os = "linux")]
fn is_locked() -> bool {
@ -1724,11 +1886,11 @@ mod test {
.read(true)
.write(true)
.create(true)
.open(&path)
.open(path)
.unwrap();
file.set_len(128).unwrap();
let mut mmap = unsafe { Mmap::map(&file).unwrap() };
let mmap = unsafe { Mmap::map(&file).unwrap() };
#[cfg(target_os = "linux")]
assert!(!is_locked());
@ -1751,4 +1913,119 @@ mod test {
#[cfg(target_os = "linux")]
assert!(!is_locked());
}
#[test]
#[cfg(target_os = "linux")]
fn remap_grow() {
use crate::RemapOptions;
let initial_len = 128;
let final_len = 2000;
let zeros = vec![0u8; final_len];
let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
let file = tempfile::tempfile().unwrap();
file.set_len(final_len as u64).unwrap();
let mut mmap = unsafe { MmapOptions::new().len(initial_len).map_mut(&file).unwrap() };
assert_eq!(mmap.len(), initial_len);
assert_eq!(&mmap[..], &zeros[..initial_len]);
unsafe {
mmap.remap(final_len, RemapOptions::new().may_move(true))
.unwrap()
};
// The size should have been updated
assert_eq!(mmap.len(), final_len);
// Should still be all zeros
assert_eq!(&mmap[..], &zeros);
// Write out to the whole expanded slice.
mmap.copy_from_slice(&incr);
}
#[test]
#[cfg(target_os = "linux")]
fn remap_shrink() {
use crate::RemapOptions;
let initial_len = 20000;
let final_len = 400;
let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
let file = tempfile::tempfile().unwrap();
file.set_len(initial_len as u64).unwrap();
let mut mmap = unsafe { MmapMut::map_mut(&file).unwrap() };
assert_eq!(mmap.len(), initial_len);
unsafe { mmap.remap(final_len, RemapOptions::new()).unwrap() };
assert_eq!(mmap.len(), final_len);
// Check that the mmap is still writable along the slice length
mmap.copy_from_slice(&incr);
}
#[test]
#[cfg(target_os = "linux")]
#[cfg(target_pointer_width = "32")]
fn remap_len_overflow() {
use crate::RemapOptions;
let file = tempfile::tempfile().unwrap();
file.set_len(1024).unwrap();
let mut mmap = unsafe { MmapOptions::new().len(1024).map(&file).unwrap() };
let res = unsafe { mmap.remap(0x80000000, RemapOptions::new().may_move(true)) };
assert_eq!(
res.unwrap_err().to_string(),
"memory map length overflows isize"
);
assert_eq!(mmap.len(), 1024);
}
#[test]
#[cfg(target_os = "linux")]
fn remap_with_offset() {
use crate::RemapOptions;
let offset = 77;
let initial_len = 128;
let final_len = 2000;
let zeros = vec![0u8; final_len];
let incr: Vec<u8> = (0..final_len).map(|v| v as u8).collect();
let file = tempfile::tempfile().unwrap();
file.set_len(final_len as u64 + offset).unwrap();
let mut mmap = unsafe {
MmapOptions::new()
.len(initial_len)
.offset(offset)
.map_mut(&file)
.unwrap()
};
assert_eq!(mmap.len(), initial_len);
assert_eq!(&mmap[..], &zeros[..initial_len]);
unsafe {
mmap.remap(final_len, RemapOptions::new().may_move(true))
.unwrap()
};
// The size should have been updated
assert_eq!(mmap.len(), final_len);
// Should still be all zeros
assert_eq!(&mmap[..], &zeros);
// Write out to the whole expanded slice.
mmap.copy_from_slice(&incr);
}
}

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

@ -36,7 +36,7 @@ impl MmapInner {
MmapInner::new()
}
pub fn map_anon(_: usize, _: bool) -> io::Result<MmapInner> {
pub fn map_anon(_: usize, _: bool, _: bool) -> io::Result<MmapInner> {
MmapInner::new()
}

176
third_party/rust/memmap2/src/unix.rs поставляемый
Просмотреть файл

@ -28,6 +28,18 @@ const MAP_POPULATE: libc::c_int = libc::MAP_POPULATE;
#[cfg(not(any(target_os = "linux", target_os = "android")))]
const MAP_POPULATE: libc::c_int = 0;
#[cfg(any(
target_os = "android",
all(target_os = "linux", not(target_env = "musl"))
))]
use libc::{mmap64 as mmap, off64_t as off_t};
#[cfg(not(any(
target_os = "android",
all(target_os = "linux", not(target_env = "musl"))
)))]
use libc::{mmap, off_t};
pub struct MmapInner {
ptr: *mut libc::c_void,
len: usize,
@ -36,7 +48,7 @@ pub struct MmapInner {
impl MmapInner {
/// Creates a new `MmapInner`.
///
/// This is a thin wrapper around the `mmap` sytem call.
/// This is a thin wrapper around the `mmap` system call.
fn new(
len: usize,
prot: libc::c_int,
@ -46,7 +58,48 @@ impl MmapInner {
) -> io::Result<MmapInner> {
let alignment = offset % page_size() as u64;
let aligned_offset = offset - alignment;
let aligned_len = len + alignment as usize;
let (map_len, map_offset) = Self::adjust_mmap_params(len, alignment as usize)?;
unsafe {
let ptr = mmap(
ptr::null_mut(),
map_len as libc::size_t,
prot,
flags,
file,
aligned_offset as off_t,
);
if ptr == libc::MAP_FAILED {
Err(io::Error::last_os_error())
} else {
Ok(Self::from_raw_parts(ptr, len, map_offset))
}
}
}
fn adjust_mmap_params(len: usize, alignment: usize) -> io::Result<(usize, usize)> {
use std::isize;
// Rust's slice cannot be larger than isize::MAX.
// See https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html
//
// This is not a problem on 64-bit targets, but on 32-bit one
// having a file or an anonymous mapping larger than 2GB is quite normal
// and we have to prevent it.
//
// The code below is essentially the same as in Rust's std:
// https://github.com/rust-lang/rust/blob/db78ab70a88a0a5e89031d7ee4eccec835dcdbde/library/alloc/src/raw_vec.rs#L495
if std::mem::size_of::<usize>() < 8 && len > isize::MAX as usize {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"memory map length overflows isize",
));
}
let map_len = len + alignment;
let map_offset = alignment;
// `libc::mmap` does not support zero-size mappings. POSIX defines:
//
@ -54,7 +107,7 @@ impl MmapInner {
// > If `len` is zero, `mmap()` shall fail and no mapping shall be established.
//
// So if we would create such a mapping, crate a one-byte mapping instead:
let aligned_len = aligned_len.max(1);
let map_len = map_len.max(1);
// Note that in that case `MmapInner::len` is still set to zero,
// and `Mmap` will still dereferences to an empty slice.
@ -79,25 +132,73 @@ impl MmapInner {
//
// (SIGBUS is still possible by mapping a non-empty file and then truncating it
// to a shorter size, but that is unrelated to this handling of empty files.)
Ok((map_len, map_offset))
}
unsafe {
let ptr = libc::mmap(
ptr::null_mut(),
aligned_len as libc::size_t,
prot,
flags,
file,
aligned_offset as libc::off_t,
);
/// Get the current memory mapping as a `(ptr, map_len, offset)` tuple.
///
/// Note that `map_len` is the length of the memory mapping itself and
/// _not_ the one that would be passed to `from_raw_parts`.
fn as_mmap_params(&self) -> (*mut libc::c_void, usize, usize) {
let offset = self.ptr as usize % page_size();
let len = self.len + offset;
if ptr == libc::MAP_FAILED {
Err(io::Error::last_os_error())
} else {
Ok(MmapInner {
ptr: ptr.offset(alignment as isize),
len,
})
}
// There are two possible memory layouts we could have, depending on
// the length and offset passed when constructing this instance:
//
// 1. The "normal" memory layout looks like this:
//
// |<------------------>|<---------------------->|
// mmap ptr offset ptr public slice
//
// That is, we have
// - The start of the page-aligned memory mapping returned by mmap,
// followed by,
// - Some number of bytes that are memory mapped but ignored since
// they are before the byte offset requested by the user, followed
// by,
// - The actual memory mapped slice requested by the user.
//
// This maps cleanly to a (ptr, len, offset) tuple.
//
// 2. Then, we have the case where the user requested a zero-length
// memory mapping. mmap(2) does not support zero-length mappings so
// this crate works around that by actually making a mapping of
// length one. This means that we have
// - A length zero slice, followed by,
// - A single memory mapped byte
//
// Note that this only happens if the offset within the page is also
// zero. Otherwise, we have a memory map of offset bytes and not a
// zero-length memory map.
//
// This doesn't fit cleanly into a (ptr, len, offset) tuple. Instead,
// we fudge it slightly: a zero-length memory map turns into a
// mapping of length one and can't be told apart outside of this
// method without knowing the original length.
if len == 0 {
(self.ptr, 1, 0)
} else {
(unsafe { self.ptr.offset(-(offset as isize)) }, len, offset)
}
}
/// Construct this `MmapInner` from its raw components
///
/// # Safety
///
/// - `ptr` must point to the start of memory mapping that can be freed
/// using `munmap(2)` (i.e. returned by `mmap(2)` or `mremap(2)`)
/// - The memory mapping at `ptr` must have a length of `len + offset`.
/// - If `len + offset == 0` then the memory mapping must be of length 1.
/// - `offset` must be less than the current page size.
unsafe fn from_raw_parts(ptr: *mut libc::c_void, len: usize, offset: usize) -> Self {
debug_assert_eq!(ptr as usize % page_size(), 0, "ptr not page-aligned");
debug_assert!(offset < page_size(), "offset larger than page size");
Self {
ptr: ptr.add(offset),
len,
}
}
@ -162,12 +263,13 @@ impl MmapInner {
}
/// Open an anonymous memory map.
pub fn map_anon(len: usize, stack: bool) -> io::Result<MmapInner> {
pub fn map_anon(len: usize, stack: bool, populate: bool) -> io::Result<MmapInner> {
let stack = if stack { MAP_STACK } else { 0 };
let populate = if populate { MAP_POPULATE } else { 0 };
MmapInner::new(
len,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANON | stack,
libc::MAP_PRIVATE | libc::MAP_ANON | stack | populate,
-1,
0,
)
@ -245,7 +347,7 @@ impl MmapInner {
let offset = offset as isize - alignment as isize;
let len = len + alignment;
unsafe {
if libc::madvise(self.ptr.offset(offset), len, advice as i32) != 0 {
if libc::madvise(self.ptr.offset(offset), len, advice.0) != 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
@ -253,6 +355,24 @@ impl MmapInner {
}
}
#[cfg(target_os = "linux")]
pub fn remap(&mut self, new_len: usize, options: crate::RemapOptions) -> io::Result<()> {
let (old_ptr, old_len, offset) = self.as_mmap_params();
let (map_len, offset) = Self::adjust_mmap_params(new_len, offset)?;
unsafe {
let new_ptr = libc::mremap(old_ptr, old_len, map_len, options.into_flags());
if new_ptr == libc::MAP_FAILED {
Err(io::Error::last_os_error())
} else {
// We explicitly don't drop self since the pointer within is no longer valid.
ptr::write(self, Self::from_raw_parts(new_ptr, new_len, offset));
Ok(())
}
}
}
pub fn lock(&self) -> io::Result<()> {
unsafe {
if libc::mlock(self.ptr, self.len) != 0 {
@ -276,16 +396,12 @@ impl MmapInner {
impl Drop for MmapInner {
fn drop(&mut self) {
let alignment = self.ptr as usize % page_size();
let len = self.len + alignment;
let len = len.max(1);
let (ptr, len, _) = self.as_mmap_params();
// Any errors during unmapping/closing are ignored as the only way
// to report them would be through panicking which is highly discouraged
// in Drop impls, c.f. https://github.com/rust-lang/lang-team/issues/97
unsafe {
let ptr = self.ptr.offset(-(alignment as isize));
libc::munmap(ptr, len as libc::size_t);
}
unsafe { libc::munmap(ptr, len as libc::size_t) };
}
}

9
third_party/rust/memmap2/src/windows.rs поставляемый
Просмотреть файл

@ -132,9 +132,12 @@ extern "system" {
fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
}
/// Returns a fixed pointer that is valid for `slice::from_raw_parts::<u8>` with `len == 0`.
/// Returns a fixed aligned pointer that is valid for `slice::from_raw_parts::<u8>` with `len == 0`.
///
/// This aligns the pointer to `allocation_granularity()` or 1 if unknown.
fn empty_slice_ptr() -> *mut c_void {
std::ptr::NonNull::<u8>::dangling().cast().as_ptr()
let align = allocation_granularity().max(1);
unsafe { mem::transmute(align) }
}
pub struct MmapInner {
@ -340,7 +343,7 @@ impl MmapInner {
Ok(inner)
}
pub fn map_anon(len: usize, _stack: bool) -> io::Result<MmapInner> {
pub fn map_anon(len: usize, _stack: bool, _populate: bool) -> io::Result<MmapInner> {
// Ensure a non-zero length for the underlying mapping
let mapped_len = len.max(1);
unsafe {

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

@ -1 +1 @@
{"files":{"Cargo.toml":"d7167fc703ca78f2b972d2c369ffec203e3d60af75a9748fc7a43772be77cb1c","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"02ac6427f376e6f587c1f3e4d5df2a72e4cf13c4858409e73f26d47ad8e54340","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"716365680d5265688687d8986b2d8485165f86543d874ca332cba803d1884d64","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"17e8777b05998a8149fc5168af3bca1e0f9aeffe28cb3d6dbfb89c546f75e5ed"},"package":null}
{"files":{"Cargo.toml":"e0f49679fe070718b42d9e9bed49860a29471f6e2854a501dceba286301888b1","LICENSE":"06de63df29199a394442b57a28e886059ddc940973e10646877a0793fd53e2c9","README.md":"4c2a1448aab9177fd5f033faaf704af7bb222bf0804079fd3cff90fa1df4b812","src/errors/linux.rs":"df743ac9478e39f8a577f4f10f2d1317babad7b7c0d26cdbba2ea6b5426f4126","src/errors/macos.rs":"02ac6427f376e6f587c1f3e4d5df2a72e4cf13c4858409e73f26d47ad8e54340","src/errors/mod.rs":"f224af66124fd31a040c8da11bbab7b7795b48e4edea76e01c1f4dee537ea38a","src/errors/windows.rs":"0567af7bfac3ae2a8dff418e10873d8a5bf15a8b8ac6892c5ffdab08ec3ac901","src/format.rs":"f453ada36ffcb986a62391f9451b7826bdde9d5024beb11a495d1ed1e93bb52c","src/lib.rs":"0900c00594b3c386b86127055889006f0d7d0004b08455fadb0e60d55a469cab","src/traits.rs":"93127ad69a849325ed66a0626e0bdae05868488f81c539d35c71a7bfbb9e51ac","src/utils.rs":"17e8777b05998a8149fc5168af3bca1e0f9aeffe28cb3d6dbfb89c546f75e5ed"},"package":"3dbc11dfb55b3b7b5684fb16d98e0fc9d1e93a64d6b00bf383eabfc4541aaac2"}

29
third_party/rust/minidump-common/Cargo.toml поставляемый
Просмотреть файл

@ -12,30 +12,41 @@
[package]
edition = "2018"
name = "minidump-common"
version = "0.17.0"
version = "0.19.1"
authors = ["Ted Mielczarek <ted@mielczarek.org>"]
description = "Some common types for working with minidump files."
homepage = "https://github.com/rust-minidump/rust-minidump"
readme = "README.md"
license = "MIT"
repository = "https://github.com/rust-minidump/rust-minidump"
[dependencies]
bitflags = "1.3.2"
debugid = "0.8.0"
num-derive = "0.4"
num-traits = "0.2"
range-map = "0.2"
smart-default = "0.7.0"
resolver = "2"
[dependencies.arbitrary]
version = "1"
features = ["derive"]
optional = true
[dependencies.bitflags]
version = "2"
[dependencies.debugid]
version = "0.8.0"
[dependencies.num-derive]
version = "0.4"
[dependencies.num-traits]
version = "0.2"
[dependencies.range-map]
version = "0.2"
[dependencies.scroll]
version = "0.11.0"
features = ["derive"]
[dependencies.smart-default]
version = "0.7.0"
[badges.travis-ci]
repository = "rust-minidump/rust-minidump"

104
third_party/rust/minidump-common/src/format.rs поставляемый
Просмотреть файл

@ -209,6 +209,9 @@ pub enum MINIDUMP_STREAM_TYPE {
Memory64ListStream = 9,
CommentStreamA = 10,
CommentStreamW = 11,
/// The list of handles used by the process
///
/// See [`MINIDUMP_HANDLE_DATA_STREAM`]
HandleDataStream = 12,
FunctionTable = 13,
/// The list of executable modules from the process that were unloaded by the time of the crash
@ -317,6 +320,9 @@ pub enum MINIDUMP_STREAM_TYPE {
///
/// See ['MINIDUMP_MAC_BOOTARGS']
MozMacosBootargsStream = 0x4d7a0002,
/// The contents of /proc/self/limits from a Linux system
MozLinuxLimits = 0x4d7a0003,
}
impl From<MINIDUMP_STREAM_TYPE> for u32 {
@ -775,6 +781,7 @@ bitflags! {
/// This applies to the [`CONTEXT_ARM`], [`CONTEXT_PPC`], [`CONTEXT_MIPS`],
/// [`CONTEXT_AMD64`], [`CONTEXT_ARM64`], [`CONTEXT_PPC64`], [`CONTEXT_SPARC`] and
/// [`CONTEXT_ARM64_OLD`] structs.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsCpu: u32 {
const CONTEXT_IA64 = 0x80000;
/// Super-H, includes SH3, from winnt.h in the Windows CE 5.0 SDK
@ -808,6 +815,7 @@ impl ContextFlagsCpu {
bitflags! {
/// Flags available for use in [`CONTEXT_AMD64.context_flags`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsAmd64: u32 {
/// SegSs, Rsp, SegCs, Rip, and EFlags
const CONTEXT_AMD64_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_AMD64.bits();
@ -827,6 +835,7 @@ bitflags! {
bitflags! {
/// Flags available for use in [`CONTEXT_X86.context_flags`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsX86: u32 {
/// Ebp, Eip, SegCs, EFlags, Esp, SegSs
const CONTEXT_X86_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_X86.bits();
@ -847,6 +856,7 @@ bitflags! {
bitflags! {
/// Flags available for use in [`CONTEXT_ARM64.context_flags`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsArm64: u32 {
/// FP, LR, SP, PC, and CPSR
const CONTEXT_ARM64_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_ARM64.bits();
@ -867,6 +877,7 @@ bitflags! {
bitflags! {
/// Flags available for use in [`CONTEXT_ARM64_OLD.context_flags`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsArm64Old: u32 {
// Yes, breakpad never defined CONTROL for this context
@ -881,6 +892,7 @@ bitflags! {
bitflags! {
/// Flags available for use in [`CONTEXT_ARM.context_flags`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContextFlagsArm: u32 {
// Yes, breakpad never defined CONTROL for this context
@ -1801,6 +1813,7 @@ impl From<u8> for XSTATE_FEATURE {
bitflags! {
/// Known flags for `MINIDUMP_MISC_INFO*.flags1`
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MiscInfoFlags: u32 {
const MINIDUMP_MISC1_PROCESS_ID = 0x00000001;
const MINIDUMP_MISC1_PROCESS_TIMES = 0x00000002;
@ -1867,6 +1880,7 @@ pub struct MINIDUMP_MEMORY_INFO {
bitflags! {
/// Potential values for [`MINIDUMP_MEMORY_INFO::state`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryState: u32 {
const MEM_COMMIT = 0x01000;
const MEM_FREE = 0x10000;
@ -1880,6 +1894,7 @@ bitflags! {
/// See [Microsoft's documentation][msdn] for details.
///
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/Memory/memory-protection-constants
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryProtection: u32 {
const PAGE_NOACCESS = 0x01;
const PAGE_READONLY = 0x02;
@ -1898,6 +1913,7 @@ bitflags! {
bitflags! {
/// Potential values for [`MINIDUMP_MEMORY_INFO::_type`]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryType: u32 {
const MEM_PRIVATE = 0x00020000;
const MEM_MAPPED = 0x00040000;
@ -2422,6 +2438,7 @@ bitflags! {
/// This matches the Linux kernel definitions from [<asm/hwcaps.h>][hwcap].
///
/// [hwcap]: https://elixir.bootlin.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArmElfHwCaps: u32 {
const HWCAP_SWP = (1 << 0);
const HWCAP_HALF = (1 << 1);
@ -2448,3 +2465,90 @@ bitflags! {
const HWCAP_EVTSTRM = (1 << 21);
}
}
#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
pub enum MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE {
MiniHandleObjectInformationNone,
MiniThreadInformation1,
MiniMutantInformation1,
MiniMutantInformation2,
MiniProcessInformation1,
MiniProcessInformation2,
MiniEventInformation1,
MiniSectionInformation1,
MiniSemaphoreInformation1,
MiniHandleObjectInformationTypeMax,
}
/// OS-specific handle object information. Microsoft headers state that it can
/// change based on the target platform. The object is larger than this structure
/// (as specified by `size_of_info`) and the remaining data is stored after the
/// `size_of_info` field. The format of this information is not specified.
#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
pub struct MINIDUMP_HANDLE_OBJECT_INFORMATION {
/// RVA pointing to the next handle object information. Elements of this type
/// are chained and the last one has this field set to 0.
pub next_info_rva: RVA,
/// Type of this handle object information element, see [`MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE`]
pub info_type: u32,
/// Size of this element, this must be larger than `size_of::<MINIDUMP_HANDLE_OBJECT_INFORMATION>()`
pub size_of_info: u32,
}
#[derive(Debug, Default, Clone, Pread, Pwrite, SizeWith)]
pub struct MINIDUMP_HANDLE_DESCRIPTOR {
/// The operating system handle value. A HANDLE on Windows and file descriptor number on Linux.
pub handle: u64,
/// An RVA to a `MINIDUMP_STRING` structure that specifies the object type of the handle.
/// This member can be zero.
pub type_name_rva: RVA,
/// An RVA to a `MINIDUMP_STRING` structure that specifies the object name of the handle.
/// This member can be zero.
pub object_name_rva: RVA,
/// The meaning of this member depends on the handle type and the operating system.
pub attributes: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub granted_access: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub handle_count: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub pointer_count: u32,
}
#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
pub struct MINIDUMP_HANDLE_DESCRIPTOR_2 {
/// The operating system handle value. A HANDLE on Windows and file descriptor number on Linux.
pub handle: u64,
/// An RVA to a `MINIDUMP_STRING` structure that specifies the object type of the handle.
/// This member can be zero.
pub type_name_rva: RVA,
/// An RVA to a `MINIDUMP_STRING` structure that specifies the object name of the handle.
/// This member can be zero.
pub object_name_rva: RVA,
/// The meaning of this member depends on the handle type and the operating system.
pub attributes: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub granted_access: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub handle_count: u32,
/// The meaning of this member depends on the handle type and the operating system.
pub pointer_count: u32,
/// An RVA to a [`MINIDUMP_HANDLE_OBJECT_INFORMATION`] structure that specifies object-specific information.
/// This member can be 0 if there is no extra information.
pub object_info_rva: RVA,
/// Reserved for future use; must be zero.
reserved0: u32,
}
#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
pub struct MINIDUMP_HANDLE_DATA_STREAM {
/// The size of this header, in bytes.
pub size_of_header: u32,
/// The size of each descriptor in the stream, in bytes.
pub size_of_descriptor: u32,
/// The number of descriptors in the stream.
pub number_of_descriptors: u32,
/// Reserved for future use; must be zero.
pub reserved: u32,
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -1 +0,0 @@
* @Jake-Shadle

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

@ -1,22 +0,0 @@
name: Security audit
on:
schedule:
# Runs at 00:00 UTC everyday
- cron: "0 0 * * *"
push:
paths:
- "**/Cargo.toml"
- "**/Cargo.lock"
- "**/audit.toml"
jobs:
audit:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: deny audit
uses: EmbarkStudios/cargo-deny-action@v1
with:
command: check advisories

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

@ -1,86 +0,0 @@
name: Continuous Integration
on:
push:
branches:
- main
- github-actions
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt,clippy
- name: rustfmt
run: cargo fmt --all -- --check
- name: clippy
run: cargo clippy --all-features --all-targets -- -D warnings
test:
name: Test
runs-on: ${{ matrix.job.os }}
strategy:
matrix:
job:
- { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-22.04, target: x86_64-unknown-linux-musl }
- { os: windows-2022, target: x86_64-pc-windows-msvc }
- { os: macos-12, target: x86_64-apple-darwin }
# TODO: Add macos aarch64 here once it becomes available as a runner
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
target: ${{ matrix.job.target }}
- name: Fetch
run: cargo fetch --target ${{ matrix.job.target }}
- name: Build
run: cargo test --target ${{ matrix.job.target }} --no-run
- name: Test
run: cargo test --target ${{ matrix.job.target }}
# This job builds non-tier1 targets that aren't already tested
build_lower_tier:
name: Build sources
runs-on: ${{ matrix.job.os }}
strategy:
matrix:
job:
- { os: ubuntu-22.04, target: i686-unknown-linux-gnu, use-cross: true }
#- { os: ubuntu-latest, target: i686-unknown-linux-musl, use-cross: true }
- { os: ubuntu-22.04, target: aarch64-unknown-linux-gnu, use-cross: true }
- { os: ubuntu-22.04, target: aarch64-unknown-linux-musl, use-cross: true }
#- { os: ubuntu-22.04, target: aarch64-linux-android, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-gnueabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-musleabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-linux-androideabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-gnueabihf, use-cross: true }
# TODO: Remove this when aarch64 macs can be used as runners
- { os: macos-12, target: aarch64-apple-darwin, use-cross: false }
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
target: ${{ matrix.job.target }}
#- name: Unit tests
- name: Build
uses: actions-rs/cargo@v1
with:
#command: test
command: build
use-cross: ${{ matrix.job.use-cross }}
args: --target ${{ matrix.job.target }} --verbose --all-targets
#args: --target ${{ matrix.job.target }} --verbose -- --nocapture

23
third_party/rust/minidump-writer/CHANGELOG.md поставляемый
Просмотреть файл

@ -8,6 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header -->
## [Unreleased] - ReleaseDate
## [0.8.3] - 2023-11-07
### Added
- [PR#94](https://github.com/rust-minidump/minidump-writer/pull/94) added support for writing [file information](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_handle_descriptor) for every file open in the process the dump is being performed for into the [`MINIDUMP_HANDLE_DATA_STREAM`](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_handle_data_stream) stream.
- [PR#90](https://github.com/rust-minidump/minidump-writer/pull/90) added support for including the `/proc/<pid>/limits` file in the [`MozLinuxLimits`](https://docs.rs/minidump-common/latest/minidump_common/format/enum.MINIDUMP_STREAM_TYPE.html#variant.MozLinuxLimits) stream. This information can be used together with the file information described above to diagnose situations where the process was killed by the kernel due to file handle limits being hit. Thanks [@lissyx](https://github.com/lissyx)!
### Changed
- [PR#94](https://github.com/rust-minidump/minidump-writer/pull/94) updated several dependencies to align with `minidump-common`, which was also bumped.
## [0.8.2] - 2023-09-21
### Added
- [PR#86](https://github.com/rust-minidump/minidump-writer/pull/86) added support for `i686-android-linux`.
### Fixed
- [PR#85](https://github.com/rust-minidump/minidump-writer/pull/85) removed the dependency on `chrono`.
- [PR#89](https://github.com/rust-minidump/minidump-writer/pull/89) resolved [#88](https://github.com/rust-minidump/minidump-writer/issues/88) by merging ranges that were mapped, but had 1 or more unmapped ranges in between them.
### Changed
- [PR#87](https://github.com/rust-minidump/minidump-writer/pull/87) updated some dependencies.
## [0.8.1] - 2023-06-21
### Added
- [PR#70](https://github.com/rust-minidump/minidump-writer/pull/70) resolved [#8](https://github.com/rust-minidump/minidump-writer/issues/8) by adding support for writing `MemoryInfoListStream` on Linux/Android targets, this allows minidump consumers to process minidumps more easily without needing to parse and understand Linux-specific information. Thanks [@afranchuk](https://github.com/afranchuk)!
@ -84,7 +103,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial release, including basic support for `x86_64-unknown-linux-gnu/musl` and `x86_64-pc-windows-msvc`
<!-- next-url -->
[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.8.1...HEAD
[Unreleased]: https://github.com/rust-minidump/minidump-writer/compare/0.8.3...HEAD
[0.8.3]: https://github.com/rust-minidump/minidump-writer/compare/0.8.2...0.8.3
[0.8.2]: https://github.com/rust-minidump/minidump-writer/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/rust-minidump/minidump-writer/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/rust-minidump/minidump-writer/compare/0.7.0...0.8.0
[0.7.0]: https://github.com/rust-minidump/minidump-writer/compare/0.6.0...0.7.0

1851
third_party/rust/minidump-writer/Cargo.lock сгенерированный поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

86
third_party/rust/minidump-writer/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "minidump-writer"
version = "0.8.1"
version = "0.8.3"
authors = ["Martin Sirringhaus"]
description = "Rust rewrite of Breakpad's minidump_writer"
homepage = "https://github.com/rust-minidump/minidump-writer"
@ -20,27 +20,45 @@ readme = "README.md"
license = "MIT"
repository = "https://github.com/rust-minidump/minidump-writer"
[dependencies]
bitflags = "2.0"
byteorder = "1.3.2"
cfg-if = "1.0"
crash-context = "0.6.1"
memoffset = "0.9"
minidump-common = "0.17.0"
scroll = "0.11"
tempfile = "3.1.0"
thiserror = "1.0.21"
[dependencies.bitflags]
version = "2.4"
[dev-dependencies]
memmap2 = "0.5"
minidump = "0.17.0"
[dependencies.byteorder]
version = "1.4"
[dependencies.cfg-if]
version = "1.0"
[dependencies.crash-context]
version = "0.6"
[dependencies.memoffset]
version = "0.9"
[dependencies.minidump-common]
version = "0.19.1"
[dependencies.scroll]
version = "0.11"
[dependencies.tempfile]
version = "3.8"
[dependencies.thiserror]
version = "1.0"
[dev-dependencies.futures]
version = "0.3"
features = ["executor"]
[dev-dependencies.memmap2]
version = "0.8"
[dev-dependencies.minidump]
version = "0.19"
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.nix]
version = "0.26"
version = "0.27"
features = [
"mman",
"process",
@ -50,32 +68,38 @@ features = [
default-features = false
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.procfs-core]
version = "0.16.0-RC1"
version = "0.16"
default-features = false
[target."cfg(target_os = \"macos\")".dependencies]
mach2 = "0.4"
[target."cfg(target_os = \"macos\")".dev-dependencies]
similar-asserts = "1.2"
uuid = "1.0"
[target."cfg(target_os = \"macos\")".dependencies.mach2]
version = "0.4"
[target."cfg(target_os = \"macos\")".dev-dependencies.dump_syms]
version = "2.0.0"
version = "2.2"
default-features = false
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-processor]
version = "0.17.0"
version = "0.19"
default-features = false
[target."cfg(target_os = \"macos\")".dev-dependencies.minidump-unwind]
version = "0.17"
version = "0.19"
features = ["debuginfo"]
[target."cfg(target_os = \"windows\")".dependencies]
bitflags = "2.0"
[target."cfg(target_os = \"macos\")".dev-dependencies.similar-asserts]
version = "1.5"
[target."cfg(unix)".dependencies]
goblin = "0.7"
libc = "0.2.74"
memmap2 = "0.5"
[target."cfg(target_os = \"macos\")".dev-dependencies.uuid]
version = "1.4"
[target."cfg(target_os = \"windows\")".dependencies.bitflags]
version = "2.4"
[target."cfg(unix)".dependencies.goblin]
version = "0.7.1"
[target."cfg(unix)".dependencies.libc]
version = "0.2"
[target."cfg(unix)".dependencies.memmap2]
version = "0.8"

21
third_party/rust/minidump-writer/deny.toml поставляемый
Просмотреть файл

@ -1,2 +1,23 @@
targets = [
{ triple = "x86_64-unknown-linux-gnu" },
{ triple = "x86_64-unknown-linux-musl" },
{ triple = "x86_64-pc-windows-msvc" },
{ triple = "x86_64-apple-darwin" },
{ triple = "aarch64-apple-darwin" },
{ triple = "aarch64-linux-android" },
{ triple = "x86_64-linux-android" },
]
[advisories]
ignore = []
[bans]
multiple-versions = "deny"
skip = [
# scroll still depends on 1.0
{ name = "syn", version = "=1.0.109" },
]
[licenses]
allow = ["MIT", "Apache-2.0"]
exceptions = [{ allow = ["Unicode-DFS-2016"], name = "unicode-ident" }]

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

@ -15,6 +15,7 @@ mod linux {
sys::mman::{mmap, MapFlags, ProtFlags},
unistd::getppid,
};
use std::os::fd::BorrowedFd;
macro_rules! test {
($x:expr, $errmsg:expr) => {
@ -214,12 +215,12 @@ mod linux {
let memory_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
// Get some memory to be mapped by the child-process
let mapped_mem = unsafe {
mmap(
mmap::<BorrowedFd>(
None,
memory_size,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANON,
-1,
None,
0,
)
.unwrap()
@ -246,6 +247,26 @@ mod linux {
}
}
fn create_files_wait(num: usize) -> Result<()> {
let mut file_array = Vec::<tempfile::NamedTempFile>::with_capacity(num);
for id in 0..num {
let file = tempfile::Builder::new()
.prefix("test_file")
.suffix::<str>(id.to_string().as_ref())
.tempfile()
.unwrap();
file_array.push(file);
println!("1");
}
println!("1");
loop {
std::thread::park();
// This shouldn't be executed, but we put it here to ensure that
// all the files within the array are kept open.
println!("{}", file_array.len());
}
}
pub(super) fn real_main(args: Vec<String>) -> Result<()> {
match args.len() {
1 => match args[0].as_ref() {
@ -267,6 +288,10 @@ mod linux {
let num_of_threads: usize = args[1].parse().unwrap();
spawn_name_wait(num_of_threads)
}
"create_files_wait" => {
let num_of_files: usize = args[1].parse().unwrap();
create_files_wait(num_of_files)
}
_ => Err(format!("Len 2: Unknown test option: {}", args[0]).into()),
},
3 => {

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

@ -142,6 +142,16 @@ pub enum SectionExceptionStreamError {
MemoryWriterError(#[from] MemoryWriterError),
}
#[derive(Debug, Error)]
pub enum SectionHandleDataStreamError {
#[error("Failed to access file")]
IOError(#[from] std::io::Error),
#[error("Failed to write to memory")]
MemoryWriterError(#[from] MemoryWriterError),
#[error("Failed integer conversion")]
TryFromIntError(#[from] std::num::TryFromIntError),
}
#[derive(Debug, Error)]
pub enum SectionMappingsError {
#[error("Failed to write to memory")]
@ -218,6 +228,8 @@ pub enum WriterError {
SectionAppMemoryError(#[from] SectionAppMemoryError),
#[error("Failed when writing section ExceptionStream")]
SectionExceptionStreamError(#[from] SectionExceptionStreamError),
#[error("Failed when writing section HandleDataStream")]
SectionHandleDataStreamError(#[from] SectionHandleDataStreamError),
#[error("Failed when writing section MappingsError")]
SectionMappingsError(#[from] SectionMappingsError),
#[error("Failed when writing section MemList")]

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

@ -189,7 +189,7 @@ impl MinidumpWriter {
) -> Result<()> {
// A minidump file contains a number of tagged streams. This is the number
// of streams which we write.
let num_writers = 15u32;
let num_writers = 17u32;
let mut header_section = MemoryWriter::<MDRawHeader>::alloc(buffer)?;
@ -323,10 +323,26 @@ impl MinidumpWriter {
// Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/limits", self.blamed_thread))
{
Ok(location) => MDRawDirectory {
stream_type: MDStreamType::MozLinuxLimits as u32,
location,
},
Err(_) => Default::default(),
};
// Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = thread_names_stream::write(buffer, dumper)?;
// Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
// This section is optional, so we ignore errors when writing it
if let Ok(dirent) = handle_data_stream::write(self, buffer) {
let _ = dir_section.write_to_file(buffer, Some(dirent));
}
// If you add more directory entries, don't forget to update num_writers, above.
Ok(())
}

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

@ -1,5 +1,6 @@
pub mod app_memory;
pub mod exception_stream;
pub mod handle_data_stream;
pub mod mappings;
pub mod memory_info_list_stream;
pub mod memory_list_stream;

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

@ -0,0 +1,84 @@
use std::{
ffi::{CString, OsString},
fs::{self, DirEntry},
mem::{self},
os::unix::prelude::OsStrExt,
path::{Path, PathBuf},
};
use crate::mem_writer::MemoryWriter;
use super::*;
fn file_stat(path: &Path) -> Option<libc::stat> {
let c_path = CString::new(path.as_os_str().as_bytes()).ok()?;
let mut stat = unsafe { std::mem::zeroed::<libc::stat>() };
let result = unsafe { libc::stat(c_path.as_ptr(), &mut stat) };
if result == 0 {
Some(stat)
} else {
None
}
}
fn direntry_to_descriptor(buffer: &mut DumpBuf, entry: &DirEntry) -> Option<MDRawHandleDescriptor> {
let handle = filename_to_fd(&entry.file_name())?;
let realpath = fs::read_link(entry.path()).ok()?;
let path_rva = write_string_to_location(buffer, realpath.to_string_lossy().as_ref()).ok()?;
let stat = file_stat(&entry.path())?;
// TODO: We store the contents of `st_mode` into the `attributes` field, but
// we could also store a human-readable string of the file type inside
// `type_name_rva`. We might move this missing information (and
// more) inside a custom `MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE` blob.
// That would make this conversion loss-less.
Some(MDRawHandleDescriptor {
handle,
type_name_rva: 0,
object_name_rva: path_rva.rva,
attributes: stat.st_mode,
granted_access: 0,
handle_count: 0,
pointer_count: 0,
})
}
fn filename_to_fd(filename: &OsString) -> Option<u64> {
let filename = filename.to_string_lossy();
filename.parse::<u64>().ok()
}
pub fn write(
config: &mut MinidumpWriter,
buffer: &mut DumpBuf,
) -> Result<MDRawDirectory, errors::SectionHandleDataStreamError> {
let proc_fd_path = PathBuf::from(format!("/proc/{}/fd", config.process_id));
let proc_fd_iter = fs::read_dir(proc_fd_path)?;
let descriptors: Vec<_> = proc_fd_iter
.filter_map(|entry| entry.ok())
.filter_map(|entry| direntry_to_descriptor(buffer, &entry))
.collect();
let number_of_descriptors = descriptors.len() as u32;
let stream_header = MemoryWriter::<MDRawHandleDataStream>::alloc_with_val(
buffer,
MDRawHandleDataStream {
size_of_header: mem::size_of::<MDRawHandleDataStream>() as u32,
size_of_descriptor: mem::size_of::<MDRawHandleDescriptor>() as u32,
number_of_descriptors,
reserved: 0,
},
)?;
let mut dirent = MDRawDirectory {
stream_type: MDStreamType::HandleDataStream as u32,
location: stream_header.location(),
};
let descriptor_list =
MemoryArrayWriter::<MDRawHandleDescriptor>::alloc_from_iter(buffer, descriptors)?;
dirent.location.data_size += descriptor_list.location().data_size;
Ok(dirent)
}

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

@ -2,7 +2,9 @@ pub use minidump_common::format::{
self, ArmElfHwCaps as MDCPUInformationARMElfHwCaps, PlatformId,
ProcessorArchitecture as MDCPUArchitecture, GUID, MINIDUMP_DIRECTORY as MDRawDirectory,
MINIDUMP_EXCEPTION as MDException, MINIDUMP_EXCEPTION_STREAM as MDRawExceptionStream,
MINIDUMP_HEADER as MDRawHeader, MINIDUMP_LOCATION_DESCRIPTOR as MDLocationDescriptor,
MINIDUMP_HANDLE_DATA_STREAM as MDRawHandleDataStream,
MINIDUMP_HANDLE_DESCRIPTOR as MDRawHandleDescriptor, MINIDUMP_HEADER as MDRawHeader,
MINIDUMP_LOCATION_DESCRIPTOR as MDLocationDescriptor,
MINIDUMP_MEMORY_DESCRIPTOR as MDMemoryDescriptor, MINIDUMP_MEMORY_INFO as MDMemoryInfo,
MINIDUMP_MEMORY_INFO_LIST as MDMemoryInfoList, MINIDUMP_MODULE as MDRawModule,
MINIDUMP_SIGNATURE as MD_HEADER_SIGNATURE, MINIDUMP_STREAM_TYPE as MDStreamType,

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

@ -58,6 +58,11 @@ pub fn start_child_and_wait_for_named_threads(num: usize) -> Child {
start_child_and_wait_for_threads_helper("spawn_name_wait", num)
}
#[allow(unused)]
pub fn start_child_and_wait_for_create_files(num: usize) -> Child {
start_child_and_wait_for_threads_helper("create_files_wait", num)
}
#[allow(unused)]
pub fn wait_for_threads(child: &mut Child, num: usize) {
let mut f = BufReader::new(child.stdout.as_mut().expect("Can't open stdout"));

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

@ -224,6 +224,9 @@ contextual_tests! {
let _ = dump
.get_raw_stream(LinuxDsoDebug as u32)
.expect("Couldn't find LinuxDsoDebug");
let _ = dump
.get_raw_stream(MozLinuxLimits as u32)
.expect("Couldn't find MozLinuxLimits");
}
fn test_write_with_additional_memory(context: Context) {
@ -473,6 +476,46 @@ contextual_tests! {
expected.insert(format!("thread_{}", id));
}
assert_eq!(expected, names);
}
fn test_file_descriptors(context: Context) {
let num_of_files = 5;
let mut child = start_child_and_wait_for_create_files(num_of_files);
let pid = child.id() as i32;
let mut tmpfile = tempfile::Builder::new()
.prefix("testfiles")
.tempfile()
.unwrap();
let mut tmp = context.minidump_writer(pid);
let _ = tmp.dump(&mut tmpfile).expect("Could not write minidump");
child.kill().expect("Failed to kill process");
// Reap child
let waitres = child.wait().expect("Failed to wait for child");
let status = waitres.signal().expect("Child did not die due to signal");
assert_eq!(waitres.code(), None);
assert_eq!(status, Signal::SIGKILL as i32);
// Read dump file and check its contents. There should be a truncated minidump available
let dump = Minidump::read_path(tmpfile.path()).expect("Failed to read minidump");
let fds: MinidumpHandleDataStream = dump.get_stream().expect("Couldn't find MinidumpHandleDataStream");
// We check that we create num_of_files plus stdin, stdout and stderr
for i in 0..2 {
let descriptor = fds.handles.get(i).expect("Descriptor should be present");
let fd = *descriptor.raw.handle().expect("Handle should be populated");
assert_eq!(fd, i as u64);
}
for i in 3..num_of_files {
let descriptor = fds.handles.get(i).expect("Descriptor should be present");
let object_name = descriptor.object_name.as_ref().expect("The path should be populated");
let file_name = object_name.split('/').last().expect("The filename should be present");
assert!(file_name.starts_with("test_file"));
assert!(file_name.ends_with(&(i - 3).to_string()));
}
}
}

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

@ -7,7 +7,7 @@ use nix::sys::signal::Signal;
use std::convert::TryInto;
use std::io::{BufRead, BufReader};
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::AsFd;
use std::os::unix::process::ExitStatusExt;
mod common;
@ -129,7 +129,7 @@ fn test_merged_mappings() {
map_size,
ProtFlags::PROT_READ,
MapFlags::MAP_SHARED,
file.as_raw_fd(),
Some(file.as_fd()),
0,
)
.unwrap()
@ -142,7 +142,7 @@ fn test_merged_mappings() {
page_size,
ProtFlags::PROT_NONE,
MapFlags::MAP_SHARED | MapFlags::MAP_FIXED,
file.as_raw_fd(),
Some(file.as_fd()),
// Map a different offset just to
// better test real-world conditions.
page_size.get().try_into().unwrap(), // try_into() in order to work for 32 and 64 bit

2
third_party/rust/nix/.cargo-checksum.json поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -3,9 +3,120 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
## [0.26.2] - 2023-01-18
## [0.27.1] - 2023-08-28
### Fixed
- Fix `SockaddrIn6` bug that was swapping flowinfo and scope_id byte ordering.
- Fixed generating the documentation on docs.rs.
([#2111](https://github.com/nix-rust/nix/pull/2111))
## [0.27.0] - 2023-08-28
### Added
- Added `AT_EACCESS` to `AtFlags` on all platforms but android
([#1995](https://github.com/nix-rust/nix/pull/1995))
- Add `PF_ROUTE` to `SockType` on macOS, iOS, all of the BSDs, Fuchsia, Haiku, Illumos.
([#1867](https://github.com/nix-rust/nix/pull/1867))
- Added `nix::ucontext` module on `aarch64-unknown-linux-gnu`.
(#[1662](https://github.com/nix-rust/nix/pull/1662))
- Added `CanRaw` to `SockProtocol` and `CanBcm` as a separate `SocProtocol` constant.
([#1912](https://github.com/nix-rust/nix/pull/1912))
- Added `Generic` and `NFLOG` to `SockProtocol`.
([#2092](https://github.com/nix-rust/nix/pull/2092))
- Added `mq_timedreceive` to `::nix::mqueue`.
([#1966])(https://github.com/nix-rust/nix/pull/1966)
- Added `LocalPeerPid` to `nix::sys::socket::sockopt` for macOS. ([#1967](https://github.com/nix-rust/nix/pull/1967))
- Added `TFD_TIMER_CANCEL_ON_SET` to `::nix::sys::time::TimerSetTimeFlags` on Linux and Android.
([#2040](https://github.com/nix-rust/nix/pull/2040))
- Added `SOF_TIMESTAMPING_OPT_ID` and `SOF_TIMESTAMPING_OPT_TSONLY` to `nix::sys::socket::TimestampingFlag`.
([#2048](https://github.com/nix-rust/nix/pull/2048))
- Enabled socket timestamping options on Android. ([#2077](https://github.com/nix-rust/nix/pull/2077))
- Added vsock support for macOS ([#2056](https://github.com/nix-rust/nix/pull/2056))
- Added `SO_SETFIB` and `SO_USER_COOKIE` to `nix::sys::socket::sockopt` for FreeBSD.
([#2085](https://github.com/nix-rust/nix/pull/2085))
- Added `SO_RTABLE` for OpenBSD and `SO_ACCEPTFILTER` for FreeBSD/NetBSD to `nix::sys::socket::sockopt`.
([#2085](https://github.com/nix-rust/nix/pull/2085))
- Added `MSG_WAITFORONE` to `MsgFlags` on Android, Fuchsia, Linux, NetBSD,
FreeBSD, OpenBSD, and Solaris.
([#2014](https://github.com/nix-rust/nix/pull/2014))
- Added `SO_TS_CLOCK` for FreeBSD to `nix::sys::socket::sockopt`.
([#2093](https://github.com/nix-rust/nix/pull/2093))
- Added support for prctl in Linux.
(#[1550](https://github.com/nix-rust/nix/pull/1550))
- `nix::socket` and `nix::select` are now available on Redox.
([#2012](https://github.com/nix-rust/nix/pull/2012))
- Implemented AsFd, AsRawFd, FromRawFd, and IntoRawFd for `mqueue::MqdT`.
([#2097](https://github.com/nix-rust/nix/pull/2097))
- Add the ability to set `kevent_flags` on `SigEvent`.
([#1731](https://github.com/nix-rust/nix/pull/1731))
### Changed
- All Cargo features have been removed from the default set. Users will need to
specify which features they depend on in their Cargo.toml.
([#2091](https://github.com/nix-rust/nix/pull/2091))
- Implemented I/O safety for many, but not all, of Nix's APIs. Many public
functions argument and return types have changed:
| Original Type | New Type |
| ------------- | --------------------- |
| AsRawFd | AsFd |
| RawFd | BorrowedFd or OwnedFd |
(#[1906](https://github.com/nix-rust/nix/pull/1906))
- Use I/O safety with `copy_file_range`, and expose it on FreeBSD.
(#[1906](https://github.com/nix-rust/nix/pull/1906))
- The MSRV is now 1.65
([#1862](https://github.com/nix-rust/nix/pull/1862))
([#2104](https://github.com/nix-rust/nix/pull/2104))
- The epoll interface now uses a type.
([#1882](https://github.com/nix-rust/nix/pull/1882))
- With I/O-safe type applied in `pty::OpenptyResult` and `pty::ForkptyResult`,
users no longer need to manually close the file descriptors in these types.
([#1921](https://github.com/nix-rust/nix/pull/1921))
- Refactored `name` parameter of `mq_open` and `mq_unlink` to be generic over
`NixPath`.
([#2102](https://github.com/nix-rust/nix/pull/2102)).
- Made `clone` unsafe, like `fork`.
([#1993](https://github.com/nix-rust/nix/pull/1993))
### Removed
- `sys::event::{kevent, kevent_ts}` are deprecated in favor of
`sys::kevent::Kqueue::kevent`, and `sys::event::kqueue` is deprecated in
favor of `sys::kevent::Kqueue::new`.
([#1943](https://github.com/nix-rust/nix/pull/1943))
- Removed deprecated IoVec API.
([#1855](https://github.com/nix-rust/nix/pull/1855))
- Removed deprecated net APIs.
([#1861](https://github.com/nix-rust/nix/pull/1861))
- `nix::sys::signalfd::signalfd` is deprecated. Use
`nix::sys::signalfd::SignalFd` instead.
([#1938](https://github.com/nix-rust/nix/pull/1938))
- Removed `SigEvent` support on Fuchsia, where it was unsound.
([#2079](https://github.com/nix-rust/nix/pull/2079))
- Removed `flock` from `::nix::fcntl` on Solaris.
([#2082](https://github.com/nix-rust/nix/pull/2082))
## [0.26.3] - 2023-08-27
### Fixed
- Fix: send `ETH_P_ALL` in htons format
([#1925](https://github.com/nix-rust/nix/pull/1925))
- Fix: `recvmsg` now sets the length of the received `sockaddr_un` field
correctly on Linux platforms. ([#2041](https://github.com/nix-rust/nix/pull/2041))
- Fix potentially invalid conversions in
`SockaddrIn::from<std::net::SocketAddrV4>`,
`SockaddrIn6::from<std::net::SockaddrV6>`, `IpMembershipRequest::new`, and
`Ipv6MembershipRequest::new` with future Rust versions.
([#2061](https://github.com/nix-rust/nix/pull/2061))
- Fixed an incorrect lifetime returned from `recvmsg`.
([#2095](https://github.com/nix-rust/nix/pull/2095))
## [0.26.2] - 2023-01-18
### Fixed
- Fix `SockaddrIn6` bug that was swapping `flowinfo` and `scope_id` byte
ordering.
([#1964](https://github.com/nix-rust/nix/pull/1964))
## [0.26.1] - 2022-11-29
@ -209,7 +320,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1563](https://github.com/nix-rust/nix/pull/1563))
- Added `process_vm_readv` and `process_vm_writev` on Android.
(#[1557](https://github.com/nix-rust/nix/pull/1557))
- Added `nix::uncontext` module on s390x.
- Added `nix::ucontext` module on s390x.
(#[1662](https://github.com/nix-rust/nix/pull/1662))
- Implemented `Extend`, `FromIterator`, and `IntoIterator` for `SigSet` and
added `SigSet::iter` and `SigSetIter`.

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

@ -10,10 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.56"
edition = "2021"
rust-version = "1.65"
name = "nix"
version = "0.26.2"
version = "0.27.1"
authors = ["The nix-rust Project Developers"]
include = [
"src/**/*",
@ -29,6 +29,7 @@ license = "MIT"
repository = "https://github.com/nix-rust/nix"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
@ -65,32 +66,30 @@ path = "test/test_mount.rs"
harness = false
[[test]]
name = "test-ptymaster-drop"
path = "test/test_ptymaster_drop.rs"
name = "test-prctl"
path = "test/sys/test_prctl.rs"
[dependencies.bitflags]
version = "1.1"
version = "2.3.1"
[dependencies.cfg-if]
version = "1.0"
[dependencies.libc]
version = "0.2.137"
version = "0.2.147"
features = ["extra_traits"]
[dependencies.memoffset]
version = "0.9"
optional = true
[dependencies.pin-utils]
version = "0.1.0"
optional = true
[dependencies.static_assertions]
version = "1"
[dev-dependencies.assert-impl]
version = "0.1"
[dev-dependencies.lazy_static]
version = "1.4"
[dev-dependencies.parking_lot]
version = "0.12"
@ -101,45 +100,12 @@ version = "0.8"
version = "1.0.7"
[dev-dependencies.tempfile]
version = "3.3.0"
version = "3.7.1"
[features]
acct = []
aio = ["pin-utils"]
default = [
"acct",
"aio",
"dir",
"env",
"event",
"feature",
"fs",
"hostname",
"inotify",
"ioctl",
"kmod",
"mman",
"mount",
"mqueue",
"net",
"personality",
"poll",
"process",
"pthread",
"ptrace",
"quota",
"reboot",
"resource",
"sched",
"signal",
"socket",
"term",
"time",
"ucontext",
"uio",
"user",
"zerocopy",
]
default = []
dir = ["fs"]
env = []
event = []
@ -177,9 +143,5 @@ zerocopy = [
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
version = "0.5.3"
[target."cfg(not(target_os = \"redox\"))".dependencies.memoffset]
version = "0.7"
optional = true
[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
version = "0.4"

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

@ -30,7 +30,7 @@ pub fn gethostname() -> Result<OsString>;
## Supported Platforms
nix target support consists of two tiers. While nix attempts to support all
nix target support consists of three tiers. While nix attempts to support all
platforms supported by [libc](https://github.com/rust-lang/libc), only some
platforms are actively supported due to either technical or manpower
limitations. Support for platforms is split into three tiers:
@ -41,55 +41,70 @@ limitations. Support for platforms is split into three tiers:
blocks the inclusion of new code. Tests may be run, but failures
in tests don't block the inclusion of new code.
* Tier 3 - Builds for this target are run in CI. Failures during the build
*do not* block the inclusion of new code. Testing may be run, but
failures in tests don't block the inclusion of new code.
*do not* necessarily block the inclusion of new code. That is, at
our discretion a Tier 3 target may be dropped at any time, if it
would otherwise block development.
Platforms not listed are supported on a best-effort basis, relying on our users
to report any problems.
The following targets are supported by `nix`:
Tier 1:
* aarch64-apple-darwin
* aarch64-unknown-linux-gnu
* arm-unknown-linux-gnueabi
* armv7-unknown-linux-gnueabihf
* i686-unknown-freebsd
* i686-unknown-linux-gnu
* i686-unknown-linux-musl
* mips-unknown-linux-gnu
* mips64-unknown-linux-gnuabi64
* mips64el-unknown-linux-gnuabi64
* mipsel-unknown-linux-gnu
* powerpc64le-unknown-linux-gnu
* x86_64-unknown-freebsd
* x86_64-unknown-linux-gnu
* x86_64-unknown-linux-musl
Tier 2:
* aarch64-apple-ios
* aarch64-linux-android
* arm-linux-androideabi
* arm-unknown-linux-musleabi
* armv7-linux-androideabi
* i686-linux-android
* powerpc-unknown-linux-gnu
* s390x-unknown-linux-gnu
* x86_64-apple-ios
* x86_64-linux-android
* x86_64-apple-darwin
* x86_64-unknown-illumos
* x86_64-unknown-netbsd
Tier 3:
* armv7-unknown-linux-uclibceabihf
* x86_64-fuchsia
* x86_64-unknown-dragonfly
* x86_64-unknown-haiku
* x86_64-unknown-linux-gnux32
* x86_64-unknown-openbsd
* x86_64-unknown-redox
<table>
<tr>
<th>Tier 1</th>
<th>Tier 2</th>
<th>Tier 3</th>
</tr>
<tr>
<td>
<ul>
<li>aarch64-apple-darwin</li>
<li>aarch64-unknown-linux-gnu</li>
<li>arm-unknown-linux-gnueabi</li>
<li>armv7-unknown-linux-gnueabihf</li>
<li>i686-unknown-freebsd</li>
<li>i686-unknown-linux-gnu</li>
<li>i686-unknown-linux-musl</li>
<li>mips-unknown-linux-gnu</li>
<li>mips64-unknown-linux-gnuabi64</li>
<li>mips64el-unknown-linux-gnuabi64</li>
<li>mipsel-unknown-linux-gnu</li>
<li>powerpc64le-unknown-linux-gnu</li>
<li>x86_64-unknown-freebsd</li>
<li>x86_64-unknown-linux-gnu</li>
<li>x86_64-unknown-linux-musl</li>
</ul>
</td>
<td>
<ul>
<li>aarch64-apple-ios</li>
<li>aarch64-linux-android</li>
<li>arm-linux-androideabi</li>
<li>arm-unknown-linux-musleabi</li>
<li>armv7-linux-androideabi</li>
<li>i686-linux-android</li>
<li>s390x-unknown-linux-gnu</li>
<li>x86_64-linux-android</li>
<li>x86_64-unknown-illumos</li>
<li>x86_64-unknown-netbsd</li>
</td>
<td>
<li>armv7-unknown-linux-uclibceabihf</li>
<li>powerpc64-unknown-linux-gnu</li>
<li>x86_64-fuchsia</li>
<li>x86_64-unknown-dragonfly</li>
<li>x86_64-unknown-haiku</li>
<li>x86_64-unknown-linux-gnux32</li>
<li>x86_64-unknown-openbsd</li>
<li>x86_64-unknown-redox</li>
</td>
</tr>
</table>
## Minimum Supported Rust Version (MSRV)
nix is supported on Rust 1.56.1 and higher. Its MSRV will not be
nix is supported on Rust 1.65 and higher. Its MSRV will not be
changed in the future without bumping the major or minor version.
## Contributing

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

@ -101,6 +101,9 @@ impl Drop for Dir {
}
}
// The pass by mut is technically needless only because the inner NonNull is
// Copy. But philosophically we're mutating the Dir, so we pass by mut.
#[allow(clippy::needless_pass_by_ref_mut)]
fn next(dir: &mut Dir) -> Option<Result<Entry>> {
unsafe {
// Note: POSIX specifies that portable applications should dynamically allocate a
@ -221,7 +224,8 @@ impl Entry {
#[allow(clippy::unnecessary_cast)]
pub fn ino(&self) -> u64 {
cfg_if! {
if #[cfg(any(target_os = "android",
if #[cfg(any(target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
@ -240,7 +244,7 @@ impl Entry {
/// Returns the bare file name of this directory entry without any other leading path component.
pub fn file_name(&self) -> &ffi::CStr {
unsafe { ::std::ffi::CStr::from_ptr(self.0.d_name.as_ptr()) }
unsafe { ffi::CStr::from_ptr(self.0.d_name.as_ptr()) }
}
/// Returns the type of this directory entry, if known.
@ -250,6 +254,7 @@ impl Entry {
/// `fstat` if this returns `None`.
pub fn file_type(&self) -> Option<Type> {
#[cfg(not(any(
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
@ -267,6 +272,7 @@ impl Entry {
// illumos, Solaris, and Haiku systems do not have the d_type member at all:
#[cfg(any(
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"

247
third_party/rust/nix/src/errno.rs поставляемый
Просмотреть файл

@ -34,6 +34,10 @@ cfg_if! {
unsafe fn errno_location() -> *mut c_int {
libc::_errnop()
}
} else if #[cfg(any(target_os = "aix"))] {
unsafe fn errno_location() -> *mut c_int {
libc::_Errno()
}
}
}
@ -223,6 +227,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -232,6 +237,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -241,6 +247,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -250,6 +257,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -259,6 +267,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -268,6 +277,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -277,6 +287,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -286,6 +297,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -421,6 +433,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -457,6 +470,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -466,6 +480,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -482,6 +497,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "fuchsia"
))]
EBADMSG => "Not a data message",
@ -492,6 +508,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "fuchsia",
target_os = "haiku"
))]
@ -572,6 +589,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia",
@ -582,6 +600,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "fuchsia"
@ -722,6 +741,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "fuchsia"
))]
EOWNERDEAD => "Owner died",
@ -732,6 +752,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "aix",
target_os = "fuchsia"
))]
ENOTRECOVERABLE => "State not recoverable",
@ -868,6 +889,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "ios",
target_os = "openbsd",
target_os = "netbsd",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
@ -879,6 +901,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "aix",
target_os = "openbsd",
target_os = "netbsd"
))]
@ -889,6 +912,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "aix",
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox"
@ -903,6 +927,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
@ -917,6 +942,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox",
target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
@ -928,6 +954,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "aix",
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox"
@ -1009,6 +1036,7 @@ fn desc(errno: Errno) -> &'static str {
target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
target_os = "aix",
target_os = "openbsd",
target_os = "netbsd",
target_os = "redox"
@ -1044,6 +1072,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
@ -1060,6 +1089,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
@ -1068,6 +1098,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
@ -1076,6 +1107,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "aix",
target_os = "netbsd",
target_os = "redox"
))]
@ -1084,6 +1116,7 @@ fn desc(errno: Errno) -> &'static str {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "aix",
target_os = "illumos",
target_os = "solaris"
))]
@ -3131,3 +3164,217 @@ mod consts {
}
}
}
#[cfg(target_os = "aix")]
mod consts {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(i32)]
#[non_exhaustive]
pub enum Errno {
UnknownErrno = 0,
EPERM = libc::EPERM,
ENOENT = libc::ENOENT,
ESRCH = libc::ESRCH,
EINTR = libc::EINTR,
EIO = libc::EIO,
ENXIO = libc::ENXIO,
E2BIG = libc::E2BIG,
ENOEXEC = libc::ENOEXEC,
EBADF = libc::EBADF,
ECHILD = libc::ECHILD,
EAGAIN = libc::EAGAIN,
ENOMEM = libc::ENOMEM,
EACCES = libc::EACCES,
EFAULT = libc::EFAULT,
ENOTBLK = libc::ENOTBLK,
EBUSY = libc::EBUSY,
EEXIST = libc::EEXIST,
EXDEV = libc::EXDEV,
ENODEV = libc::ENODEV,
ENOTDIR = libc::ENOTDIR,
EISDIR = libc::EISDIR,
EINVAL = libc::EINVAL,
ENFILE = libc::ENFILE,
EMFILE = libc::EMFILE,
ENOTTY = libc::ENOTTY,
ETXTBSY = libc::ETXTBSY,
EFBIG = libc::EFBIG,
ENOSPC = libc::ENOSPC,
ESPIPE = libc::ESPIPE,
EROFS = libc::EROFS,
EMLINK = libc::EMLINK,
EPIPE = libc::EPIPE,
EDOM = libc::EDOM,
ERANGE = libc::ERANGE,
EDEADLK = libc::EDEADLK,
ENAMETOOLONG = libc::ENAMETOOLONG,
ENOLCK = libc::ENOLCK,
ENOSYS = libc::ENOSYS,
ENOTEMPTY = libc::ENOTEMPTY,
ELOOP = libc::ELOOP,
ENOMSG = libc::ENOMSG,
EIDRM = libc::EIDRM,
EINPROGRESS = libc::EINPROGRESS,
EALREADY = libc::EALREADY,
ENOTSOCK = libc::ENOTSOCK,
EDESTADDRREQ = libc::EDESTADDRREQ,
EMSGSIZE = libc::EMSGSIZE,
EPROTOTYPE = libc::EPROTOTYPE,
ENOPROTOOPT = libc::ENOPROTOOPT,
EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
EPFNOSUPPORT = libc::EPFNOSUPPORT,
EAFNOSUPPORT = libc::EAFNOSUPPORT,
EADDRINUSE = libc::EADDRINUSE,
EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
ENETDOWN = libc::ENETDOWN,
ENETUNREACH = libc::ENETUNREACH,
ENETRESET = libc::ENETRESET,
ECONNABORTED = libc::ECONNABORTED,
ECONNRESET = libc::ECONNRESET,
ENOBUFS = libc::ENOBUFS,
EISCONN = libc::EISCONN,
ENOTCONN = libc::ENOTCONN,
ESHUTDOWN = libc::ESHUTDOWN,
ETOOMANYREFS = libc::ETOOMANYREFS,
ETIMEDOUT = libc::ETIMEDOUT,
ECONNREFUSED = libc::ECONNREFUSED,
EHOSTDOWN = libc::EHOSTDOWN,
EHOSTUNREACH = libc::EHOSTUNREACH,
ECHRNG = libc::ECHRNG,
EL2NSYNC = libc::EL2NSYNC,
EL3HLT = libc::EL3HLT,
EL3RST = libc::EL3RST,
ELNRNG = libc::ELNRNG,
EUNATCH = libc::EUNATCH,
ENOCSI = libc::ENOCSI,
EL2HLT = libc::EL2HLT,
ENOLINK = libc::ENOLINK,
EPROTO = libc::EPROTO,
EMULTIHOP = libc::EMULTIHOP,
EBADMSG = libc::EBADMSG,
EOVERFLOW = libc::EOVERFLOW,
EILSEQ = libc::EILSEQ,
ERESTART = libc::ERESTART,
EOWNERDEAD = libc::EOWNERDEAD,
ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
ENOTSUP = libc::ENOTSUP,
EPROCLIM = libc::EPROCLIM,
EUSERS = libc::EUSERS,
EDQUOT = libc::EDQUOT,
ESTALE = libc::ESTALE,
EREMOTE = libc::EREMOTE,
ECANCELED = libc::ECANCELED,
ENODATA = libc::ENODATA,
ENOSR = libc::ENOSR,
ENOSTR = libc::ENOSTR,
ETIME = libc::ETIME,
EOPNOTSUPP = libc::EOPNOTSUPP,
}
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;
match e {
libc::EPERM => EPERM,
libc::ENOENT => ENOENT,
libc::ESRCH => ESRCH,
libc::EINTR => EINTR,
libc::EIO => EIO,
libc::ENXIO => ENXIO,
libc::E2BIG => E2BIG,
libc::ENOEXEC => ENOEXEC,
libc::EBADF => EBADF,
libc::ECHILD => ECHILD,
libc::EAGAIN => EAGAIN,
libc::ENOMEM => ENOMEM,
libc::EACCES => EACCES,
libc::EFAULT => EFAULT,
libc::ENOTBLK => ENOTBLK,
libc::EBUSY => EBUSY,
libc::EEXIST => EEXIST,
libc::EXDEV => EXDEV,
libc::ENODEV => ENODEV,
libc::ENOTDIR => ENOTDIR,
libc::EISDIR => EISDIR,
libc::EINVAL => EINVAL,
libc::ENFILE => ENFILE,
libc::EMFILE => EMFILE,
libc::ENOTTY => ENOTTY,
libc::ETXTBSY => ETXTBSY,
libc::EFBIG => EFBIG,
libc::ENOSPC => ENOSPC,
libc::ESPIPE => ESPIPE,
libc::EROFS => EROFS,
libc::EMLINK => EMLINK,
libc::EPIPE => EPIPE,
libc::EDOM => EDOM,
libc::ERANGE => ERANGE,
libc::EDEADLK => EDEADLK,
libc::ENAMETOOLONG => ENAMETOOLONG,
libc::ENOLCK => ENOLCK,
libc::ENOSYS => ENOSYS,
libc::ENOTEMPTY => ENOTEMPTY,
libc::ELOOP => ELOOP,
libc::ENOMSG => ENOMSG,
libc::EIDRM => EIDRM,
libc::EINPROGRESS => EINPROGRESS,
libc::EALREADY => EALREADY,
libc::ENOTSOCK => ENOTSOCK,
libc::EDESTADDRREQ => EDESTADDRREQ,
libc::EMSGSIZE => EMSGSIZE,
libc::EPROTOTYPE => EPROTOTYPE,
libc::ENOPROTOOPT => ENOPROTOOPT,
libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
libc::EPFNOSUPPORT => EPFNOSUPPORT,
libc::EAFNOSUPPORT => EAFNOSUPPORT,
libc::EADDRINUSE => EADDRINUSE,
libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
libc::ENETDOWN => ENETDOWN,
libc::ENETUNREACH => ENETUNREACH,
libc::ENETRESET => ENETRESET,
libc::ECONNABORTED => ECONNABORTED,
libc::ECONNRESET => ECONNRESET,
libc::ENOBUFS => ENOBUFS,
libc::EISCONN => EISCONN,
libc::ENOTCONN => ENOTCONN,
libc::ESHUTDOWN => ESHUTDOWN,
libc::ETOOMANYREFS => ETOOMANYREFS,
libc::ETIMEDOUT => ETIMEDOUT,
libc::ECONNREFUSED => ECONNREFUSED,
libc::EHOSTDOWN => EHOSTDOWN,
libc::EHOSTUNREACH => EHOSTUNREACH,
libc::ECHRNG => ECHRNG,
libc::EL2NSYNC => EL2NSYNC,
libc::EL3HLT => EL3HLT,
libc::EL3RST => EL3RST,
libc::ELNRNG => ELNRNG,
libc::EUNATCH => EUNATCH,
libc::ENOCSI => ENOCSI,
libc::EL2HLT => EL2HLT,
libc::ENOLINK => ENOLINK,
libc::EPROTO => EPROTO,
libc::EMULTIHOP => EMULTIHOP,
libc::EBADMSG => EBADMSG,
libc::EOVERFLOW => EOVERFLOW,
libc::EILSEQ => EILSEQ,
libc::ERESTART => ERESTART,
libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
libc::EOWNERDEAD => EOWNERDEAD,
libc::ENOTSUP => ENOTSUP,
libc::EPROCLIM => EPROCLIM,
libc::EUSERS => EUSERS,
libc::EDQUOT => EDQUOT,
libc::ESTALE => ESTALE,
libc::EREMOTE => EREMOTE,
libc::ECANCELED => ECANCELED,
libc::ENODATA => ENODATA,
libc::ENOSR => ENOSR,
libc::ENOSTR => ENOSTR,
libc::ETIME => ETIME,
libc::EOPNOTSUPP => EOPNOTSUPP,
_ => UnknownErrno,
}
}
}

337
third_party/rust/nix/src/fcntl.rs поставляемый
Просмотреть файл

@ -5,11 +5,19 @@ use std::ffi::OsString;
use std::os::raw;
use std::os::unix::ffi::OsStringExt;
use std::os::unix::io::RawFd;
// For splice and copy_file_range
#[cfg(any(
target_os = "android",
target_os = "freebsd",
target_os = "linux"
))]
use std::{
os::unix::io::{AsFd, AsRawFd},
ptr,
};
#[cfg(feature = "fs")]
use crate::{sys::stat::Mode, NixPath, Result};
#[cfg(any(target_os = "android", target_os = "linux"))]
use std::ptr; // For splice and copy_file_range
#[cfg(any(
target_os = "linux",
@ -35,7 +43,7 @@ libc_bitflags! {
AT_NO_AUTOMOUNT;
#[cfg(any(target_os = "android", target_os = "linux"))]
AT_EMPTY_PATH;
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[cfg(not(target_os = "android"))]
AT_EACCESS;
}
}
@ -54,7 +62,10 @@ libc_bitflags!(
/// Open the file in append-only mode.
O_APPEND;
/// Generate a signal when input or output becomes possible.
#[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))]
#[cfg(not(any(target_os = "aix",
target_os = "illumos",
target_os = "solaris",
target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
O_ASYNC;
/// Closes the file descriptor once an `execve` call is made.
@ -193,9 +204,13 @@ feature! {
// The conversion is not identical on all operating systems.
#[allow(clippy::useless_conversion)]
pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
let fd = path.with_nix_path(|cstr| {
unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
pub fn open<P: ?Sized + NixPath>(
path: &P,
oflag: OFlag,
mode: Mode,
) -> Result<RawFd> {
let fd = path.with_nix_path(|cstr| unsafe {
libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
})?;
Errno::result(fd)
@ -210,8 +225,8 @@ pub fn openat<P: ?Sized + NixPath>(
oflag: OFlag,
mode: Mode,
) -> Result<RawFd> {
let fd = path.with_nix_path(|cstr| {
unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
let fd = path.with_nix_path(|cstr| unsafe {
libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
})?;
Errno::result(fd)
}
@ -237,7 +252,7 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
}
}
#[cfg(all(target_os = "linux", target_env = "gnu",))]
#[cfg(all(target_os = "linux", target_env = "gnu"))]
#[cfg(feature = "fs")]
libc_bitflags! {
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
@ -250,10 +265,7 @@ libc_bitflags! {
feature! {
#![feature = "fs"]
#[cfg(all(
target_os = "linux",
target_env = "gnu",
))]
#[cfg(all(target_os = "linux", target_env = "gnu"))]
pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
old_dirfd: Option<RawFd>,
old_path: &P1,
@ -306,55 +318,84 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
})
}
fn inner_readlink<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P) -> Result<OsString> {
fn inner_readlink<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
path: &P,
) -> Result<OsString> {
let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
// simple case: result is strictly less than `PATH_MAX`
let res = readlink_maybe_at(dirfd, path, &mut v)?;
let len = Errno::result(res)?;
debug_assert!(len >= 0);
if (len as usize) < v.capacity() {
return wrap_readlink_result(v, res);
}
// Uh oh, the result is too long...
// Let's try to ask lstat how many bytes to allocate.
let reported_size = match dirfd {
#[cfg(target_os = "redox")]
Some(_) => unreachable!(),
#[cfg(any(target_os = "android", target_os = "linux"))]
Some(dirfd) => {
let flags = if path.is_empty() { AtFlags::AT_EMPTY_PATH } else { AtFlags::empty() };
super::sys::stat::fstatat(dirfd, path, flags | AtFlags::AT_SYMLINK_NOFOLLOW)
},
#[cfg(not(any(target_os = "android", target_os = "linux", target_os = "redox")))]
Some(dirfd) => super::sys::stat::fstatat(dirfd, path, AtFlags::AT_SYMLINK_NOFOLLOW),
None => super::sys::stat::lstat(path)
}
.map(|x| x.st_size)
.unwrap_or(0);
let mut try_size = if reported_size > 0 {
// Note: even if `lstat`'s apparently valid answer turns out to be
// wrong, we will still read the full symlink no matter what.
reported_size as usize + 1
} else {
// If lstat doesn't cooperate, or reports an error, be a little less
// precise.
(libc::PATH_MAX as usize).max(128) << 1
};
loop {
v.reserve_exact(try_size);
{
// simple case: result is strictly less than `PATH_MAX`
let res = readlink_maybe_at(dirfd, path, &mut v)?;
let len = Errno::result(res)?;
debug_assert!(len >= 0);
if (len as usize) < v.capacity() {
break wrap_readlink_result(v, res);
} else {
// Ugh! Still not big enough!
match try_size.checked_shl(1) {
Some(next_size) => try_size = next_size,
// It's absurd that this would happen, but handle it sanely
// anyway.
None => break Err(Errno::ENAMETOOLONG),
return wrap_readlink_result(v, res);
}
}
// Uh oh, the result is too long...
// Let's try to ask lstat how many bytes to allocate.
let mut try_size = {
let reported_size = match dirfd {
#[cfg(target_os = "redox")]
Some(_) => unreachable!(),
#[cfg(any(target_os = "android", target_os = "linux"))]
Some(dirfd) => {
let flags = if path.is_empty() {
AtFlags::AT_EMPTY_PATH
} else {
AtFlags::empty()
};
super::sys::stat::fstatat(
dirfd,
path,
flags | AtFlags::AT_SYMLINK_NOFOLLOW,
)
}
#[cfg(not(any(
target_os = "android",
target_os = "linux",
target_os = "redox"
)))]
Some(dirfd) => super::sys::stat::fstatat(
dirfd,
path,
AtFlags::AT_SYMLINK_NOFOLLOW,
),
None => super::sys::stat::lstat(path),
}
.map(|x| x.st_size)
.unwrap_or(0);
if reported_size > 0 {
// Note: even if `lstat`'s apparently valid answer turns out to be
// wrong, we will still read the full symlink no matter what.
reported_size as usize + 1
} else {
// If lstat doesn't cooperate, or reports an error, be a little less
// precise.
(libc::PATH_MAX as usize).max(128) << 1
}
};
loop {
{
v.reserve_exact(try_size);
let res = readlink_maybe_at(dirfd, path, &mut v)?;
let len = Errno::result(res)?;
debug_assert!(len >= 0);
if (len as usize) < v.capacity() {
return wrap_readlink_result(v, res);
}
}
// Ugh! Still not big enough!
match try_size.checked_shl(1) {
Some(next_size) => try_size = next_size,
// It's absurd that this would happen, but handle it sanely
// anyway.
None => break Err(Errno::ENAMETOOLONG),
}
}
}
@ -364,7 +405,10 @@ pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
}
#[cfg(not(target_os = "redox"))]
pub fn readlinkat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
pub fn readlinkat<P: ?Sized + NixPath>(
dirfd: RawFd,
path: &P,
) -> Result<OsString> {
inner_readlink(Some(dirfd), path)
}
@ -427,9 +471,17 @@ pub enum FcntlArg<'a> {
F_OFD_SETLKW(&'a libc::flock),
#[cfg(any(target_os = "linux", target_os = "android"))]
F_OFD_GETLK(&'a mut libc::flock),
#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd"
))]
F_ADD_SEALS(SealFlag),
#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd"
))]
F_GET_SEALS,
#[cfg(any(target_os = "macos", target_os = "ios"))]
F_FULLFSYNC,
@ -458,7 +510,9 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
let res = unsafe {
match arg {
F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd),
F_DUPFD_CLOEXEC(rawfd) => {
libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd)
}
F_GETFD => libc::fcntl(fd, libc::F_GETFD),
F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
F_GETFL => libc::fcntl(fd, libc::F_GETFL),
@ -475,9 +529,19 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
#[cfg(any(target_os = "android", target_os = "linux"))]
F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd"
))]
F_ADD_SEALS(flag) => {
libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits())
}
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd"
))]
F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
#[cfg(any(target_os = "macos", target_os = "ios"))]
F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
@ -503,7 +567,7 @@ pub enum FlockArg {
UnlockNonblock,
}
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
use self::FlockArg::*;
@ -512,8 +576,12 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
LockShared => libc::flock(fd, libc::LOCK_SH),
LockExclusive => libc::flock(fd, libc::LOCK_EX),
Unlock => libc::flock(fd, libc::LOCK_UN),
LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB),
LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB),
LockSharedNonblock => {
libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB)
}
LockExclusiveNonblock => {
libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB)
}
UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
}
};
@ -552,44 +620,65 @@ feature! {
///
/// The `copy_file_range` system call performs an in-kernel copy between
/// file descriptors `fd_in` and `fd_out` without the additional cost of
/// transferring data from the kernel to user space and then back into the
/// kernel. It copies up to `len` bytes of data from file descriptor `fd_in` to
/// file descriptor `fd_out`, overwriting any data that exists within the
/// requested range of the target file.
/// transferring data from the kernel to user space and back again. There may be
/// additional optimizations for specific file systems. It copies up to `len`
/// bytes of data from file descriptor `fd_in` to file descriptor `fd_out`,
/// overwriting any data that exists within the requested range of the target
/// file.
///
/// If the `off_in` and/or `off_out` arguments are used, the values
/// will be mutated to reflect the new position within the file after
/// copying. If they are not used, the relevant filedescriptors will be seeked
/// copying. If they are not used, the relevant file descriptors will be seeked
/// to the new position.
///
/// On successful completion the number of bytes actually copied will be
/// returned.
#[cfg(any(target_os = "android", target_os = "linux"))]
pub fn copy_file_range(
fd_in: RawFd,
off_in: Option<&mut libc::loff_t>,
fd_out: RawFd,
off_out: Option<&mut libc::loff_t>,
// Note: FreeBSD defines the offset argument as "off_t". Linux and Android
// define it as "loff_t". But on both OSes, on all supported platforms, those
// are 64 bits. So Nix uses i64 to make the docs simple and consistent.
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
fd_in: Fd1,
off_in: Option<&mut i64>,
fd_out: Fd2,
off_out: Option<&mut i64>,
len: usize,
) -> Result<usize> {
let off_in = off_in
.map(|offset| offset as *mut libc::loff_t)
.map(|offset| offset as *mut i64)
.unwrap_or(ptr::null_mut());
let off_out = off_out
.map(|offset| offset as *mut libc::loff_t)
.map(|offset| offset as *mut i64)
.unwrap_or(ptr::null_mut());
let ret = unsafe {
libc::syscall(
libc::SYS_copy_file_range,
fd_in,
off_in,
fd_out,
off_out,
len,
0,
)
};
cfg_if::cfg_if! {
if #[cfg(target_os = "freebsd")] {
let ret = unsafe {
libc::copy_file_range(
fd_in.as_fd().as_raw_fd(),
off_in,
fd_out.as_fd().as_raw_fd(),
off_out,
len,
0,
)
};
} else {
// May Linux distros still don't include copy_file_range in their
// libc implementations, so we need to make a direct syscall.
let ret = unsafe {
libc::syscall(
libc::SYS_copy_file_range,
fd_in,
off_in,
fd_out.as_fd().as_raw_fd(),
off_out,
len,
0,
)
};
}
}
Errno::result(ret).map(|r| r as usize)
}
@ -609,12 +698,19 @@ pub fn splice(
.map(|offset| offset as *mut libc::loff_t)
.unwrap_or(ptr::null_mut());
let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) };
let ret = unsafe {
libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
};
Errno::result(ret).map(|r| r as usize)
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result<usize> {
pub fn tee(
fd_in: RawFd,
fd_out: RawFd,
len: usize,
flags: SpliceFFlags,
) -> Result<usize> {
let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
Errno::result(ret).map(|r| r as usize)
}
@ -623,9 +719,8 @@ pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Resu
pub fn vmsplice(
fd: RawFd,
iov: &[std::io::IoSlice<'_>],
flags: SpliceFFlags
) -> Result<usize>
{
flags: SpliceFFlags,
) -> Result<usize> {
let ret = unsafe {
libc::vmsplice(
fd,
@ -638,7 +733,7 @@ pub fn vmsplice(
}
}
#[cfg(any(target_os = "linux"))]
#[cfg(target_os = "linux")]
#[cfg(feature = "fs")]
libc_bitflags!(
/// Mode argument flags for fallocate determining operation performed on a given range.
@ -678,7 +773,7 @@ feature! {
///
/// Allows the caller to directly manipulate the allocated disk space for the
/// file referred to by fd.
#[cfg(any(target_os = "linux"))]
#[cfg(target_os = "linux")]
#[cfg(feature = "fs")]
pub fn fallocate(
fd: RawFd,
@ -755,14 +850,19 @@ impl SpacectlRange {
/// ```
#[cfg(target_os = "freebsd")]
pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
let mut rqsr = libc::spacectl_range{r_offset: range.0, r_len: range.1};
let res = unsafe { libc::fspacectl(
let mut rqsr = libc::spacectl_range {
r_offset: range.0,
r_len: range.1,
};
let res = unsafe {
libc::fspacectl(
fd,
libc::SPACECTL_DEALLOC, // Only one command is supported ATM
&rqsr,
0, // No flags are currently supported
&mut rqsr
)};
0, // No flags are currently supported
&mut rqsr,
)
};
Errno::result(res).map(|_| SpacectlRange(rqsr.r_offset, rqsr.r_len))
}
@ -797,18 +897,25 @@ pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
/// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef");
/// ```
#[cfg(target_os = "freebsd")]
pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t)
-> Result<()>
{
let mut rqsr = libc::spacectl_range{r_offset: offset, r_len: len};
pub fn fspacectl_all(
fd: RawFd,
offset: libc::off_t,
len: libc::off_t,
) -> Result<()> {
let mut rqsr = libc::spacectl_range {
r_offset: offset,
r_len: len,
};
while rqsr.r_len > 0 {
let res = unsafe { libc::fspacectl(
let res = unsafe {
libc::fspacectl(
fd,
libc::SPACECTL_DEALLOC, // Only one command is supported ATM
&rqsr,
0, // No flags are currently supported
&mut rqsr
)};
0, // No flags are currently supported
&mut rqsr,
)
};
Errno::result(res)?;
}
Ok(())
@ -825,8 +932,8 @@ pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t)
))]
mod posix_fadvise {
use crate::errno::Errno;
use std::os::unix::io::RawFd;
use crate::Result;
use std::os::unix::io::RawFd;
#[cfg(feature = "fs")]
libc_enum! {
@ -871,7 +978,11 @@ mod posix_fadvise {
target_os = "wasi",
target_os = "freebsd"
))]
pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> {
pub fn posix_fallocate(
fd: RawFd,
offset: libc::off_t,
len: libc::off_t,
) -> Result<()> {
let res = unsafe { libc::posix_fallocate(fd, offset, len) };
match Errno::result(res) {
Err(err) => Err(err),

16
third_party/rust/nix/src/features.rs поставляемый
Просмотреть файл

@ -6,6 +6,7 @@ mod os {
use crate::sys::utsname::uname;
use crate::Result;
use std::os::unix::ffi::OsStrExt;
use std::sync::atomic::{AtomicUsize, Ordering};
// Features:
// * atomic cloexec on socket: 2.6.27
@ -72,15 +73,15 @@ mod os {
}
fn kernel_version() -> Result<usize> {
static mut KERNEL_VERS: usize = 0;
static KERNEL_VERS: AtomicUsize = AtomicUsize::new(0);
let mut kernel_vers = KERNEL_VERS.load(Ordering::Relaxed);
unsafe {
if KERNEL_VERS == 0 {
KERNEL_VERS = parse_kernel_version()?;
}
Ok(KERNEL_VERS)
if kernel_vers == 0 {
kernel_vers = parse_kernel_version()?;
KERNEL_VERS.store(kernel_vers, Ordering::Relaxed);
}
Ok(kernel_vers)
}
/// Check if the OS supports atomic close-on-exec for sockets
@ -112,6 +113,7 @@ mod os {
}
#[cfg(any(
target_os = "aix",
target_os = "macos",
target_os = "ios",
target_os = "fuchsia",

8
third_party/rust/nix/src/kmod.rs поставляемый
Просмотреть файл

@ -3,7 +3,7 @@
//! For more details see
use std::ffi::CStr;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use crate::errno::Errno;
use crate::Result;
@ -79,15 +79,15 @@ libc_bitflags!(
/// ```
///
/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
pub fn finit_module<T: AsRawFd>(
fd: &T,
pub fn finit_module<Fd: AsFd>(
fd: Fd,
param_values: &CStr,
flags: ModuleInitFlags,
) -> Result<()> {
let res = unsafe {
libc::syscall(
libc::SYS_finit_module,
fd.as_raw_fd(),
fd.as_fd().as_raw_fd(),
param_values.as_ptr(),
flags.bits(),
)

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

@ -16,7 +16,7 @@
//! * `fs` - File system functionality
//! * `hostname` - Get and set the system's hostname
//! * `inotify` - Linux's `inotify` file system notification API
//! * `ioctl` - The `ioctl` syscall, and wrappers for my specific instances
//! * `ioctl` - The `ioctl` syscall, and wrappers for many specific instances
//! * `kmod` - Load and unload kernel modules
//! * `mman` - Stuff relating to memory management
//! * `mount` - Mount and unmount file systems
@ -47,7 +47,43 @@
#![recursion_limit = "500"]
#![deny(unused)]
#![allow(unused_macros)]
#![cfg_attr(not(feature = "default"), allow(unused_imports))]
#![cfg_attr(
not(all(
feature = "acct",
feature = "aio",
feature = "dir",
feature = "env",
feature = "event",
feature = "feature",
feature = "fs",
feature = "hostname",
feature = "inotify",
feature = "ioctl",
feature = "kmod",
feature = "mman",
feature = "mount",
feature = "mqueue",
feature = "net",
feature = "personality",
feature = "poll",
feature = "process",
feature = "pthread",
feature = "ptrace",
feature = "quota",
feature = "reboot",
feature = "resource",
feature = "sched",
feature = "socket",
feature = "signal",
feature = "term",
feature = "time",
feature = "ucontext",
feature = "uio",
feature = "user",
feature = "zerocopy",
)),
allow(unused_imports)
)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
@ -144,7 +180,12 @@ feature! {
// provides bindings for them.
#[cfg(all(
target_os = "linux",
any(target_arch = "s390x", target_arch = "x86", target_arch = "x86_64")
any(
target_arch = "aarch64",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64"
)
))]
feature! {
#![feature = "ucontext"]

5
third_party/rust/nix/src/macros.rs поставляемый
Просмотреть файл

@ -63,6 +63,8 @@ macro_rules! libc_bitflags {
}
) => {
::bitflags::bitflags! {
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
$(#[$outer])*
pub struct $BitFlags: $T {
$(
@ -95,7 +97,6 @@ macro_rules! libc_bitflags {
/// }
/// ```
// Some targets don't use all rules.
#[allow(unknown_lints)]
#[allow(unused_macro_rules)]
macro_rules! libc_enum {
// Exit rule.
@ -133,6 +134,8 @@ macro_rules! libc_enum {
impl ::std::convert::TryFrom<$repr> for $BitFlags {
type Error = $crate::Error;
#[allow(unused_doc_comments)]
#[allow(deprecated)]
#[allow(unused_attributes)]
fn try_from(x: $repr) -> $crate::Result<Self> {
match x {
$($try_froms)*

6
third_party/rust/nix/src/mount/bsd.rs поставляемый
Просмотреть файл

@ -391,8 +391,8 @@ impl<'a> Nmount<'a> {
});
let niov = self.iov.len() as c_uint;
let iovp = self.iov.as_mut_ptr() as *mut libc::iovec;
let res = unsafe { libc::nmount(iovp, niov, flags.bits) };
let iovp = self.iov.as_mut_ptr();
let res = unsafe { libc::nmount(iovp, niov, flags.bits()) };
match Errno::result(res) {
Ok(_) => Ok(()),
Err(error) => {
@ -446,7 +446,7 @@ where
P: ?Sized + NixPath,
{
let res = mountpoint.with_nix_path(|cstr| unsafe {
libc::unmount(cstr.as_ptr(), flags.bits)
libc::unmount(cstr.as_ptr(), flags.bits())
})?;
Errno::result(res).map(drop)

54
third_party/rust/nix/src/mount/linux.rs поставляемый
Просмотреть файл

@ -1,9 +1,9 @@
#![allow(missing_docs)]
use crate::errno::Errno;
use crate::{NixPath, Result};
use libc::{self, c_int, c_ulong};
libc_bitflags!(
/// Used with [`mount`].
pub struct MsFlags: c_ulong {
/// Mount read-only
MS_RDONLY;
@ -27,36 +27,80 @@ libc_bitflags!(
MS_NODIRATIME;
/// Linux 2.4.0 - Bind directory at different place
MS_BIND;
/// Move an existing mount to a new location
MS_MOVE;
/// Used to create a recursive bind mount.
MS_REC;
/// Suppress the display of certain kernel warning messages.
MS_SILENT;
/// VFS does not apply the umask
MS_POSIXACL;
/// The resulting mount cannot subsequently be bind mounted.
MS_UNBINDABLE;
/// Make this mount point private.
MS_PRIVATE;
/// If this is a shared mount point that is a member of a peer group
/// that contains other members, convert it to a slave mount.
MS_SLAVE;
/// Make this mount point shared.
MS_SHARED;
/// When a file on this filesystem is accessed, update the file's
/// last access time (atime) only if the current value of atime is
/// less than or equal to the file's last modification time (mtime) or
/// last status change time (ctime).
MS_RELATIME;
/// Mount request came from within the kernel
#[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
MS_KERNMOUNT;
/// Update inode I_version field
MS_I_VERSION;
/// Always update the last access time (atime) when files on this
/// filesystem are accessed.
MS_STRICTATIME;
/// Reduce on-disk updates of inode timestamps (atime, mtime, ctime) by
/// maintaining these changes only in memory.
MS_LAZYTIME;
#[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
#[allow(missing_docs)] // Not documented in Linux
MS_ACTIVE;
#[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
#[allow(missing_docs)] // Not documented in Linux
MS_NOUSER;
#[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_RMT_MASK;
#[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_MGC_VAL;
#[allow(missing_docs)] // Not documented in Linux; possibly kernel-only
MS_MGC_MSK;
}
);
libc_bitflags!(
/// Used with [`umount2].
pub struct MntFlags: c_int {
/// Attempt to unmount even if still in use, aborting pending requests.
MNT_FORCE;
/// Lazy unmount. Disconnect the file system immediately, but don't
/// actually unmount it until it ceases to be busy.
MNT_DETACH;
/// Mark the mount point as expired.
MNT_EXPIRE;
/// Don't dereference `target` if it is a symlink.
UMOUNT_NOFOLLOW;
}
);
/// Mount a file system.
///
/// # Arguments
/// - `source` - Specifies the file system. e.g. `/dev/sd0`.
/// - `target` - Specifies the destination. e.g. `/mnt`.
/// - `fstype` - The file system type, e.g. `ext4`.
/// - `flags` - Optional flags controlling the mount.
/// - `data` - Optional file system specific data.
///
/// # See Also
/// [`mount`](https://man7.org/linux/man-pages/man2/mount.2.html)
pub fn mount<
P1: ?Sized + NixPath,
P2: ?Sized + NixPath,
@ -88,7 +132,7 @@ pub fn mount<
s,
t.as_ptr(),
ty,
flags.bits,
flags.bits(),
d as *const libc::c_void,
)
})
@ -99,6 +143,7 @@ pub fn mount<
Errno::result(res).map(drop)
}
/// Unmount the file system mounted at `target`.
pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
let res =
target.with_nix_path(|cstr| unsafe { libc::umount(cstr.as_ptr()) })?;
@ -106,9 +151,12 @@ pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
Errno::result(res).map(drop)
}
/// Unmount the file system mounted at `target`.
///
/// See also [`umount`](https://man7.org/linux/man-pages/man2/umount.2.html)
pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
let res = target.with_nix_path(|cstr| unsafe {
libc::umount2(cstr.as_ptr(), flags.bits)
libc::umount2(cstr.as_ptr(), flags.bits())
})?;
Errno::result(res).map(drop)

110
third_party/rust/nix/src/mqueue.rs поставляемый
Просмотреть файл

@ -9,16 +9,16 @@
//! use nix::sys::stat::Mode;
//!
//! const MSG_SIZE: mq_attr_member_t = 32;
//! let mq_name= CString::new("/a_nix_test_queue").unwrap();
//! let mq_name= "/a_nix_test_queue";
//!
//! let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
//! let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
//! let mqd0 = mq_open(&mq_name, oflag0, mode, None).unwrap();
//! let mqd0 = mq_open(mq_name, oflag0, mode, None).unwrap();
//! let msg_to_send = b"msg_1";
//! mq_send(&mqd0, msg_to_send, 1).unwrap();
//!
//! let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
//! let mqd1 = mq_open(&mq_name, oflag1, mode, None).unwrap();
//! let mqd1 = mq_open(mq_name, oflag1, mode, None).unwrap();
//! let mut buf = [0u8; 32];
//! let mut prio = 0u32;
//! let len = mq_receive(&mqd1, &mut buf, &mut prio).unwrap();
@ -31,12 +31,20 @@
//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
use crate::errno::Errno;
use crate::NixPath;
use crate::Result;
use crate::sys::stat::Mode;
use libc::{self, c_char, mqd_t, size_t};
use std::ffi::CStr;
use std::mem;
#[cfg(any(
target_os = "linux",
target_os = "netbsd",
target_os = "dragonfly"
))]
use std::os::unix::io::{
AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd,
};
libc_bitflags! {
/// Used with [`mq_open`].
@ -139,33 +147,41 @@ impl MqAttr {
/// Open a message queue
///
/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
// The mode.bits cast is only lossless on some OSes
// The mode.bits() cast is only lossless on some OSes
#[allow(clippy::cast_lossless)]
pub fn mq_open(
name: &CStr,
pub fn mq_open<P>(
name: &P,
oflag: MQ_OFlag,
mode: Mode,
attr: Option<&MqAttr>,
) -> Result<MqdT> {
let res = match attr {
) -> Result<MqdT>
where
P: ?Sized + NixPath,
{
let res = name.with_nix_path(|cstr| match attr {
Some(mq_attr) => unsafe {
libc::mq_open(
name.as_ptr(),
cstr.as_ptr(),
oflag.bits(),
mode.bits() as libc::c_int,
&mq_attr.mq_attr as *const libc::mq_attr,
)
},
None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
};
None => unsafe { libc::mq_open(cstr.as_ptr(), oflag.bits()) },
})?;
Errno::result(res).map(MqdT)
}
/// Remove a message queue
///
/// See also [`mq_unlink(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
pub fn mq_unlink(name: &CStr) -> Result<()> {
let res = unsafe { libc::mq_unlink(name.as_ptr()) };
pub fn mq_unlink<P>(name: &P) -> Result<()>
where
P: ?Sized + NixPath,
{
let res =
name.with_nix_path(|cstr| unsafe { libc::mq_unlink(cstr.as_ptr()) })?;
Errno::result(res).map(drop)
}
@ -197,6 +213,32 @@ pub fn mq_receive(
Errno::result(res).map(|r| r as usize)
}
feature! {
#![feature = "time"]
use crate::sys::time::TimeSpec;
/// Receive a message from a message queue with a timeout
///
/// See also ['mq_timedreceive(2)'](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
pub fn mq_timedreceive(
mqdes: &MqdT,
message: &mut [u8],
msg_prio: &mut u32,
abstime: &TimeSpec,
) -> Result<usize> {
let len = message.len() as size_t;
let res = unsafe {
libc::mq_timedreceive(
mqdes.0,
message.as_mut_ptr() as *mut c_char,
len,
msg_prio as *mut u32,
abstime.as_ref(),
)
};
Errno::result(res).map(|r| r as usize)
}
}
/// Send a message to a message queue
///
/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
@ -274,3 +316,43 @@ pub fn mq_remove_nonblock(mqd: &MqdT) -> Result<MqAttr> {
);
mq_setattr(mqd, &newattr)
}
#[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "dragonfly"))]
impl AsFd for MqdT {
/// Borrow the underlying message queue descriptor.
fn as_fd(&self) -> BorrowedFd {
// SAFETY: [MqdT] will only contain a valid fd by construction.
unsafe { BorrowedFd::borrow_raw(self.0) }
}
}
#[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "dragonfly"))]
impl AsRawFd for MqdT {
/// Return the underlying message queue descriptor.
///
/// Returned descriptor is a "shallow copy" of the descriptor, so it refers
/// to the same underlying kernel object as `self`.
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "dragonfly"))]
impl FromRawFd for MqdT {
/// Construct an [MqdT] from [RawFd].
///
/// # Safety
/// The `fd` given must be a valid and open file descriptor for a message
/// queue.
unsafe fn from_raw_fd(fd: RawFd) -> MqdT {
MqdT(fd)
}
}
#[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "dragonfly"))]
impl IntoRawFd for MqdT {
/// Consume this [MqdT] and return a [RawFd].
fn into_raw_fd(self) -> RawFd {
self.0
}
}

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

@ -334,6 +334,7 @@ libc_bitflags!(
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "illumos",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod if_nameindex {
@ -465,5 +466,6 @@ mod if_nameindex {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "illumos",
))]
pub use if_nameindex::*;

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

@ -1,5 +1,5 @@
//! Wait for events to trigger on specific file descriptors
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd};
use crate::errno::Errno;
use crate::Result;
@ -14,20 +14,36 @@ use crate::Result;
/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct PollFd {
pub struct PollFd<'fd> {
pollfd: libc::pollfd,
_fd: std::marker::PhantomData<BorrowedFd<'fd>>,
}
impl PollFd {
impl<'fd> PollFd<'fd> {
/// Creates a new `PollFd` specifying the events of interest
/// for a given file descriptor.
pub const fn new(fd: RawFd, events: PollFlags) -> PollFd {
//
// Different from other I/O-safe interfaces, here, we have to take `AsFd`
// by reference to prevent the case where the `fd` is closed but it is
// still in use. For example:
//
// ```rust
// let (reader, _) = pipe().unwrap();
//
// // If `PollFd::new()` takes `AsFd` by value, then `reader` will be consumed,
// // but the file descriptor of `reader` will still be in use.
// let pollfd = PollFd::new(reader, flag);
//
// // Do something with `pollfd`, which uses the CLOSED fd.
// ```
pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> PollFd<'fd> {
PollFd {
pollfd: libc::pollfd {
fd,
fd: fd.as_fd().as_raw_fd(),
events: events.bits(),
revents: PollFlags::empty().bits(),
},
_fd: std::marker::PhantomData,
}
}
@ -68,9 +84,29 @@ impl PollFd {
}
}
impl AsRawFd for PollFd {
fn as_raw_fd(&self) -> RawFd {
self.pollfd.fd
impl<'fd> AsFd for PollFd<'fd> {
fn as_fd(&self) -> BorrowedFd<'_> {
// Safety:
//
// BorrowedFd::borrow_raw(RawFd) requires that the raw fd being passed
// must remain open for the duration of the returned BorrowedFd, this is
// guaranteed as the returned BorrowedFd has the lifetime parameter same
// as `self`:
// "fn as_fd<'self>(&'self self) -> BorrowedFd<'self>"
// which means that `self` (PollFd) is guaranteed to outlive the returned
// BorrowedFd. (Lifetime: PollFd > BorrowedFd)
//
// And the lifetime parameter of PollFd::new(fd, ...) ensures that `fd`
// (an owned file descriptor) must outlive the returned PollFd:
// "pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> PollFd<'fd>"
// (Lifetime: Owned fd > PollFd)
//
// With two above relationships, we can conclude that the `Owned file
// descriptor` will outlive the returned BorrowedFd,
// (Lifetime: Owned fd > BorrowedFd)
// i.e., the raw fd being passed will remain valid for the lifetime of
// the returned BorrowedFd.
unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) }
}
}

70
third_party/rust/nix/src/pty.rs поставляемый
Просмотреть файл

@ -5,37 +5,39 @@ pub use libc::winsize as Winsize;
use std::ffi::CStr;
use std::io;
#[cfg(not(target_os = "aix"))]
use std::mem;
use std::os::unix::prelude::*;
use crate::errno::Errno;
#[cfg(not(target_os = "aix"))]
use crate::sys::termios::Termios;
#[cfg(feature = "process")]
use crate::unistd::{ForkResult, Pid};
use crate::unistd::ForkResult;
#[cfg(all(feature = "process", not(target_os = "aix")))]
use crate::unistd::Pid;
use crate::{fcntl, unistd, Result};
/// Representation of a master/slave pty pair
///
/// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// This is returned by [`openpty`].
#[derive(Debug)]
pub struct OpenptyResult {
/// The master port in a virtual pty pair
pub master: RawFd,
pub master: OwnedFd,
/// The slave port in a virtual pty pair
pub slave: RawFd,
pub slave: OwnedFd,
}
feature! {
#![feature = "process"]
/// Representation of a master with a forked pty
///
/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
#[derive(Clone, Copy, Debug)]
/// This is returned by [`forkpty`].
#[derive(Debug)]
pub struct ForkptyResult {
/// The master port in a virtual pty pair
pub master: RawFd,
pub master: OwnedFd,
/// Metadata about forked process
pub fork_result: ForkResult,
}
@ -43,51 +45,33 @@ pub struct ForkptyResult {
/// Representation of the Master device in a master/slave pty pair
///
/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct PtyMaster(RawFd);
/// While this datatype is a thin wrapper around `OwnedFd`, it enforces that the available PTY
/// functions are given the correct file descriptor.
#[derive(Debug)]
pub struct PtyMaster(OwnedFd);
impl AsRawFd for PtyMaster {
fn as_raw_fd(&self) -> RawFd {
self.0
self.0.as_raw_fd()
}
}
impl IntoRawFd for PtyMaster {
fn into_raw_fd(self) -> RawFd {
let fd = self.0;
mem::forget(self);
fd
}
}
impl Drop for PtyMaster {
fn drop(&mut self) {
// On drop, we ignore errors like EINTR and EIO because there's no clear
// way to handle them, we can't return anything, and (on FreeBSD at
// least) the file descriptor is deallocated in these cases. However,
// we must panic on EBADF, because it is always an error to close an
// invalid file descriptor. That frequently indicates a double-close
// condition, which can cause confusing errors for future I/O
// operations.
let e = unistd::close(self.0);
if e == Err(Errno::EBADF) {
panic!("Closing an invalid file descriptor!");
};
fd.into_raw_fd()
}
}
impl io::Read for PtyMaster {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
unistd::read(self.0, buf).map_err(io::Error::from)
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
}
}
impl io::Write for PtyMaster {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unistd::write(self.0, buf).map_err(io::Error::from)
unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
@ -96,13 +80,13 @@ impl io::Write for PtyMaster {
impl io::Read for &PtyMaster {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
unistd::read(self.0, buf).map_err(io::Error::from)
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
}
}
impl io::Write for &PtyMaster {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unistd::write(self.0, buf).map_err(io::Error::from)
unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
@ -164,7 +148,7 @@ pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
return Err(Errno::last());
}
Ok(PtyMaster(fd))
Ok(PtyMaster(unsafe { OwnedFd::from_raw_fd(fd) }))
}
/// Get the name of the slave pseudoterminal (see
@ -244,6 +228,7 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
#[cfg(not(target_os = "aix"))]
pub fn openpty<
'a,
'b,
@ -308,8 +293,8 @@ pub fn openpty<
unsafe {
Ok(OpenptyResult {
master: master.assume_init(),
slave: slave.assume_init(),
master: OwnedFd::from_raw_fd(master.assume_init()),
slave: OwnedFd::from_raw_fd(slave.assume_init()),
})
}
}
@ -335,6 +320,7 @@ feature! {
/// special care must be taken to only invoke code you can control and audit.
///
/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
#[cfg(not(target_os = "aix"))]
pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
winsize: T,
termios: U,
@ -364,7 +350,7 @@ pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b T
})?;
Ok(ForkptyResult {
master: master.assume_init(),
master: OwnedFd::from_raw_fd(master.assume_init()),
fork_result,
})
}

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

@ -16,7 +16,7 @@ mod sched_linux_like {
use libc::{self, c_int, c_void};
use std::mem;
use std::option::Option;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
@ -95,7 +95,17 @@ mod sched_linux_like {
/// address need not be the highest address of the region. Nix will take
/// care of that requirement. The user only needs to provide a reference to
/// a normally allocated buffer.
pub fn clone(
///
/// # Safety
///
/// Because `clone` creates a child process with its stack located in
/// `stack` without specifying the size of the stack, special care must be
/// taken to ensure that the child process does not overflow the provided
/// stack space.
///
/// See [`fork`](crate::unistd::fork) for additional safety concerns related
/// to executing child processes.
pub unsafe fn clone(
mut cb: CloneCb,
stack: &mut [u8],
flags: CloneFlags,
@ -106,20 +116,18 @@ mod sched_linux_like {
(*cb)() as c_int
}
let res = unsafe {
let combined = flags.bits() | signal.unwrap_or(0);
let ptr = stack.as_mut_ptr().add(stack.len());
let ptr_aligned = ptr.sub(ptr as usize % 16);
libc::clone(
mem::transmute(
callback
as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
),
ptr_aligned as *mut c_void,
combined,
&mut cb as *mut _ as *mut c_void,
)
};
let combined = flags.bits() | signal.unwrap_or(0);
let ptr = stack.as_mut_ptr().add(stack.len());
let ptr_aligned = ptr.sub(ptr as usize % 16);
let res = libc::clone(
mem::transmute(
callback
as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
),
ptr_aligned as *mut c_void,
combined,
&mut cb as *mut _ as *mut c_void,
);
Errno::result(res).map(Pid::from_raw)
}
@ -136,8 +144,8 @@ mod sched_linux_like {
/// reassociate thread with a namespace
///
/// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
let res = unsafe { libc::setns(fd, nstype.bits()) };
pub fn setns<Fd: AsFd>(fd: Fd, nstype: CloneFlags) -> Result<()> {
let res = unsafe { libc::setns(fd.as_fd().as_raw_fd(), nstype.bits()) };
Errno::result(res).map(drop)
}

18
third_party/rust/nix/src/sys/aio.rs поставляемый
Просмотреть файл

@ -163,7 +163,7 @@ impl AioCb {
0 => Ok(()),
num if num > 0 => Err(Errno::from_i32(num)),
-1 => Err(Errno::last()),
num => panic!("unknown aio_error return value {:?}", num),
num => panic!("unknown aio_error return value {num:?}"),
}
}
@ -1051,8 +1051,14 @@ pub fn aio_suspend(
list: &[&dyn AsRef<libc::aiocb>],
timeout: Option<TimeSpec>,
) -> Result<()> {
let p = list as *const [&dyn AsRef<libc::aiocb>]
as *const [*const libc::aiocb] as *const *const libc::aiocb;
// Note that this allocation could be eliminated by making the argument
// generic, and accepting arguments like &[AioWrite]. But that would
// prevent using aio_suspend to wait on a heterogeneous list of mixed
// operations.
let v = list.iter()
.map(|x| x.as_ref() as *const libc::aiocb)
.collect::<Vec<*const libc::aiocb>>();
let p = v.as_ptr();
let timep = match timeout {
None => ptr::null::<libc::timespec>(),
Some(x) => x.as_ref() as *const libc::timespec,
@ -1136,14 +1142,11 @@ pub fn aio_suspend(
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use std::thread;
/// # use std::time;
/// # use lazy_static::lazy_static;
/// # use nix::errno::Errno;
/// # use nix::sys::aio::*;
/// # use nix::sys::signal::*;
/// # use tempfile::tempfile;
/// lazy_static! {
/// pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
/// }
/// pub static SIGNALED: AtomicBool = AtomicBool::new(false);
///
/// extern fn sigfunc(_: c_int) {
/// SIGNALED.store(true, Ordering::Relaxed);
@ -1172,6 +1175,7 @@ pub fn aio_suspend(
/// // notification, we know that all operations are complete.
/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
/// ```
#[deprecated(since = "0.27.0", note = "https://github.com/nix-rust/nix/issues/2017")]
pub fn lio_listio(
mode: LioMode,
list: &mut [Pin<&mut dyn AsMut<libc::aiocb>>],

128
third_party/rust/nix/src/sys/epoll.rs поставляемый
Просмотреть файл

@ -2,8 +2,7 @@ use crate::errno::Errno;
use crate::Result;
use libc::{self, c_int};
use std::mem;
use std::os::unix::io::RawFd;
use std::ptr;
use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
libc_bitflags!(
pub struct EpollFlags: c_int {
@ -70,6 +69,126 @@ impl EpollEvent {
}
}
/// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html).
/// ```
/// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}};
/// # use nix::unistd::write;
/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd};
/// # use std::time::{Instant, Duration};
/// # fn main() -> nix::Result<()> {
/// const DATA: u64 = 17;
/// const MILLIS: u64 = 100;
///
/// // Create epoll
/// let epoll = Epoll::new(EpollCreateFlags::empty())?;
///
/// // Create eventfd & Add event
/// let eventfd = eventfd(0, EfdFlags::empty())?;
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
///
/// // Arm eventfd & Time wait
/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
/// let now = Instant::now();
///
/// // Wait on event
/// let mut events = [EpollEvent::empty()];
/// epoll.wait(&mut events, MILLIS as isize)?;
///
/// // Assert data correct & timeout didn't occur
/// assert_eq!(events[0].data(), DATA);
/// assert!(now.elapsed() < Duration::from_millis(MILLIS));
/// # Ok(())
/// # }
/// ```
#[derive(Debug)]
pub struct Epoll(pub OwnedFd);
impl Epoll {
/// Creates a new epoll instance and returns a file descriptor referring to that instance.
///
/// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html).
pub fn new(flags: EpollCreateFlags) -> Result<Self> {
let res = unsafe { libc::epoll_create1(flags.bits()) };
let fd = Errno::result(res)?;
let owned_fd = unsafe { OwnedFd::from_raw_fd(fd) };
Ok(Self(owned_fd))
}
/// Add an entry to the interest list of the epoll file descriptor for
/// specified in events.
///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`.
pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> {
self.epoll_ctl(EpollOp::EpollCtlAdd, fd, &mut event)
}
/// Remove (deregister) the target file descriptor `fd` from the interest list.
///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` .
pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> {
self.epoll_ctl(EpollOp::EpollCtlDel, fd, None)
}
/// Change the settings associated with `fd` in the interest list to the new settings specified
/// in `event`.
///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`.
pub fn modify<Fd: AsFd>(
&self,
fd: Fd,
event: &mut EpollEvent,
) -> Result<()> {
self.epoll_ctl(EpollOp::EpollCtlMod, fd, event)
}
/// Waits for I/O events, blocking the calling thread if no events are currently available.
/// (This can be thought of as fetching items from the ready list of the epoll instance.)
///
/// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
pub fn wait(
&self,
events: &mut [EpollEvent],
timeout: isize,
) -> Result<usize> {
let res = unsafe {
libc::epoll_wait(
self.0.as_raw_fd(),
events.as_mut_ptr() as *mut libc::epoll_event,
events.len() as c_int,
timeout as c_int,
)
};
Errno::result(res).map(|r| r as usize)
}
/// This system call is used to add, modify, or remove entries in the interest list of the epoll
/// instance referred to by `self`. It requests that the operation `op` be performed for the
/// target file descriptor, `fd`.
///
/// When possible prefer [`Epoll::add`], [`Epoll::delete`] and [`Epoll::modify`].
///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
fn epoll_ctl<'a, Fd: AsFd, T>(
&self,
op: EpollOp,
fd: Fd,
event: T,
) -> Result<()>
where
T: Into<Option<&'a mut EpollEvent>>,
{
let event: Option<&mut EpollEvent> = event.into();
let ptr = event
.map(|x| &mut x.event as *mut libc::epoll_event)
.unwrap_or(std::ptr::null_mut());
unsafe {
Errno::result(libc::epoll_ctl(
self.0.as_raw_fd(),
op as c_int,
fd.as_fd().as_raw_fd(),
ptr,
))
.map(drop)
}
}
}
#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
#[inline]
pub fn epoll_create() -> Result<RawFd> {
let res = unsafe { libc::epoll_create(1024) };
@ -77,6 +196,7 @@ pub fn epoll_create() -> Result<RawFd> {
Errno::result(res)
}
#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
let res = unsafe { libc::epoll_create1(flags.bits()) };
@ -84,6 +204,7 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
Errno::result(res)
}
#[deprecated(since = "0.27.0", note = "Use Epoll::epoll_ctl() instead")]
#[inline]
pub fn epoll_ctl<'a, T>(
epfd: RawFd,
@ -102,13 +223,14 @@ where
if let Some(ref mut event) = event {
libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
} else {
libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
libc::epoll_ctl(epfd, op as c_int, fd, std::ptr::null_mut())
}
};
Errno::result(res).map(drop)
}
}
#[deprecated(since = "0.27.0", note = "Use Epoll::wait() instead")]
#[inline]
pub fn epoll_wait(
epfd: RawFd,

213
third_party/rust/nix/src/sys/event.rs поставляемый
Просмотреть файл

@ -1,5 +1,7 @@
/* TOOD: Implement for other kqueue based systems
*/
//! Kernel event notification mechanism
//!
//! # See Also
//! [kqueue(2)](https://www.freebsd.org/cgi/man.cgi?query=kqueue)
use crate::{Errno, Result};
#[cfg(not(target_os = "netbsd"))]
@ -8,16 +10,74 @@ use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t};
use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t};
use std::convert::TryInto;
use std::mem;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
use std::ptr;
// Redefine kevent in terms of programmer-friendly enums and bitfields.
/// A kernel event queue. Used to notify a process of various asynchronous
/// events.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct KEvent {
kevent: libc::kevent,
}
/// A kernel event queue.
///
/// Used by the kernel to notify the process of various types of asynchronous
/// events.
#[repr(transparent)]
#[derive(Debug)]
pub struct Kqueue(OwnedFd);
impl Kqueue {
/// Create a new kernel event queue.
pub fn new() -> Result<Self> {
let res = unsafe { libc::kqueue() };
Errno::result(res).map(|fd| unsafe { Self(OwnedFd::from_raw_fd(fd)) })
}
/// Register new events with the kqueue, and return any pending events to
/// the user.
///
/// This method will block until either the timeout expires, or a registered
/// event triggers a notification.
///
/// # Arguments
/// - `changelist` - Any new kevents to register for notifications.
/// - `eventlist` - Storage space for the kernel to return notifications.
/// - `timeout` - An optional timeout.
///
/// # Returns
/// Returns the number of events placed in the `eventlist`. If an error
/// occurs while processing an element of the `changelist` and there is
/// enough room in the `eventlist`, then the event will be placed in the
/// `eventlist` with `EV_ERROR` set in `flags` and the system error in
/// `data`.
pub fn kevent(
&self,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_opt: Option<timespec>,
) -> Result<usize> {
let res = unsafe {
libc::kevent(
self.0.as_raw_fd(),
changelist.as_ptr() as *const libc::kevent,
changelist.len() as type_of_nchanges,
eventlist.as_mut_ptr() as *mut libc::kevent,
eventlist.len() as type_of_nchanges,
if let Some(ref timeout) = timeout_opt {
timeout as *const timespec
} else {
ptr::null()
},
)
};
Errno::result(res).map(|r| r as usize)
}
}
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
@ -26,7 +86,7 @@ pub struct KEvent {
target_os = "openbsd"
))]
type type_of_udata = *mut libc::c_void;
#[cfg(any(target_os = "netbsd"))]
#[cfg(target_os = "netbsd")]
type type_of_udata = intptr_t;
#[cfg(target_os = "netbsd")]
@ -37,22 +97,34 @@ libc_enum! {
#[cfg_attr(target_os = "netbsd", repr(u32))]
#[cfg_attr(not(target_os = "netbsd"), repr(i16))]
#[non_exhaustive]
/// Kqueue filter types. These are all the different types of event that a
/// kqueue can notify for.
pub enum EventFilter {
/// Notifies on the completion of a POSIX AIO operation.
EVFILT_AIO,
/// Returns whenever there is no remaining data in the write buffer
#[cfg(target_os = "freebsd")]
/// Returns whenever there is no remaining data in the write buffer
EVFILT_EMPTY,
#[cfg(target_os = "dragonfly")]
/// Takes a descriptor as the identifier, and returns whenever one of
/// the specified exceptional conditions has occurred on the descriptor.
EVFILT_EXCEPT,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"))]
/// Establishes a file system monitor.
EVFILT_FS,
#[cfg(target_os = "freebsd")]
/// Notify for completion of a list of POSIX AIO operations.
/// # See Also
/// [lio_listio(2)](https://www.freebsd.org/cgi/man.cgi?query=lio_listio)
EVFILT_LIO,
#[cfg(any(target_os = "ios", target_os = "macos"))]
/// Mach portsets
EVFILT_MACHPORT,
/// Notifies when a process performs one or more of the requested
/// events.
EVFILT_PROC,
/// Returns events associated with the process referenced by a given
/// process descriptor, created by `pdfork()`. The events to monitor are:
@ -60,20 +132,31 @@ libc_enum! {
/// - NOTE_EXIT: the process has exited. The exit status will be stored in data.
#[cfg(target_os = "freebsd")]
EVFILT_PROCDESC,
/// Takes a file descriptor as the identifier, and notifies whenever
/// there is data available to read.
EVFILT_READ,
/// Returns whenever an asynchronous `sendfile()` call completes.
#[cfg(target_os = "freebsd")]
#[doc(hidden)]
#[deprecated(since = "0.27.0", note = "Never fully implemented by the OS")]
EVFILT_SENDFILE,
/// Takes a signal number to monitor as the identifier and notifies when
/// the given signal is delivered to the process.
EVFILT_SIGNAL,
/// Establishes a timer and notifies when the timer expires.
EVFILT_TIMER,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos"))]
/// Notifies only when explicitly requested by the user.
EVFILT_USER,
#[cfg(any(target_os = "ios", target_os = "macos"))]
/// Virtual memory events
EVFILT_VM,
/// Notifies when a requested event happens on a specified file.
EVFILT_VNODE,
/// Takes a file descriptor as the identifier, and notifies whenever
/// it is possible to write to the file without blocking.
EVFILT_WRITE,
}
impl TryFrom<type_of_event_filter>
@ -86,131 +169,194 @@ libc_enum! {
target_os = "macos",
target_os = "openbsd"
))]
#[doc(hidden)]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd"))]
#[cfg(target_os = "netbsd")]
#[doc(hidden)]
pub type type_of_event_flag = u32;
libc_bitflags! {
/// Event flags. See the man page for details.
// There's no useful documentation we can write for the individual flags
// that wouldn't simply be repeating the man page.
pub struct EventFlag: type_of_event_flag {
#[allow(missing_docs)]
EV_ADD;
#[allow(missing_docs)]
EV_CLEAR;
#[allow(missing_docs)]
EV_DELETE;
#[allow(missing_docs)]
EV_DISABLE;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "netbsd", target_os = "openbsd"))]
#[allow(missing_docs)]
EV_DISPATCH;
#[cfg(target_os = "freebsd")]
#[allow(missing_docs)]
EV_DROP;
#[allow(missing_docs)]
EV_ENABLE;
#[allow(missing_docs)]
EV_EOF;
#[allow(missing_docs)]
EV_ERROR;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
EV_FLAG0;
#[allow(missing_docs)]
EV_FLAG1;
#[cfg(target_os = "dragonfly")]
#[allow(missing_docs)]
EV_NODATA;
#[allow(missing_docs)]
EV_ONESHOT;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
EV_OOBAND;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
EV_POLL;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos",
target_os = "netbsd", target_os = "openbsd"))]
#[allow(missing_docs)]
EV_RECEIPT;
}
}
libc_bitflags!(
/// Filter-specific flags. See the man page for details.
// There's no useful documentation we can write for the individual flags
// that wouldn't simply be repeating the man page.
#[allow(missing_docs)]
pub struct FilterFlag: u32 {
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_ABSOLUTE;
#[allow(missing_docs)]
NOTE_ATTRIB;
#[allow(missing_docs)]
NOTE_CHILD;
#[allow(missing_docs)]
NOTE_DELETE;
#[cfg(target_os = "openbsd")]
#[allow(missing_docs)]
NOTE_EOF;
#[allow(missing_docs)]
NOTE_EXEC;
#[allow(missing_docs)]
NOTE_EXIT;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_EXITSTATUS;
#[allow(missing_docs)]
NOTE_EXTEND;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFAND;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFCOPY;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFCTRLMASK;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFLAGSMASK;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFNOP;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_FFOR;
#[allow(missing_docs)]
NOTE_FORK;
#[allow(missing_docs)]
NOTE_LINK;
#[allow(missing_docs)]
NOTE_LOWAT;
#[cfg(target_os = "freebsd")]
#[allow(missing_docs)]
NOTE_MSECONDS;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_NONE;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_NSECONDS;
#[cfg(target_os = "dragonfly")]
#[allow(missing_docs)]
NOTE_OOB;
#[allow(missing_docs)]
NOTE_PCTRLMASK;
#[allow(missing_docs)]
NOTE_PDATAMASK;
#[allow(missing_docs)]
NOTE_RENAME;
#[allow(missing_docs)]
NOTE_REVOKE;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_SECONDS;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_SIGNAL;
#[allow(missing_docs)]
NOTE_TRACK;
#[allow(missing_docs)]
NOTE_TRACKERR;
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly"))]
#[allow(missing_docs)]
NOTE_TRIGGER;
#[cfg(target_os = "openbsd")]
#[allow(missing_docs)]
NOTE_TRUNCATE;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
#[allow(missing_docs)]
NOTE_USECONDS;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_VM_ERROR;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_VM_PRESSURE;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(missing_docs)]
NOTE_VM_PRESSURE_TERMINATE;
#[allow(missing_docs)]
NOTE_WRITE;
}
);
pub fn kqueue() -> Result<RawFd> {
let res = unsafe { libc::kqueue() };
Errno::result(res)
#[allow(missing_docs)]
#[deprecated(since = "0.27.0", note = "Use KEvent::new instead")]
pub fn kqueue() -> Result<Kqueue> {
Kqueue::new()
}
// KEvent can't derive Send because on some operating systems, udata is defined
@ -220,6 +366,8 @@ unsafe impl Send for KEvent {}
impl KEvent {
#[allow(clippy::needless_update)] // Not needless on all platforms.
/// Construct a new `KEvent` suitable for submission to the kernel via the
/// `changelist` argument of [`Kqueue::kevent`].
pub fn new(
ident: uintptr_t,
filter: EventFilter,
@ -242,33 +390,46 @@ impl KEvent {
}
}
/// Value used to identify this event. The exact interpretation is
/// determined by the attached filter, but often is a raw file descriptor.
pub fn ident(&self) -> uintptr_t {
self.kevent.ident
}
/// Identifies the kernel filter used to process this event.
///
/// Will only return an error if the kernel reports an event via a filter
/// that is unknown to Nix.
pub fn filter(&self) -> Result<EventFilter> {
self.kevent.filter.try_into()
}
/// Flags control what the kernel will do when this event is added with
/// [`Kqueue::kevent`].
pub fn flags(&self) -> EventFlag {
EventFlag::from_bits(self.kevent.flags).unwrap()
}
/// Filter-specific flags.
pub fn fflags(&self) -> FilterFlag {
FilterFlag::from_bits(self.kevent.fflags).unwrap()
}
/// Filter-specific data value.
pub fn data(&self) -> intptr_t {
self.kevent.data as intptr_t
}
/// Opaque user-defined value passed through the kernel unchanged.
pub fn udata(&self) -> intptr_t {
self.kevent.udata as intptr_t
}
}
#[allow(missing_docs)]
#[deprecated(since = "0.27.0", note = "Use Kqueue::kevent instead")]
pub fn kevent(
kq: RawFd,
kq: &Kqueue,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_ms: usize,
@ -279,7 +440,7 @@ pub fn kevent(
tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long,
};
kevent_ts(kq, changelist, eventlist, Some(timeout))
kq.kevent(changelist, eventlist, Some(timeout))
}
#[cfg(any(
@ -293,30 +454,20 @@ type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;
#[allow(missing_docs)]
#[deprecated(since = "0.27.0", note = "Use Kqueue::kevent instead")]
pub fn kevent_ts(
kq: RawFd,
kq: &Kqueue,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_opt: Option<timespec>,
) -> Result<usize> {
let res = unsafe {
libc::kevent(
kq,
changelist.as_ptr() as *const libc::kevent,
changelist.len() as type_of_nchanges,
eventlist.as_mut_ptr() as *mut libc::kevent,
eventlist.len() as type_of_nchanges,
if let Some(ref timeout) = timeout_opt {
timeout as *const timespec
} else {
ptr::null()
},
)
};
Errno::result(res).map(|r| r as usize)
kq.kevent(changelist, eventlist, timeout_opt)
}
/// Modify an existing [`KEvent`].
// Probably should deprecate. Would anybody ever use it over `KEvent::new`?
#[deprecated(since = "0.27.0", note = "Use Kqueue::kevent instead")]
#[inline]
pub fn ev_set(
ev: &mut KEvent,

6
third_party/rust/nix/src/sys/eventfd.rs поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
use crate::errno::Errno;
use crate::Result;
use std::os::unix::io::RawFd;
use std::os::unix::io::{FromRawFd, OwnedFd};
libc_bitflags! {
pub struct EfdFlags: libc::c_int {
@ -10,8 +10,8 @@ libc_bitflags! {
}
}
pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
let res = unsafe { libc::eventfd(initval, flags.bits()) };
Errno::result(res).map(|r| r as RawFd)
Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) })
}

32
third_party/rust/nix/src/sys/inotify.rs поставляемый
Просмотреть файл

@ -32,7 +32,7 @@ use libc::{c_char, c_int};
use std::ffi::{CStr, OsStr, OsString};
use std::mem::{size_of, MaybeUninit};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
use std::ptr;
libc_bitflags! {
@ -101,9 +101,9 @@ libc_bitflags! {
/// An inotify instance. This is also a file descriptor, you can feed it to
/// other interfaces consuming file descriptors, epoll for example.
#[derive(Debug, Clone, Copy)]
#[derive(Debug)]
pub struct Inotify {
fd: RawFd,
fd: OwnedFd,
}
/// This object is returned when you create a new watch on an inotify instance.
@ -143,7 +143,7 @@ impl Inotify {
pub fn init(flags: InitFlags) -> Result<Inotify> {
let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) });
res.map(|fd| Inotify { fd })
res.map(|fd| Inotify { fd: unsafe { OwnedFd::from_raw_fd(fd) } })
}
/// Adds a new watch on the target file or directory.
@ -152,12 +152,12 @@ impl Inotify {
///
/// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
pub fn add_watch<P: ?Sized + NixPath>(
self,
&self,
path: &P,
mask: AddWatchFlags,
) -> Result<WatchDescriptor> {
let res = path.with_nix_path(|cstr| unsafe {
libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
libc::inotify_add_watch(self.fd.as_raw_fd(), cstr.as_ptr(), mask.bits())
})?;
Errno::result(res).map(|wd| WatchDescriptor { wd })
@ -169,7 +169,7 @@ impl Inotify {
/// Returns an EINVAL error if the watch descriptor is invalid.
///
/// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
cfg_if! {
if #[cfg(target_os = "linux")] {
let arg = wd.wd;
@ -177,7 +177,7 @@ impl Inotify {
let arg = wd.wd as u32;
}
}
let res = unsafe { libc::inotify_rm_watch(self.fd, arg) };
let res = unsafe { libc::inotify_rm_watch(self.fd.as_raw_fd(), arg) };
Errno::result(res).map(drop)
}
@ -188,14 +188,14 @@ impl Inotify {
///
/// Returns as many events as available. If the call was non blocking and no
/// events could be read then the EAGAIN error is returned.
pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
pub fn read_events(&self) -> Result<Vec<InotifyEvent>> {
let header_size = size_of::<libc::inotify_event>();
const BUFSIZ: usize = 4096;
let mut buffer = [0u8; BUFSIZ];
let mut events = Vec::new();
let mut offset = 0;
let nread = read(self.fd, &mut buffer)?;
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
while (nread - offset) >= header_size {
let event = unsafe {
@ -235,14 +235,14 @@ impl Inotify {
}
}
impl AsRawFd for Inotify {
fn as_raw_fd(&self) -> RawFd {
self.fd
impl FromRawFd for Inotify {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Inotify { fd: OwnedFd::from_raw_fd(fd) }
}
}
impl FromRawFd for Inotify {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Inotify { fd }
impl AsFd for Inotify {
fn as_fd(&'_ self) -> BorrowedFd<'_> {
self.fd.as_fd()
}
}

78
third_party/rust/nix/src/sys/ioctl/linux.rs поставляемый
Просмотреть файл

@ -1,3 +1,5 @@
use cfg_if::cfg_if;
/// The datatype used for the ioctl number
#[cfg(any(target_os = "android", target_env = "musl"))]
#[doc(hidden)]
@ -14,47 +16,41 @@ pub const NRBITS: ioctl_num_type = 8;
#[doc(hidden)]
pub const TYPEBITS: ioctl_num_type = 8;
#[cfg(any(
target_arch = "mips",
target_arch = "mips64",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc64"
))]
mod consts {
#[doc(hidden)]
pub const NONE: u8 = 1;
#[doc(hidden)]
pub const READ: u8 = 2;
#[doc(hidden)]
pub const WRITE: u8 = 4;
#[doc(hidden)]
pub const SIZEBITS: u8 = 13;
#[doc(hidden)]
pub const DIRBITS: u8 = 3;
}
// "Generic" ioctl protocol
#[cfg(any(
target_arch = "x86",
target_arch = "arm",
target_arch = "s390x",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64"
))]
mod consts {
#[doc(hidden)]
pub const NONE: u8 = 0;
#[doc(hidden)]
pub const READ: u8 = 2;
#[doc(hidden)]
pub const WRITE: u8 = 1;
#[doc(hidden)]
pub const SIZEBITS: u8 = 14;
#[doc(hidden)]
pub const DIRBITS: u8 = 2;
cfg_if! {
if #[cfg(any(
target_arch = "mips",
target_arch = "mips64",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "sparc64"
))] {
mod consts {
#[doc(hidden)]
pub const NONE: u8 = 1;
#[doc(hidden)]
pub const READ: u8 = 2;
#[doc(hidden)]
pub const WRITE: u8 = 4;
#[doc(hidden)]
pub const SIZEBITS: u8 = 13;
#[doc(hidden)]
pub const DIRBITS: u8 = 3;
}
} else {
// "Generic" ioctl protocol
mod consts {
#[doc(hidden)]
pub const NONE: u8 = 0;
#[doc(hidden)]
pub const READ: u8 = 2;
#[doc(hidden)]
pub const WRITE: u8 = 1;
#[doc(hidden)]
pub const SIZEBITS: u8 = 14;
#[doc(hidden)]
pub const DIRBITS: u8 = 2;
}
}
}
pub use self::consts::*;

6
third_party/rust/nix/src/sys/ioctl/mod.rs поставляемый
Просмотреть файл

@ -712,7 +712,7 @@ macro_rules! ioctl_read_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
}
)
}
@ -751,7 +751,7 @@ macro_rules! ioctl_write_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &[$ty])
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
}
)
}
@ -780,7 +780,7 @@ macro_rules! ioctl_readwrite_buf {
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data))
}
)
}

7
third_party/rust/nix/src/sys/memfd.rs поставляемый
Просмотреть файл

@ -1,7 +1,7 @@
//! Interfaces for managing memory-backed files.
use cfg_if::cfg_if;
use std::os::unix::io::RawFd;
use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
use crate::errno::Errno;
use crate::Result;
@ -40,7 +40,8 @@ libc_bitflags!(
/// For more information, see [`memfd_create(2)`].
///
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
#[inline] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined
pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> {
let res = unsafe {
cfg_if! {
if #[cfg(all(
@ -60,5 +61,5 @@ pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
}
};
Errno::result(res).map(|r| r as RawFd)
Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r as RawFd) })
}

36
third_party/rust/nix/src/sys/mman.rs поставляемый
Просмотреть файл

@ -8,7 +8,7 @@ use crate::Result;
#[cfg(feature = "fs")]
use crate::{fcntl::OFlag, sys::stat::Mode};
use libc::{self, c_int, c_void, off_t, size_t};
use std::{os::unix::io::RawFd, num::NonZeroUsize};
use std::{num::NonZeroUsize, os::unix::io::{AsRawFd, AsFd}};
libc_bitflags! {
/// Desired memory protection of a memory mapping.
@ -82,7 +82,7 @@ libc_bitflags! {
/// Do not reserve swap space for this mapping.
///
/// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MAP_NORESERVE;
/// Populate page tables for a mapping.
@ -282,6 +282,8 @@ libc_enum! {
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_DODUMP,
/// Specify that the application no longer needs the pages in the given range.
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MADV_FREE,
/// Request that the system not flush the current range to disk unless it needs to.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
@ -416,20 +418,20 @@ pub fn munlockall() -> Result<()> {
/// See the [`mmap(2)`] man page for detailed requirements.
///
/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
pub unsafe fn mmap(
pub unsafe fn mmap<F: AsFd>(
addr: Option<NonZeroUsize>,
length: NonZeroUsize,
prot: ProtFlags,
flags: MapFlags,
fd: RawFd,
f: Option<F>,
offset: off_t,
) -> Result<*mut c_void> {
let ptr = addr.map_or(
std::ptr::null_mut(),
|a| usize::from(a) as *mut c_void
);
let ret = libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset);
let ptr =
addr.map_or(std::ptr::null_mut(), |a| usize::from(a) as *mut c_void);
let fd = f.map(|f| f.as_fd().as_raw_fd()).unwrap_or(-1);
let ret =
libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset);
if ret == libc::MAP_FAILED {
Err(Errno::last())
@ -519,11 +521,12 @@ pub unsafe fn madvise(
/// # use nix::libc::size_t;
/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
/// # use std::ptr;
/// # use std::os::unix::io::BorrowedFd;
/// const ONE_K: size_t = 1024;
/// let one_k_non_zero = std::num::NonZeroUsize::new(ONE_K).unwrap();
/// let mut slice: &mut [u8] = unsafe {
/// let mem = mmap(None, one_k_non_zero, ProtFlags::PROT_NONE,
/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
/// let mem = mmap::<BorrowedFd>(None, one_k_non_zero, ProtFlags::PROT_NONE,
/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, None, 0).unwrap();
/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
/// };
@ -567,9 +570,11 @@ pub fn shm_open<P>(
name: &P,
flag: OFlag,
mode: Mode
) -> Result<RawFd>
) -> Result<std::os::unix::io::OwnedFd>
where P: ?Sized + NixPath
{
use std::os::unix::io::{FromRawFd, OwnedFd};
let ret = name.with_nix_path(|cstr| {
#[cfg(any(target_os = "macos", target_os = "ios"))]
unsafe {
@ -581,7 +586,10 @@ pub fn shm_open<P>(
}
})?;
Errno::result(ret)
match ret {
-1 => Err(Errno::last()),
fd => Ok(unsafe{ OwnedFd::from_raw_fd(fd) })
}
}
}

9
third_party/rust/nix/src/sys/mod.rs поставляемый
Просмотреть файл

@ -25,7 +25,6 @@ feature! {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
#[allow(missing_docs)]
pub mod event;
#[cfg(any(target_os = "android", target_os = "linux"))]
@ -68,6 +67,12 @@ feature! {
pub mod personality;
}
#[cfg(target_os = "linux")]
feature! {
#![feature = "process"]
pub mod prctl;
}
feature! {
#![feature = "pthread"]
pub mod pthread;
@ -111,7 +116,6 @@ feature! {
pub mod resource;
}
#[cfg(not(target_os = "redox"))]
feature! {
#![feature = "poll"]
pub mod select;
@ -139,7 +143,6 @@ feature! {
pub mod signalfd;
}
#[cfg(not(target_os = "redox"))]
feature! {
#![feature = "socket"]
#[allow(missing_docs)]

5
third_party/rust/nix/src/sys/personality.rs поставляемый
Просмотреть файл

@ -80,7 +80,10 @@ pub fn get() -> Result<Persona> {
///
/// Example:
///
/// ```
// Disable test on aarch64 until we know why it fails.
// https://github.com/nix-rust/nix/issues/2060
#[cfg_attr(target_arch = "aarch64", doc = " ```no_run")]
#[cfg_attr(not(target_arch = "aarch64"), doc = " ```")]
/// # use nix::sys::personality::{self, Persona};
/// let mut pers = personality::get().unwrap();
/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE));

208
third_party/rust/nix/src/sys/prctl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,208 @@
//! prctl is a Linux-only API for performing operations on a process or thread.
//!
//! Note that careless use of some prctl() operations can confuse the user-space run-time
//! environment, so these operations should be used with care.
//!
//! For more documentation, please read [prctl(2)](https://man7.org/linux/man-pages/man2/prctl.2.html).
use crate::errno::Errno;
use crate::sys::signal::Signal;
use crate::Result;
use libc::{c_int, c_ulong};
use std::convert::TryFrom;
use std::ffi::{CStr, CString};
libc_enum! {
/// The type of hardware memory corruption kill policy for the thread.
#[repr(i32)]
#[non_exhaustive]
#[allow(non_camel_case_types)]
pub enum PrctlMCEKillPolicy {
/// The thread will receive SIGBUS as soon as a memory corruption is detected.
PR_MCE_KILL_EARLY,
/// The process is killed only when it accesses a corrupted page.
PR_MCE_KILL_LATE,
/// Uses the system-wide default.
PR_MCE_KILL_DEFAULT,
}
impl TryFrom<i32>
}
fn prctl_set_bool(option: c_int, status: bool) -> Result<()> {
let res = unsafe { libc::prctl(option, status as c_ulong, 0, 0, 0) };
Errno::result(res).map(drop)
}
fn prctl_get_bool(option: c_int) -> Result<bool> {
let res = unsafe { libc::prctl(option, 0, 0, 0, 0) };
Errno::result(res).map(|res| res != 0)
}
/// Set the "child subreaper" attribute for this process
pub fn set_child_subreaper(attribute: bool) -> Result<()> {
prctl_set_bool(libc::PR_SET_CHILD_SUBREAPER, attribute)
}
/// Get the "child subreaper" attribute for this process
pub fn get_child_subreaper() -> Result<bool> {
// prctl writes into this var
let mut subreaper: c_int = 0;
let res = unsafe { libc::prctl(libc::PR_GET_CHILD_SUBREAPER, &mut subreaper, 0, 0, 0) };
Errno::result(res).map(|_| subreaper != 0)
}
/// Set the dumpable attribute which determines if core dumps are created for this process.
pub fn set_dumpable(attribute: bool) -> Result<()> {
prctl_set_bool(libc::PR_SET_DUMPABLE, attribute)
}
/// Get the dumpable attribute for this process.
pub fn get_dumpable() -> Result<bool> {
prctl_get_bool(libc::PR_GET_DUMPABLE)
}
/// Set the "keep capabilities" attribute for this process. This causes the thread to retain
/// capabilities even if it switches its UID to a nonzero value.
pub fn set_keepcaps(attribute: bool) -> Result<()> {
prctl_set_bool(libc::PR_SET_KEEPCAPS, attribute)
}
/// Get the "keep capabilities" attribute for this process
pub fn get_keepcaps() -> Result<bool> {
prctl_get_bool(libc::PR_GET_KEEPCAPS)
}
/// Clear the thread memory corruption kill policy and use the system-wide default
pub fn clear_mce_kill() -> Result<()> {
let res = unsafe { libc::prctl(libc::PR_MCE_KILL, libc::PR_MCE_KILL_CLEAR, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Set the thread memory corruption kill policy
pub fn set_mce_kill(policy: PrctlMCEKillPolicy) -> Result<()> {
let res = unsafe {
libc::prctl(
libc::PR_MCE_KILL,
libc::PR_MCE_KILL_SET,
policy as c_ulong,
0,
0,
)
};
Errno::result(res).map(drop)
}
/// Get the thread memory corruption kill policy
pub fn get_mce_kill() -> Result<PrctlMCEKillPolicy> {
let res = unsafe { libc::prctl(libc::PR_MCE_KILL_GET, 0, 0, 0, 0) };
match Errno::result(res) {
Ok(val) => Ok(PrctlMCEKillPolicy::try_from(val)?),
Err(e) => Err(e),
}
}
/// Set the parent-death signal of the calling process. This is the signal that the calling process
/// will get when its parent dies.
pub fn set_pdeathsig<T: Into<Option<Signal>>>(signal: T) -> Result<()> {
let sig = match signal.into() {
Some(s) => s as c_int,
None => 0,
};
let res = unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, sig, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Returns the current parent-death signal
pub fn get_pdeathsig() -> Result<Option<Signal>> {
// prctl writes into this var
let mut sig: c_int = 0;
let res = unsafe { libc::prctl(libc::PR_GET_PDEATHSIG, &mut sig, 0, 0, 0) };
match Errno::result(res) {
Ok(_) => Ok(match sig {
0 => None,
_ => Some(Signal::try_from(sig)?),
}),
Err(e) => Err(e),
}
}
/// Set the name of the calling thread. Strings longer than 15 bytes will be truncated.
pub fn set_name(name: &CStr) -> Result<()> {
let res = unsafe { libc::prctl(libc::PR_SET_NAME, name.as_ptr(), 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Return the name of the calling thread
pub fn get_name() -> Result<CString> {
// Size of buffer determined by linux/sched.h TASK_COMM_LEN
let buf = [0u8; 16];
let res = unsafe { libc::prctl(libc::PR_GET_NAME, &buf, 0, 0, 0) };
let len = buf.iter().position(|&c| c == 0).unwrap_or(buf.len());
let name = CStr::from_bytes_with_nul(&buf[..=len]).map_err(|_| Errno::EINVAL)?;
Errno::result(res).map(|_| name.to_owned())
}
/// Sets the timer slack value for the calling thread. Timer slack is used by the kernel to group
/// timer expirations and make them the supplied amount of nanoseconds late.
pub fn set_timerslack(ns: u64) -> Result<()> {
let res = unsafe { libc::prctl(libc::PR_SET_TIMERSLACK, ns, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Get the timerslack for the calling thread.
pub fn get_timerslack() -> Result<i32> {
let res = unsafe { libc::prctl(libc::PR_GET_TIMERSLACK, 0, 0, 0, 0) };
Errno::result(res)
}
/// Disable all performance counters attached to the calling process.
pub fn task_perf_events_disable() -> Result<()> {
let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_DISABLE, 0, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Enable all performance counters attached to the calling process.
pub fn task_perf_events_enable() -> Result<()> {
let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_ENABLE, 0, 0, 0, 0) };
Errno::result(res).map(drop)
}
/// Set the calling threads "no new privs" attribute. Once set this option can not be unset.
pub fn set_no_new_privs() -> Result<()> {
prctl_set_bool(libc::PR_SET_NO_NEW_PRIVS, true) // Cannot be unset
}
/// Get the "no new privs" attribute for the calling thread.
pub fn get_no_new_privs() -> Result<bool> {
prctl_get_bool(libc::PR_GET_NO_NEW_PRIVS)
}
/// Set the state of the "THP disable" flag for the calling thread. Setting this disables
/// transparent huge pages.
pub fn set_thp_disable(flag: bool) -> Result<()> {
prctl_set_bool(libc::PR_SET_THP_DISABLE, flag)
}
/// Get the "THP disable" flag for the calling thread.
pub fn get_thp_disable() -> Result<bool> {
prctl_get_bool(libc::PR_GET_THP_DISABLE)
}

18
third_party/rust/nix/src/sys/ptrace/linux.rs поставляемый
Просмотреть файл

@ -269,7 +269,7 @@ unsafe fn ptrace_other(
.map(|_| 0)
}
/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
/// Set options, as with `ptrace(PTRACE_SETOPTIONS, ...)`.
pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
let res = unsafe {
libc::ptrace(
@ -282,17 +282,17 @@ pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
Errno::result(res).map(drop)
}
/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG, ...)`
pub fn getevent(pid: Pid) -> Result<c_long> {
ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
}
/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO, ...)`
pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
}
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO, ...)`
pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
let ret = unsafe {
Errno::clear();
@ -517,12 +517,14 @@ pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
}
}
/// Reads a word from a processes memory at the given address
/// Reads a word from a processes memory at the given address, as with
/// ptrace(PTRACE_PEEKDATA, ...)
pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut())
}
/// Writes a word into the processes memory at the given address
/// Writes a word into the processes memory at the given address, as with
/// ptrace(PTRACE_POKEDATA, ...)
///
/// # Safety
///
@ -536,13 +538,13 @@ pub unsafe fn write(
ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
}
/// Reads a word from a user area at `offset`.
/// Reads a word from a user area at `offset`, as with ptrace(PTRACE_PEEKUSER, ...).
/// The user struct definition can be found in `/usr/include/sys/user.h`.
pub fn read_user(pid: Pid, offset: AddressType) -> Result<c_long> {
ptrace_peek(Request::PTRACE_PEEKUSER, pid, offset, ptr::null_mut())
}
/// Writes a word to a user area at `offset`.
/// Writes a word to a user area at `offset`, as with ptrace(PTRACE_POKEUSER, ...).
/// The user struct definition can be found in `/usr/include/sys/user.h`.
///
/// # Safety

2
third_party/rust/nix/src/sys/ptrace/mod.rs поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
///! Provides helpers for making ptrace system calls
//! Provides helpers for making ptrace system calls
#[cfg(any(target_os = "android", target_os = "linux"))]
mod linux;

3
third_party/rust/nix/src/sys/quota.rs поставляемый
Просмотреть файл

@ -21,9 +21,8 @@ use std::{mem, ptr};
struct QuotaCmd(QuotaSubCmd, QuotaType);
impl QuotaCmd {
#[allow(unused_unsafe)]
fn as_int(&self) -> c_int {
unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
libc::QCMD(self.0 as i32, self.1 as i32)
}
}

4
third_party/rust/nix/src/sys/resource.rs поставляемый
Просмотреть файл

@ -20,6 +20,7 @@ cfg_if! {
target_os = "ios",
target_os = "android",
target_os = "dragonfly",
target_os = "aix",
all(target_os = "linux", not(target_env = "gnu"))
))]{
use libc::rlimit;
@ -51,6 +52,7 @@ libc_enum! {
target_os = "ios",
target_os = "android",
target_os = "dragonfly",
target_os = "aix",
all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
), repr(i32))]
#[non_exhaustive]
@ -115,6 +117,7 @@ libc_enum! {
target_os = "netbsd",
target_os = "openbsd",
target_os = "linux",
target_os = "aix",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
/// The maximum number of simultaneous processes for this user id.
@ -131,6 +134,7 @@ libc_enum! {
target_os = "netbsd",
target_os = "openbsd",
target_os = "linux",
target_os = "aix",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
/// When there is memory pressure and swap is available, prioritize

311
third_party/rust/nix/src/sys/select.rs поставляемый
Просмотреть файл

@ -7,7 +7,7 @@ use std::convert::TryFrom;
use std::iter::FusedIterator;
use std::mem;
use std::ops::Range;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::ptr::{null, null_mut};
pub use libc::FD_SETSIZE;
@ -15,7 +15,10 @@ pub use libc::FD_SETSIZE;
/// Contains a set of file descriptors used by [`select`]
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct FdSet(libc::fd_set);
pub struct FdSet<'fd> {
set: libc::fd_set,
_fd: std::marker::PhantomData<BorrowedFd<'fd>>,
}
fn assert_fd_valid(fd: RawFd) {
assert!(
@ -24,37 +27,40 @@ fn assert_fd_valid(fd: RawFd) {
);
}
impl FdSet {
impl<'fd> FdSet<'fd> {
/// Create an empty `FdSet`
pub fn new() -> FdSet {
pub fn new() -> FdSet<'fd> {
let mut fdset = mem::MaybeUninit::uninit();
unsafe {
libc::FD_ZERO(fdset.as_mut_ptr());
FdSet(fdset.assume_init())
Self {
set: fdset.assume_init(),
_fd: std::marker::PhantomData,
}
}
}
/// Add a file descriptor to an `FdSet`
pub fn insert(&mut self, fd: RawFd) {
assert_fd_valid(fd);
unsafe { libc::FD_SET(fd, &mut self.0) };
pub fn insert<Fd: AsFd>(&mut self, fd: &'fd Fd) {
assert_fd_valid(fd.as_fd().as_raw_fd());
unsafe { libc::FD_SET(fd.as_fd().as_raw_fd(), &mut self.set) };
}
/// Remove a file descriptor from an `FdSet`
pub fn remove(&mut self, fd: RawFd) {
assert_fd_valid(fd);
unsafe { libc::FD_CLR(fd, &mut self.0) };
pub fn remove<Fd: AsFd>(&mut self, fd: &'fd Fd) {
assert_fd_valid(fd.as_fd().as_raw_fd());
unsafe { libc::FD_CLR(fd.as_fd().as_raw_fd(), &mut self.set) };
}
/// Test an `FdSet` for the presence of a certain file descriptor.
pub fn contains(&self, fd: RawFd) -> bool {
assert_fd_valid(fd);
unsafe { libc::FD_ISSET(fd, &self.0) }
pub fn contains<Fd: AsFd>(&self, fd: &'fd Fd) -> bool {
assert_fd_valid(fd.as_fd().as_raw_fd());
unsafe { libc::FD_ISSET(fd.as_fd().as_raw_fd(), &self.set) }
}
/// Remove all file descriptors from this `FdSet`.
pub fn clear(&mut self) {
unsafe { libc::FD_ZERO(&mut self.0) };
unsafe { libc::FD_ZERO(&mut self.set) };
}
/// Finds the highest file descriptor in the set.
@ -66,15 +72,18 @@ impl FdSet {
/// # Example
///
/// ```
/// # use std::os::unix::io::{AsRawFd, BorrowedFd};
/// # use nix::sys::select::FdSet;
/// let fd_four = unsafe {BorrowedFd::borrow_raw(4)};
/// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)};
/// let mut set = FdSet::new();
/// set.insert(4);
/// set.insert(9);
/// assert_eq!(set.highest(), Some(9));
/// set.insert(&fd_four);
/// set.insert(&fd_nine);
/// assert_eq!(set.highest().map(|borrowed_fd|borrowed_fd.as_raw_fd()), Some(9));
/// ```
///
/// [`select`]: fn.select.html
pub fn highest(&self) -> Option<RawFd> {
pub fn highest(&self) -> Option<BorrowedFd<'_>> {
self.fds(None).next_back()
}
@ -88,11 +97,13 @@ impl FdSet {
///
/// ```
/// # use nix::sys::select::FdSet;
/// # use std::os::unix::io::RawFd;
/// # use std::os::unix::io::{AsRawFd, BorrowedFd, RawFd};
/// let mut set = FdSet::new();
/// set.insert(4);
/// set.insert(9);
/// let fds: Vec<RawFd> = set.fds(None).collect();
/// let fd_four = unsafe {BorrowedFd::borrow_raw(4)};
/// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)};
/// set.insert(&fd_four);
/// set.insert(&fd_nine);
/// let fds: Vec<RawFd> = set.fds(None).map(|borrowed_fd|borrowed_fd.as_raw_fd()).collect();
/// assert_eq!(fds, vec![4, 9]);
/// ```
#[inline]
@ -104,7 +115,7 @@ impl FdSet {
}
}
impl Default for FdSet {
impl<'fd> Default for FdSet<'fd> {
fn default() -> Self {
Self::new()
}
@ -112,18 +123,19 @@ impl Default for FdSet {
/// Iterator over `FdSet`.
#[derive(Debug)]
pub struct Fds<'a> {
set: &'a FdSet,
pub struct Fds<'a, 'fd> {
set: &'a FdSet<'fd>,
range: Range<usize>,
}
impl<'a> Iterator for Fds<'a> {
type Item = RawFd;
impl<'a, 'fd> Iterator for Fds<'a, 'fd> {
type Item = BorrowedFd<'fd>;
fn next(&mut self) -> Option<RawFd> {
fn next(&mut self) -> Option<Self::Item> {
for i in &mut self.range {
if self.set.contains(i as RawFd) {
return Some(i as RawFd);
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
if self.set.contains(&borrowed_i) {
return Some(borrowed_i);
}
}
None
@ -136,19 +148,20 @@ impl<'a> Iterator for Fds<'a> {
}
}
impl<'a> DoubleEndedIterator for Fds<'a> {
impl<'a, 'fd> DoubleEndedIterator for Fds<'a, 'fd> {
#[inline]
fn next_back(&mut self) -> Option<RawFd> {
fn next_back(&mut self) -> Option<BorrowedFd<'fd>> {
while let Some(i) = self.range.next_back() {
if self.set.contains(i as RawFd) {
return Some(i as RawFd);
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
if self.set.contains(&borrowed_i) {
return Some(borrowed_i);
}
}
None
}
}
impl<'a> FusedIterator for Fds<'a> {}
impl<'a, 'fd> FusedIterator for Fds<'a, 'fd> {}
/// Monitors file descriptors for readiness
///
@ -173,7 +186,7 @@ impl<'a> FusedIterator for Fds<'a> {}
/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
///
/// [`FdSet::highest`]: struct.FdSet.html#method.highest
pub fn select<'a, N, R, W, E, T>(
pub fn select<'a, 'fd, N, R, W, E, T>(
nfds: N,
readfds: R,
writefds: W,
@ -181,10 +194,11 @@ pub fn select<'a, N, R, W, E, T>(
timeout: T,
) -> Result<c_int>
where
'fd: 'a,
N: Into<Option<c_int>>,
R: Into<Option<&'a mut FdSet>>,
W: Into<Option<&'a mut FdSet>>,
E: Into<Option<&'a mut FdSet>>,
R: Into<Option<&'a mut FdSet<'fd>>>,
W: Into<Option<&'a mut FdSet<'fd>>>,
E: Into<Option<&'a mut FdSet<'fd>>>,
T: Into<Option<&'a mut TimeVal>>,
{
let mut readfds = readfds.into();
@ -197,7 +211,11 @@ where
.iter_mut()
.chain(writefds.iter_mut())
.chain(errorfds.iter_mut())
.map(|set| set.highest().unwrap_or(-1))
.map(|set| {
set.highest()
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.unwrap_or(-1)
})
.max()
.unwrap_or(-1)
+ 1
@ -256,17 +274,18 @@ use crate::sys::signal::SigSet;
/// [The new pselect() system call](https://lwn.net/Articles/176911/)
///
/// [`FdSet::highest`]: struct.FdSet.html#method.highest
pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
pub fn pselect<'a, 'fd, N, R, W, E, T, S>(nfds: N,
readfds: R,
writefds: W,
errorfds: E,
timeout: T,
sigmask: S) -> Result<c_int>
where
'fd: 'a,
N: Into<Option<c_int>>,
R: Into<Option<&'a mut FdSet>>,
W: Into<Option<&'a mut FdSet>>,
E: Into<Option<&'a mut FdSet>>,
R: Into<Option<&'a mut FdSet<'fd>>>,
W: Into<Option<&'a mut FdSet<'fd>>>,
E: Into<Option<&'a mut FdSet<'fd>>>,
T: Into<Option<&'a TimeSpec>>,
S: Into<Option<&'a SigSet>>,
{
@ -280,7 +299,7 @@ where
readfds.iter_mut()
.chain(writefds.iter_mut())
.chain(errorfds.iter_mut())
.map(|set| set.highest().unwrap_or(-1))
.map(|set| set.highest().map(|borrowed_fd|borrowed_fd.as_raw_fd()).unwrap_or(-1))
.max()
.unwrap_or(-1) + 1
});
@ -303,20 +322,22 @@ where
mod tests {
use super::*;
use crate::sys::time::{TimeVal, TimeValLike};
use crate::unistd::{pipe, write};
use std::os::unix::io::RawFd;
use crate::unistd::{close, pipe, write};
use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
#[test]
fn fdset_insert() {
let mut fd_set = FdSet::new();
for i in 0..FD_SETSIZE {
assert!(!fd_set.contains(i as RawFd));
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
assert!(!fd_set.contains(&borrowed_i));
}
fd_set.insert(7);
let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
fd_set.insert(&fd_seven);
assert!(fd_set.contains(7));
assert!(fd_set.contains(&fd_seven));
}
#[test]
@ -324,107 +345,183 @@ mod tests {
let mut fd_set = FdSet::new();
for i in 0..FD_SETSIZE {
assert!(!fd_set.contains(i as RawFd));
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
assert!(!fd_set.contains(&borrowed_i));
}
fd_set.insert(7);
fd_set.remove(7);
let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
fd_set.insert(&fd_seven);
fd_set.remove(&fd_seven);
for i in 0..FD_SETSIZE {
assert!(!fd_set.contains(i as RawFd));
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
assert!(!fd_set.contains(&borrowed_i));
}
}
#[test]
#[allow(non_snake_case)]
fn fdset_clear() {
let mut fd_set = FdSet::new();
fd_set.insert(1);
fd_set.insert((FD_SETSIZE / 2) as RawFd);
fd_set.insert((FD_SETSIZE - 1) as RawFd);
let fd_one = unsafe { BorrowedFd::borrow_raw(1) };
let fd_FD_SETSIZE_devided_by_two =
unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) };
let fd_FD_SETSIZE_minus_one =
unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) };
fd_set.insert(&fd_one);
fd_set.insert(&fd_FD_SETSIZE_devided_by_two);
fd_set.insert(&fd_FD_SETSIZE_minus_one);
fd_set.clear();
for i in 0..FD_SETSIZE {
assert!(!fd_set.contains(i as RawFd));
let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
assert!(!fd_set.contains(&borrowed_i));
}
}
#[test]
fn fdset_highest() {
let mut set = FdSet::new();
assert_eq!(set.highest(), None);
set.insert(0);
assert_eq!(set.highest(), Some(0));
set.insert(90);
assert_eq!(set.highest(), Some(90));
set.remove(0);
assert_eq!(set.highest(), Some(90));
set.remove(90);
assert_eq!(set.highest(), None);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
None
);
let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
set.insert(&fd_zero);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
Some(0)
);
set.insert(&fd_ninety);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
Some(90)
);
set.remove(&fd_zero);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
Some(90)
);
set.remove(&fd_ninety);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
None
);
set.insert(4);
set.insert(5);
set.insert(7);
assert_eq!(set.highest(), Some(7));
let fd_four = unsafe { BorrowedFd::borrow_raw(4) };
let fd_five = unsafe { BorrowedFd::borrow_raw(5) };
let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
set.insert(&fd_four);
set.insert(&fd_five);
set.insert(&fd_seven);
assert_eq!(
set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
Some(7)
);
}
#[test]
fn fdset_fds() {
let mut set = FdSet::new();
assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
set.insert(0);
assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
set.insert(90);
assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
assert_eq!(
set.fds(None)
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.collect::<Vec<_>>(),
vec![]
);
set.insert(&fd_zero);
assert_eq!(
set.fds(None)
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.collect::<Vec<_>>(),
vec![0]
);
set.insert(&fd_ninety);
assert_eq!(
set.fds(None)
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.collect::<Vec<_>>(),
vec![0, 90]
);
// highest limit
assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
assert_eq!(
set.fds(Some(89))
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.collect::<Vec<_>>(),
vec![0]
);
assert_eq!(
set.fds(Some(90))
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.collect::<Vec<_>>(),
vec![0, 90]
);
}
#[test]
fn test_select() {
let (r1, w1) = pipe().unwrap();
write(w1, b"hi!").unwrap();
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
let (r2, _w2) = pipe().unwrap();
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
write(w1.as_raw_fd(), b"hi!").unwrap();
let mut fd_set = FdSet::new();
fd_set.insert(r1);
fd_set.insert(r2);
fd_set.insert(&r1);
fd_set.insert(&r2);
let mut timeout = TimeVal::seconds(10);
assert_eq!(
1,
select(None, &mut fd_set, None, None, &mut timeout).unwrap()
);
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
assert!(fd_set.contains(&r1));
assert!(!fd_set.contains(&r2));
close(_w2).unwrap();
}
#[test]
fn test_select_nfds() {
let (r1, w1) = pipe().unwrap();
write(w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
let w1 = unsafe { OwnedFd::from_raw_fd(w1) };
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
write(w1.as_raw_fd(), b"hi!").unwrap();
let mut fd_set = FdSet::new();
fd_set.insert(r1);
fd_set.insert(r2);
fd_set.insert(&r1);
fd_set.insert(&r2);
let mut timeout = TimeVal::seconds(10);
assert_eq!(
1,
select(
Some(fd_set.highest().unwrap() + 1),
&mut fd_set,
None,
None,
&mut timeout
)
.unwrap()
);
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
{
assert_eq!(
1,
select(
Some(
fd_set
.highest()
.map(|borrowed_fd| borrowed_fd.as_raw_fd())
.unwrap()
+ 1
),
&mut fd_set,
None,
None,
&mut timeout
)
.unwrap()
);
}
assert!(fd_set.contains(&r1));
assert!(!fd_set.contains(&r2));
close(_w2).unwrap();
}
#[test]
@ -432,16 +529,17 @@ mod tests {
let (r1, w1) = pipe().unwrap();
write(w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
fd_set.insert(r1);
fd_set.insert(r2);
fd_set.insert(&r1);
fd_set.insert(&r2);
let mut timeout = TimeVal::seconds(10);
assert_eq!(
1,
select(
::std::cmp::max(r1, r2) + 1,
std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
&mut fd_set,
None,
None,
@ -449,7 +547,8 @@ mod tests {
)
.unwrap()
);
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
assert!(fd_set.contains(&r1));
assert!(!fd_set.contains(&r2));
close(_w2).unwrap();
}
}

62
third_party/rust/nix/src/sys/sendfile.rs поставляемый
Просмотреть файл

@ -1,7 +1,7 @@
//! Send data from a file to a socket, bypassing userland.
use cfg_if::cfg_if;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use std::ptr;
use libc::{self, off_t};
@ -23,16 +23,23 @@ use crate::Result;
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn sendfile(
out_fd: RawFd,
in_fd: RawFd,
pub fn sendfile<F1: AsFd, F2: AsFd>(
out_fd: F1,
in_fd: F2,
offset: Option<&mut off_t>,
count: usize,
) -> Result<usize> {
let offset = offset
.map(|offset| offset as *mut _)
.unwrap_or(ptr::null_mut());
let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) };
let ret = unsafe {
libc::sendfile(
out_fd.as_fd().as_raw_fd(),
in_fd.as_fd().as_raw_fd(),
offset,
count,
)
};
Errno::result(ret).map(|r| r as usize)
}
@ -50,16 +57,23 @@ pub fn sendfile(
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn sendfile64(
out_fd: RawFd,
in_fd: RawFd,
pub fn sendfile64<F1: AsFd, F2: AsFd>(
out_fd: F1,
in_fd: F2,
offset: Option<&mut libc::off64_t>,
count: usize,
) -> Result<usize> {
let offset = offset
.map(|offset| offset as *mut _)
.unwrap_or(ptr::null_mut());
let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) };
let ret = unsafe {
libc::sendfile64(
out_fd.as_fd().as_raw_fd(),
in_fd.as_fd().as_raw_fd(),
offset,
count,
)
};
Errno::result(ret).map(|r| r as usize)
}
@ -156,9 +170,9 @@ cfg_if! {
/// For more information, see
/// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
#[allow(clippy::too_many_arguments)]
pub fn sendfile(
in_fd: RawFd,
out_sock: RawFd,
pub fn sendfile<F1: AsFd, F2: AsFd>(
in_fd: F1,
out_sock: F2,
offset: off_t,
count: Option<usize>,
headers: Option<&[&[u8]]>,
@ -175,8 +189,8 @@ cfg_if! {
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd,
out_sock,
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
offset,
count.unwrap_or(0),
hdtr_ptr as *mut libc::sf_hdtr,
@ -206,9 +220,9 @@ cfg_if! {
///
/// For more information, see
/// [the sendfile(2) man page.](https://leaf.dragonflybsd.org/cgi/web-man?command=sendfile&section=2)
pub fn sendfile(
in_fd: RawFd,
out_sock: RawFd,
pub fn sendfile<F1: AsFd, F2: AsFd>(
in_fd: F1,
out_sock: F2,
offset: off_t,
count: Option<usize>,
headers: Option<&[&[u8]]>,
@ -218,8 +232,8 @@ cfg_if! {
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd,
out_sock,
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
offset,
count.unwrap_or(0),
hdtr_ptr as *mut libc::sf_hdtr,
@ -252,9 +266,9 @@ cfg_if! {
///
/// For more information, see
/// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
pub fn sendfile(
in_fd: RawFd,
out_sock: RawFd,
pub fn sendfile<F1: AsFd, F2: AsFd>(
in_fd: F1,
out_sock: F2,
offset: off_t,
count: Option<off_t>,
headers: Option<&[&[u8]]>,
@ -264,8 +278,8 @@ cfg_if! {
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
let return_code = unsafe {
libc::sendfile(in_fd,
out_sock,
libc::sendfile(in_fd.as_fd().as_raw_fd(),
out_sock.as_fd().as_raw_fd(),
offset,
&mut len as *mut off_t,
hdtr_ptr as *mut libc::sf_hdtr,

333
third_party/rust/nix/src/sys/signal.rs поставляемый
Просмотреть файл

@ -13,7 +13,11 @@ use std::os::unix::io::RawFd;
use std::ptr;
use std::str::FromStr;
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
#[cfg(not(any(
target_os = "fuchsia",
target_os = "openbsd",
target_os = "redox"
)))]
#[cfg(any(feature = "aio", feature = "signal"))]
pub use self::sigevent::*;
@ -93,7 +97,8 @@ libc_enum! {
#[cfg_attr(docsrs, doc(cfg(all())))]
SIGIO,
#[cfg(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux"))]
target_os = "fuchsia", target_os = "linux",
target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
/// Power failure imminent.
SIGPWR,
@ -107,7 +112,8 @@ libc_enum! {
SIGEMT,
#[cfg(not(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux",
target_os = "redox", target_os = "haiku")))]
target_os = "redox", target_os = "haiku",
target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
/// Information request
SIGINFO,
@ -186,6 +192,7 @@ impl FromStr for Signal {
target_os = "fuchsia",
target_os = "linux",
target_os = "redox",
target_os = "aix",
target_os = "haiku"
)))]
"SIGINFO" => Signal::SIGINFO,
@ -250,6 +257,7 @@ impl Signal {
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "aix",
target_os = "linux"
))]
Signal::SIGPWR => "SIGPWR",
@ -269,6 +277,7 @@ impl Signal {
target_os = "fuchsia",
target_os = "linux",
target_os = "redox",
target_os = "aix",
target_os = "haiku"
)))]
Signal::SIGINFO => "SIGINFO",
@ -345,11 +354,20 @@ const SIGNALS: [Signal; 30] = [
SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
];
#[cfg(target_os = "aix")]
#[cfg(feature = "signal")]
const SIGNALS: [Signal; 30] = [
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGKILL, SIGSEGV,
SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2, SIGPWR, SIGWINCH,
SIGURG, SIGPOLL, SIGIO, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU,
SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP,
];
#[cfg(not(any(
target_os = "linux",
target_os = "android",
target_os = "fuchsia",
target_os = "emscripten",
target_os = "aix",
target_os = "redox",
target_os = "haiku"
)))]
@ -641,7 +659,6 @@ impl<'a> IntoIterator for &'a SigSet {
}
/// A signal handler.
#[allow(unknown_lints)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SigHandler {
/// Default signal handling.
@ -670,6 +687,7 @@ impl SigAction {
/// is the `SigAction` variant). `mask` specifies other signals to block during execution of
/// the signal-catching function.
pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
#[cfg(not(target_os = "aix"))]
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
(*p).sa_sigaction = match handler {
SigHandler::SigDfl => libc::SIG_DFL,
@ -680,6 +698,16 @@ impl SigAction {
};
}
#[cfg(target_os = "aix")]
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
(*p).sa_union.__su_sigaction = match handler {
SigHandler::SigDfl => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL),
SigHandler::SigIgn => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN),
SigHandler::Handler(f) => mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f),
SigHandler::SigAction(f) => f,
};
}
let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
unsafe {
let p = s.as_mut_ptr();
@ -707,6 +735,7 @@ impl SigAction {
}
/// Returns the action's handler.
#[cfg(not(target_os = "aix"))]
pub fn handler(&self) -> SigHandler {
match self.sigaction.sa_sigaction {
libc::SIG_DFL => SigHandler::SigDfl,
@ -739,6 +768,26 @@ impl SigAction {
as extern fn(libc::c_int)),
}
}
/// Returns the action's handler.
#[cfg(target_os = "aix")]
pub fn handler(&self) -> SigHandler {
unsafe {
match self.sigaction.sa_union.__su_sigaction as usize {
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
p if self.flags().contains(SaFlags::SA_SIGINFO) =>
SigHandler::SigAction(
*(&p as *const usize
as *const extern fn(_, _, _))
as extern fn(_, _, _)),
p => SigHandler::Handler(
*(&p as *const usize
as *const extern fn(libc::c_int))
as extern fn(libc::c_int)),
}
}
}
}
/// Changes the action taken by a process on receipt of a specific signal.
@ -792,13 +841,10 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
/// Use a signal handler to set a flag variable:
///
/// ```no_run
/// # #[macro_use] extern crate lazy_static;
/// # use std::convert::TryFrom;
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use nix::sys::signal::{self, Signal, SigHandler};
/// lazy_static! {
/// static ref SIGNALED: AtomicBool = AtomicBool::new(false);
/// }
/// static SIGNALED: AtomicBool = AtomicBool::new(false);
///
/// extern fn handle_sigint(signal: libc::c_int) {
/// let signal = Signal::try_from(signal).unwrap();
@ -973,14 +1019,14 @@ feature! {
#[cfg(target_os = "freebsd")]
pub type type_of_thread_id = libc::lwpid_t;
/// Identifies a thread for [`SigevNotify::SigevThreadId`]
#[cfg(target_os = "linux")]
#[cfg(any(target_env = "gnu", target_env = "uclibc"))]
pub type type_of_thread_id = libc::pid_t;
/// Specifies the notification method used by a [`SigEvent`]
// sigval is actually a union of a int and a void*. But it's never really used
// as a pointer, because neither libc nor the kernel ever dereference it. nix
// therefore presents it as an intptr_t, which is how kevent uses it.
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
#[cfg(not(any(target_os = "fuchsia", target_os = "openbsd", target_os = "redox")))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SigevNotify {
/// No notification will be delivered
@ -993,8 +1039,7 @@ pub enum SigevNotify {
/// structure of the queued signal.
si_value: libc::intptr_t
},
// Note: SIGEV_THREAD is not implemented because libc::sigevent does not
// expose a way to set the union members needed by SIGEV_THREAD.
// Note: SIGEV_THREAD is not implemented, but could be if desired.
/// Notify by delivering an event to a kqueue.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
@ -1004,8 +1049,24 @@ pub enum SigevNotify {
/// Will be contained in the kevent's `udata` field.
udata: libc::intptr_t
},
/// Notify by delivering an event to a kqueue, with optional event flags set
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[cfg(feature = "event")]
SigevKeventFlags {
/// File descriptor of the kqueue to notify.
kq: RawFd,
/// Will be contained in the kevent's `udata` field.
udata: libc::intptr_t,
/// Flags that will be set on the delivered event. See `kevent(2)`.
flags: crate::sys::event::EventFlag
},
/// Notify by delivering a signal to a thread.
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
#[cfg(any(
target_os = "freebsd",
target_env = "gnu",
target_env = "uclibc",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
SigevThreadId {
/// Signal to send
@ -1019,24 +1080,150 @@ pub enum SigevNotify {
}
}
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
#[cfg(not(any(
target_os = "fuchsia",
target_os = "openbsd",
target_os = "redox"
)))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod sigevent {
feature! {
#![any(feature = "aio", feature = "signal")]
use std::mem;
use std::ptr;
use super::SigevNotify;
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
use super::type_of_thread_id;
#[cfg(target_os = "freebsd")]
pub(crate) use ffi::sigevent as libc_sigevent;
#[cfg(not(target_os = "freebsd"))]
pub(crate) use libc::sigevent as libc_sigevent;
// For FreeBSD only, we define the C structure here. Because the structure
// defined in libc isn't correct. The real sigevent contains union fields,
// but libc could not represent those when sigevent was originally added, so
// instead libc simply defined the most useful field. Now that Rust can
// represent unions, there's a PR to libc to fix it. However, it's stuck
// forever due to backwards compatibility concerns. Even though there's a
// workaround, libc refuses to merge it. I think it's just too complicated
// for them to want to think about right now, because that project is
// short-staffed. So we define it here instead, so we won't have to wait on
// libc.
// https://github.com/rust-lang/libc/pull/2813
#[cfg(target_os = "freebsd")]
mod ffi {
use std::{fmt, hash};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(C)]
pub struct __c_anonymous_sigev_thread {
pub _function: *mut libc::c_void, // Actually a function pointer
pub _attribute: *mut libc::pthread_attr_t,
}
#[derive(Clone, Copy)]
// This will never be used on its own, and its parent has a Debug impl,
// so it doesn't need one.
#[allow(missing_debug_implementations)]
#[repr(C)]
pub union __c_anonymous_sigev_un {
pub _threadid: libc::__lwpid_t,
pub _sigev_thread: __c_anonymous_sigev_thread,
pub _kevent_flags: libc::c_ushort,
__spare__: [libc::c_long; 8],
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct sigevent {
pub sigev_notify: libc::c_int,
pub sigev_signo: libc::c_int,
pub sigev_value: libc::sigval,
pub _sigev_un: __c_anonymous_sigev_un,
}
impl fmt::Debug for sigevent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut ds = f.debug_struct("sigevent");
ds.field("sigev_notify", &self.sigev_notify)
.field("sigev_signo", &self.sigev_signo)
.field("sigev_value", &self.sigev_value);
// Safe because we check the sigev_notify discriminant
unsafe {
match self.sigev_notify {
libc::SIGEV_KEVENT => {
ds.field("sigev_notify_kevent_flags", &self._sigev_un._kevent_flags);
}
libc::SIGEV_THREAD_ID => {
ds.field("sigev_notify_thread_id", &self._sigev_un._threadid);
}
libc::SIGEV_THREAD => {
ds.field("sigev_notify_function", &self._sigev_un._sigev_thread._function);
ds.field("sigev_notify_attributes", &self._sigev_un._sigev_thread._attribute);
}
_ => ()
};
}
ds.finish()
}
}
impl PartialEq for sigevent {
fn eq(&self, other: &Self) -> bool {
let mut equals = self.sigev_notify == other.sigev_notify;
equals &= self.sigev_signo == other.sigev_signo;
equals &= self.sigev_value == other.sigev_value;
// Safe because we check the sigev_notify discriminant
unsafe {
match self.sigev_notify {
libc::SIGEV_KEVENT => {
equals &= self._sigev_un._kevent_flags == other._sigev_un._kevent_flags;
}
libc::SIGEV_THREAD_ID => {
equals &= self._sigev_un._threadid == other._sigev_un._threadid;
}
libc::SIGEV_THREAD => {
equals &= self._sigev_un._sigev_thread == other._sigev_un._sigev_thread;
}
_ => /* The union field is don't care */ ()
}
}
equals
}
}
impl Eq for sigevent {}
impl hash::Hash for sigevent {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
self.sigev_notify.hash(s);
self.sigev_signo.hash(s);
self.sigev_value.hash(s);
// Safe because we check the sigev_notify discriminant
unsafe {
match self.sigev_notify {
libc::SIGEV_KEVENT => {
self._sigev_un._kevent_flags.hash(s);
}
libc::SIGEV_THREAD_ID => {
self._sigev_un._threadid.hash(s);
}
libc::SIGEV_THREAD => {
self._sigev_un._sigev_thread.hash(s);
}
_ => /* The union field is don't care */ ()
}
}
}
}
}
/// Used to request asynchronous notification of the completion of certain
/// events, such as POSIX AIO and timers.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
// It can't be Copy on all platforms.
#[allow(missing_copy_implementations)]
pub struct SigEvent {
sigevent: libc::sigevent
sigevent: libc_sigevent
}
impl SigEvent {
@ -1053,69 +1240,91 @@ mod sigevent {
/// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
/// more genuinely useful `sigev_notify_thread_id`
// Allow invalid_value warning on Fuchsia only.
// See https://github.com/nix-rust/nix/issues/1441
#[cfg_attr(target_os = "fuchsia", allow(invalid_value))]
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
sev.sigev_notify = match sigev_notify {
SigevNotify::SigevNone => libc::SIGEV_NONE,
SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
let mut sev: libc_sigevent = unsafe { mem::zeroed() };
match sigev_notify {
SigevNotify::SigevNone => {
sev.sigev_notify = libc::SIGEV_NONE;
},
SigevNotify::SigevSignal{signal, si_value} => {
sev.sigev_notify = libc::SIGEV_SIGNAL;
sev.sigev_signo = signal as libc::c_int;
sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
},
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
SigevNotify::SigevKevent{kq, udata} => {
sev.sigev_notify = libc::SIGEV_KEVENT;
sev.sigev_signo = kq;
sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
},
#[cfg(target_os = "freebsd")]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
};
sev.sigev_signo = match sigev_notify {
SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ kq, ..} => kq,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
_ => 0
};
sev.sigev_value.sival_ptr = match sigev_notify {
SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
};
SigEvent::set_tid(&mut sev, &sigev_notify);
#[cfg(feature = "event")]
SigevNotify::SigevKeventFlags{kq, udata, flags} => {
sev.sigev_notify = libc::SIGEV_KEVENT;
sev.sigev_signo = kq;
sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
sev._sigev_un._kevent_flags = flags.bits();
},
#[cfg(target_os = "freebsd")]
SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
sev.sigev_notify = libc::SIGEV_THREAD_ID;
sev.sigev_signo = signal as libc::c_int;
sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
sev._sigev_un._threadid = thread_id;
}
#[cfg(any(target_env = "gnu", target_env = "uclibc"))]
SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
sev.sigev_notify = libc::SIGEV_THREAD_ID;
sev.sigev_signo = signal as libc::c_int;
sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
sev.sigev_notify_thread_id = thread_id;
}
}
SigEvent{sigevent: sev}
}
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
sev.sigev_notify_thread_id = match *sigev_notify {
SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
_ => 0 as type_of_thread_id
};
}
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
/// Return a copy of the inner structure
#[cfg(target_os = "freebsd")]
pub fn sigevent(&self) -> libc::sigevent {
// Safe because they're really the same structure. See
// https://github.com/rust-lang/libc/pull/2813
unsafe {
mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
}
}
/// Return a copy of the inner structure
#[cfg(not(target_os = "freebsd"))]
pub fn sigevent(&self) -> libc::sigevent {
self.sigevent
}
/// Returns a mutable pointer to the `sigevent` wrapped by `self`
#[cfg(target_os = "freebsd")]
pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
// Safe because they're really the same structure. See
// https://github.com/rust-lang/libc/pull/2813
&mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
}
/// Returns a mutable pointer to the `sigevent` wrapped by `self`
#[cfg(not(target_os = "freebsd"))]
pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
&mut self.sigevent
}
}
impl<'a> From<&'a libc::sigevent> for SigEvent {
#[cfg(target_os = "freebsd")]
fn from(sigevent: &libc::sigevent) -> Self {
// Safe because they're really the same structure. See
// https://github.com/rust-lang/libc/pull/2813
let sigevent = unsafe {
mem::transmute::<libc::sigevent, libc_sigevent>(*sigevent)
};
SigEvent{ sigevent }
}
#[cfg(not(target_os = "freebsd"))]
fn from(sigevent: &libc::sigevent) -> Self {
SigEvent{ sigevent: *sigevent }
}

38
third_party/rust/nix/src/sys/signalfd.rs поставляемый
Просмотреть файл

@ -17,12 +17,11 @@
//! signal handlers.
use crate::errno::Errno;
pub use crate::sys::signal::{self, SigSet};
use crate::unistd;
use crate::Result;
pub use libc::signalfd_siginfo as siginfo;
use std::mem;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd, OwnedFd, AsFd, BorrowedFd};
libc_bitflags! {
pub struct SfdFlags: libc::c_int {
@ -31,7 +30,6 @@ libc_bitflags! {
}
}
pub const SIGNALFD_NEW: RawFd = -1;
#[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")]
pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
@ -46,13 +44,19 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
/// signalfd (the default handler will be invoked instead).
///
/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
#[deprecated(since = "0.27.0", note = "Use SignalFd instead")]
pub fn signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
_signalfd(fd, mask, flags)
}
fn _signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
let raw_fd = fd.map_or(-1, |x|x.as_fd().as_raw_fd());
unsafe {
Errno::result(libc::signalfd(
fd as libc::c_int,
raw_fd,
mask.as_ref(),
flags.bits(),
))
)).map(|raw_fd|FromRawFd::from_raw_fd(raw_fd))
}
}
@ -82,8 +86,8 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
/// Err(err) => (), // some error happend
/// }
/// ```
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct SignalFd(RawFd);
#[derive(Debug)]
pub struct SignalFd(OwnedFd);
impl SignalFd {
pub fn new(mask: &SigSet) -> Result<SignalFd> {
@ -91,13 +95,13 @@ impl SignalFd {
}
pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
let fd = _signalfd(None::<OwnedFd>, mask, flags)?;
Ok(SignalFd(fd))
}
pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
signalfd(self.0, mask, SfdFlags::empty()).map(drop)
_signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop)
}
pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
@ -105,7 +109,7 @@ impl SignalFd {
let size = mem::size_of_val(&buffer);
let res = Errno::result(unsafe {
libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size)
libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr() as *mut libc::c_void, size)
})
.map(|r| r as usize);
match res {
@ -117,18 +121,14 @@ impl SignalFd {
}
}
impl Drop for SignalFd {
fn drop(&mut self) {
let e = unistd::close(self.0);
if !std::thread::panicking() && e == Err(Errno::EBADF) {
panic!("Closing an invalid file descriptor!");
};
impl AsFd for SignalFd {
fn as_fd(&self) -> BorrowedFd {
self.0.as_fd()
}
}
impl AsRawFd for SignalFd {
fn as_raw_fd(&self) -> RawFd {
self.0
self.0.as_raw_fd()
}
}

874
third_party/rust/nix/src/sys/socket/addr.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

364
third_party/rust/nix/src/sys/socket/mod.rs поставляемый
Просмотреть файл

@ -1,23 +1,25 @@
//! Socket interface functions
//!
//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "uio")]
use crate::sys::time::TimeSpec;
#[cfg(not(target_os = "redox"))]
#[cfg(feature = "uio")]
use crate::sys::time::TimeVal;
use crate::{errno::Errno, Result};
use cfg_if::cfg_if;
use libc::{self, c_int, c_void, size_t, socklen_t};
#[cfg(all(feature = "uio", not(target_os = "redox")))]
use libc::{
self, c_int, c_void, iovec, size_t, socklen_t, CMSG_DATA, CMSG_FIRSTHDR,
CMSG_LEN, CMSG_NXTHDR,
iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
};
use std::convert::{TryFrom, TryInto};
#[cfg(not(target_os = "redox"))]
use std::io::{IoSlice, IoSliceMut};
#[cfg(feature = "net")]
use std::net;
use std::os::unix::io::RawFd;
use std::{mem, ptr, slice};
use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, RawFd, OwnedFd};
use std::{mem, ptr};
#[deny(missing_docs)]
mod addr;
@ -32,32 +34,26 @@ pub mod sockopt;
pub use self::addr::{SockaddrLike, SockaddrStorage};
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
#[allow(deprecated)]
pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[allow(deprecated)]
pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
#[allow(deprecated)]
pub use self::addr::{AddressFamily, UnixAddr};
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
pub use self::addr::{AddressFamily, UnixAddr};
#[cfg(not(any(
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
target_os = "haiku",
target_os = "redox",
)))]
#[cfg(feature = "net")]
pub use self::addr::{
InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, LinkAddr, SockaddrIn, SockaddrIn6,
};
#[allow(deprecated)]
pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6};
#[cfg(any(
target_os = "illumos",
target_os = "solaris",
target_os = "haiku"
target_os = "haiku",
target_os = "redox",
))]
#[cfg(feature = "net")]
pub use self::addr::{
InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, SockaddrIn, SockaddrIn6,
};
pub use self::addr::{SockaddrIn, SockaddrIn6};
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use crate::sys::socket::addr::alg::AlgAddr;
@ -66,19 +62,15 @@ pub use crate::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(feature = "ioctl")]
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
pub use crate::sys::socket::addr::vsock::VsockAddr;
#[cfg(feature = "uio")]
#[cfg(all(feature = "uio", not(target_os = "redox")))]
pub use libc::{cmsghdr, msghdr};
pub use libc::{sa_family_t, sockaddr, sockaddr_storage, sockaddr_un};
#[cfg(feature = "net")]
pub use libc::{sockaddr_in, sockaddr_in6};
// Needed by the cmsg_space macro
#[doc(hidden)]
pub use libc::{c_uint, CMSG_SPACE};
#[cfg(feature = "net")]
use crate::sys::socket::addr::{ipv4addr_to_libc, ipv6addr_to_libc};
@ -101,10 +93,11 @@ pub enum SockType {
/// entire packet with each input system call.
SeqPacket = libc::SOCK_SEQPACKET,
/// Provides raw network protocol access.
#[cfg(not(target_os = "redox"))]
Raw = libc::SOCK_RAW,
/// Provides a reliable datagram layer that does not
/// guarantee ordering.
#[cfg(not(any(target_os = "haiku")))]
#[cfg(not(any(target_os = "haiku", target_os = "redox")))]
Rdm = libc::SOCK_RDM,
}
// The TryFrom impl could've been derived using libc_enum!. But for
@ -118,10 +111,11 @@ impl TryFrom<i32> for SockType {
libc::SOCK_STREAM => Ok(Self::Stream),
libc::SOCK_DGRAM => Ok(Self::Datagram),
libc::SOCK_SEQPACKET => Ok(Self::SeqPacket),
#[cfg(not(target_os = "redox"))]
libc::SOCK_RAW => Ok(Self::Raw),
#[cfg(not(any(target_os = "haiku")))]
#[cfg(not(any(target_os = "haiku", target_os = "redox")))]
libc::SOCK_RDM => Ok(Self::Rdm),
_ => Err(Errno::EINVAL)
_ => Err(Errno::EINVAL),
}
}
}
@ -164,6 +158,11 @@ pub enum SockProtocol {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
/// Netfilter/iptables ULOG.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetlinkNFLOG = libc::NETLINK_NFLOG,
/// SELinux event notifications.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
@ -214,6 +213,11 @@ pub enum SockProtocol {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
/// Generic netlink family for simplified netlink usage.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
NetlinkGeneric = libc::NETLINK_GENERIC,
/// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
/// configuration of the kernel crypto API.
/// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
@ -226,28 +230,45 @@ pub enum SockProtocol {
// The protocol number is fed into the socket syscall in network byte order.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
EthAll = libc::ETH_P_ALL.to_be(),
EthAll = (libc::ETH_P_ALL as u16).to_be() as i32,
/// The Controller Area Network raw socket protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
CanRaw = libc::CAN_RAW,
}
#[cfg(any(target_os = "linux"))]
impl SockProtocol {
/// The Controller Area Network broadcast manager protocol
/// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(non_upper_case_globals)]
pub const CanBcm: SockProtocol = SockProtocol::NetlinkUserSock; // Matches libc::CAN_BCM
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc_bitflags! {
/// Configuration flags for `SO_TIMESTAMPING` interface
///
/// For use with [`Timestamping`][sockopt::Timestamping].
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
pub struct TimestampingFlag: c_uint {
pub struct TimestampingFlag: libc::c_uint {
/// Report any software timestamps when available.
SOF_TIMESTAMPING_SOFTWARE;
/// Report hardware timestamps as generated by SOF_TIMESTAMPING_TX_HARDWARE when available.
SOF_TIMESTAMPING_RAW_HARDWARE;
/// Collect transmiting timestamps as reported by hardware
/// Collect transmitting timestamps as reported by hardware
SOF_TIMESTAMPING_TX_HARDWARE;
/// Collect transmiting timestamps as reported by software
/// Collect transmitting timestamps as reported by software
SOF_TIMESTAMPING_TX_SOFTWARE;
/// Collect receiving timestamps as reported by hardware
SOF_TIMESTAMPING_RX_HARDWARE;
/// Collect receiving timestamps as reported by software
SOF_TIMESTAMPING_RX_SOFTWARE;
/// Generate a unique identifier along with each transmitted packet
SOF_TIMESTAMPING_OPT_ID;
/// Return transmit timestamps alongside an empty packet instead of the original packet
SOF_TIMESTAMPING_OPT_TSONLY;
}
}
@ -292,17 +313,14 @@ libc_bitflags! {
/// Sends or requests out-of-band data on sockets that support this notion
/// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
/// support out-of-band data.
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_OOB;
/// Peeks at an incoming message. The data is treated as unread and the next
/// [`recv()`](fn.recv.html)
/// or similar function shall still return this data.
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_PEEK;
/// Receive operation blocks until the full amount of data can be
/// returned. The function may return smaller amount of data if a signal
/// is caught, an error or disconnect occurs.
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_WAITALL;
/// Enables nonblocking operation; if the operation would block,
/// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar
@ -314,10 +332,10 @@ libc_bitflags! {
/// which will affect all threads in
/// the calling process and as well as other processes that hold
/// file descriptors referring to the same open file description.
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MSG_DONTWAIT;
/// Receive flags: Control Data was discarded (buffer too small)
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_CTRUNC;
/// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
/// (since Linux 2.4.27/2.6.8),
@ -327,18 +345,15 @@ libc_bitflags! {
/// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
///
/// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_TRUNC;
/// Terminates a record (when this notion is supported, as for
/// sockets of type [`SeqPacket`](enum.SockType.html)).
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_EOR;
/// This flag specifies that queued errors should be received from
/// the socket error queue. (For more details, see
/// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_ERRQUEUE;
/// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
/// file descriptor using the `SCM_RIGHTS` operation (described in
@ -354,7 +369,6 @@ libc_bitflags! {
target_os = "netbsd",
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_CMSG_CLOEXEC;
/// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
/// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
@ -369,8 +383,18 @@ libc_bitflags! {
target_os = "openbsd",
target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_NOSIGNAL;
/// Turns on [`MSG_DONTWAIT`] after the first message has been received (only for
/// `recvmmsg()`).
#[cfg(any(target_os = "android",
target_os = "fuchsia",
target_os = "linux",
target_os = "netbsd",
target_os = "freebsd",
target_os = "openbsd",
target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
MSG_WAITFORONE;
}
}
@ -462,7 +486,7 @@ cfg_if! {
/// Returns a list group identifiers (the first one being the effective GID)
pub fn groups(&self) -> &[libc::gid_t] {
unsafe {
slice::from_raw_parts(
std::slice::from_raw_parts(
self.0.cmcred_groups.as_ptr() as *const libc::gid_t,
self.0.cmcred_ngroups as _
)
@ -555,6 +579,7 @@ impl Ipv6MembershipRequest {
}
}
#[cfg(not(target_os = "redox"))]
feature! {
#![feature = "uio"]
@ -584,18 +609,19 @@ feature! {
macro_rules! cmsg_space {
( $( $x:ty ),* ) => {
{
let mut space = 0;
$(
// CMSG_SPACE is always safe
space += unsafe {
$crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
} as usize;
)*
let space = 0 $(+ $crate::sys::socket::cmsg_space::<$x>())*;
Vec::<u8>::with_capacity(space)
}
}
}
#[inline]
#[doc(hidden)]
pub fn cmsg_space<T>() -> usize {
// SAFETY: CMSG_SPACE is always safe
unsafe { libc::CMSG_SPACE(mem::size_of::<T>() as libc::c_uint) as usize }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// Contains outcome of sending or receiving a message
///
@ -688,6 +714,7 @@ pub enum ControlMessageOwned {
/// # use std::io::{IoSlice, IoSliceMut};
/// # use std::time::*;
/// # use std::str::FromStr;
/// # use std::os::unix::io::AsRawFd;
/// # fn main() {
/// // Set up
/// let message = "Ohayō!".as_bytes();
@ -696,22 +723,22 @@ pub enum ControlMessageOwned {
/// SockType::Datagram,
/// SockFlag::empty(),
/// None).unwrap();
/// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
/// setsockopt(&in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
/// let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
/// bind(in_socket, &localhost).unwrap();
/// let address: SockaddrIn = getsockname(in_socket).unwrap();
/// bind(in_socket.as_raw_fd(), &localhost).unwrap();
/// let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
/// // Get initial time
/// let time0 = SystemTime::now();
/// // Send the message
/// let iov = [IoSlice::new(message)];
/// let flags = MsgFlags::empty();
/// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
/// let l = sendmsg(in_socket.as_raw_fd(), &iov, &[], flags, Some(&address)).unwrap();
/// assert_eq!(message.len(), l);
/// // Receive the message
/// let mut buffer = vec![0u8; message.len()];
/// let mut cmsgspace = cmsg_space!(TimeVal);
/// let mut iov = [IoSliceMut::new(&mut buffer)];
/// let r = recvmsg::<SockaddrIn>(in_socket, &mut iov, Some(&mut cmsgspace), flags)
/// let r = recvmsg::<SockaddrIn>(in_socket.as_raw_fd(), &mut iov, Some(&mut cmsgspace), flags)
/// .unwrap();
/// let rtime = match r.cmsgs().next() {
/// Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
@ -727,19 +754,18 @@ pub enum ControlMessageOwned {
/// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
/// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
/// // Close socket
/// nix::unistd::close(in_socket).unwrap();
/// # }
/// ```
ScmTimestamp(TimeVal),
/// A set of nanosecond resolution timestamps
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
ScmTimestampsns(Timestamps),
/// Nanoseconds resolution timestamp
///
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
ScmTimestampns(TimeSpec),
#[cfg(any(
@ -836,7 +862,7 @@ pub enum ControlMessageOwned {
}
/// For representing packet timestamps via `SO_TIMESTAMPING` interface
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Timestamps {
/// software based timestamp, usually one containing data
@ -884,17 +910,17 @@ impl ControlMessageOwned {
let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmCreds(cred.into())
}
#[cfg(not(target_os = "haiku"))]
#[cfg(not(any(target_os = "aix", target_os = "haiku")))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
let tv: libc::timeval = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
},
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
let ts: libc::timespec = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
}
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
(libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
let tp = p as *const libc::timespec;
let ts: libc::timespec = ptr::read_unaligned(tp);
@ -990,7 +1016,7 @@ impl ControlMessageOwned {
ControlMessageOwned::Ipv6OrigDstAddr(dl)
},
(_, _) => {
let sl = slice::from_raw_parts(p, len);
let sl = std::slice::from_raw_parts(p, len);
let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
ControlMessageOwned::Unknown(ucmsg)
}
@ -1446,6 +1472,7 @@ impl<'a> ControlMessage<'a> {
/// # use nix::sys::socket::*;
/// # use nix::unistd::pipe;
/// # use std::io::IoSlice;
/// # use std::os::unix::io::AsRawFd;
/// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
/// SockFlag::empty())
/// .unwrap();
@ -1454,7 +1481,7 @@ impl<'a> ControlMessage<'a> {
/// let iov = [IoSlice::new(b"hello")];
/// let fds = [r];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
/// ```
/// When directing to a specific address, the generic type will be inferred.
/// ```
@ -1462,6 +1489,7 @@ impl<'a> ControlMessage<'a> {
/// # use nix::unistd::pipe;
/// # use std::io::IoSlice;
/// # use std::str::FromStr;
/// # use std::os::unix::io::AsRawFd;
/// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap();
/// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(),
/// None).unwrap();
@ -1470,7 +1498,7 @@ impl<'a> ControlMessage<'a> {
/// let iov = [IoSlice::new(b"hello")];
/// let fds = [r];
/// let cmsg = ControlMessage::ScmRights(&fds);
/// sendmsg(fd, &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
/// ```
pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
flags: MsgFlags, addr: Option<&S>) -> Result<usize>
@ -1535,7 +1563,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>(
for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
let mut p = &mut mmsghdr.msg_hdr;
let p = &mut mmsghdr.msg_hdr;
p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
p.msg_iovlen = slice.as_ref().len() as _;
@ -1590,8 +1618,7 @@ pub struct MultiHeaders<S> {
addresses: Box<[mem::MaybeUninit<S>]>,
// while we are not using it directly - this is used to store control messages
// and we retain pointers to them inside items array
#[allow(dead_code)]
cmsg_buffers: Option<Box<[u8]>>,
_cmsg_buffers: Option<Box<[u8]>>,
msg_controllen: usize,
}
@ -1611,24 +1638,24 @@ impl<S> MultiHeaders<S> {
{
// we will be storing pointers to addresses inside mhdr - convert it into boxed
// slice so it can'be changed later by pushing anything into self.addresses
let mut addresses = vec![std::mem::MaybeUninit::uninit(); num_slices].into_boxed_slice();
let mut addresses = vec![std::mem::MaybeUninit::<S>::uninit(); num_slices].into_boxed_slice();
let msg_controllen = cmsg_buffer.as_ref().map_or(0, |v| v.capacity());
// we'll need a cmsg_buffer for each slice, we preallocate a vector and split
// it into "slices" parts
let cmsg_buffers =
let mut cmsg_buffers =
cmsg_buffer.map(|v| vec![0u8; v.capacity() * num_slices].into_boxed_slice());
let items = addresses
.iter_mut()
.enumerate()
.map(|(ix, address)| {
let (ptr, cap) = match &cmsg_buffers {
Some(v) => ((&v[ix * msg_controllen] as *const u8), msg_controllen),
None => (std::ptr::null(), 0),
let (ptr, cap) = match &mut cmsg_buffers {
Some(v) => ((&mut v[ix * msg_controllen] as *mut u8), msg_controllen),
None => (std::ptr::null_mut(), 0),
};
let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null(), 0, ptr, cap, address.as_mut_ptr()) };
let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) };
libc::mmsghdr {
msg_hdr,
msg_len: 0,
@ -1639,7 +1666,7 @@ impl<S> MultiHeaders<S> {
Self {
items: items.into_boxed_slice(),
addresses,
cmsg_buffers,
_cmsg_buffers: cmsg_buffers,
msg_controllen,
}
}
@ -1689,7 +1716,7 @@ where
{
let mut count = 0;
for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
let mut p = &mut mmsghdr.msg_hdr;
let p = &mut mmsghdr.msg_hdr;
p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
p.msg_iovlen = slice.as_ref().len() as _;
count = i + 1;
@ -1819,6 +1846,7 @@ mod test {
use crate::sys::socket::{AddressFamily, ControlMessageOwned};
use crate::*;
use std::str::FromStr;
use std::os::unix::io::AsRawFd;
#[cfg_attr(qemu, ignore)]
#[test]
@ -1845,9 +1873,9 @@ mod test {
None,
)?;
crate::sys::socket::bind(rsock, &sock_addr)?;
crate::sys::socket::bind(rsock.as_raw_fd(), &sock_addr)?;
setsockopt(rsock, Timestamping, &TimestampingFlag::all())?;
setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
@ -1869,13 +1897,13 @@ mod test {
let iov1 = [IoSlice::new(&sbuf)];
let cmsg = cmsg_space!(crate::sys::socket::Timestamps);
sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10));
let recv = super::recvmmsg(rsock, &mut data, recv_iovs.iter(), flags, Some(t))?;
let recv = super::recvmmsg(rsock.as_raw_fd(), &mut data, recv_iovs.iter(), flags, Some(t))?;
for rmsg in recv {
#[cfg(not(any(qemu, target_arch = "aarch64")))]
@ -1916,7 +1944,7 @@ unsafe fn read_mhdr<'a, 'i, S>(
mhdr: msghdr,
r: isize,
msg_controllen: usize,
address: S,
mut address: S,
) -> RecvMsg<'a, 'i, S>
where S: SockaddrLike
{
@ -1932,6 +1960,11 @@ unsafe fn read_mhdr<'a, 'i, S>(
}.as_ref()
};
// Ignore errors if this socket address has statically-known length
//
// This is to ensure that unix socket addresses have their length set appropriately.
let _ = address.set_length(mhdr.msg_namelen as usize);
RecvMsg {
bytes: r as usize,
cmsghdr,
@ -1954,9 +1987,9 @@ unsafe fn read_mhdr<'a, 'i, S>(
///
/// Buffers must remain valid for the whole lifetime of msghdr
unsafe fn pack_mhdr_to_receive<S>(
iov_buffer: *const IoSliceMut,
iov_buffer: *mut IoSliceMut,
iov_buffer_len: usize,
cmsg_buffer: *const u8,
cmsg_buffer: *mut u8,
cmsg_capacity: usize,
address: *mut S,
) -> msghdr
@ -1967,7 +2000,7 @@ unsafe fn pack_mhdr_to_receive<S>(
// initialize it.
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
let p = mhdr.as_mut_ptr();
(*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
(*p).msg_name = address as *mut c_void;
(*p).msg_namelen = S::size();
(*p).msg_iov = iov_buffer as *mut iovec;
(*p).msg_iovlen = iov_buffer_len as _;
@ -1992,7 +2025,7 @@ fn pack_mhdr_to_send<'a, I, C, S>(
// The message header must be initialized before the individual cmsgs.
let cmsg_ptr = if capacity > 0 {
cmsg_buffer.as_ptr() as *mut c_void
cmsg_buffer.as_mut_ptr() as *mut c_void
} else {
ptr::null_mut()
};
@ -2046,7 +2079,7 @@ fn pack_mhdr_to_send<'a, I, C, S>(
/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'inner>],
mut cmsg_buffer: Option<&'a mut Vec<u8>>,
flags: MsgFlags) -> Result<RecvMsg<'a, 'inner, S>>
flags: MsgFlags) -> Result<RecvMsg<'a, 'outer, S>>
where S: SockaddrLike + 'a,
'inner: 'outer
{
@ -2056,7 +2089,7 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i
.map(|v| (v.as_mut_ptr(), v.capacity()))
.unwrap_or((ptr::null_mut(), 0));
let mut mhdr = unsafe {
pack_mhdr_to_receive(iov.as_ref().as_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
};
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
@ -2082,7 +2115,7 @@ pub fn socket<T: Into<Option<SockProtocol>>>(
ty: SockType,
flags: SockFlag,
protocol: T,
) -> Result<RawFd> {
) -> Result<OwnedFd> {
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
@ -2096,7 +2129,13 @@ pub fn socket<T: Into<Option<SockProtocol>>>(
let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
Errno::result(res)
match res {
-1 => Err(Errno::last()),
fd => {
// Safe because libc::socket returned success
unsafe { Ok(OwnedFd::from_raw_fd(fd)) }
}
}
}
/// Create a pair of connected sockets
@ -2107,7 +2146,7 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(
ty: SockType,
protocol: T,
flags: SockFlag,
) -> Result<(RawFd, RawFd)> {
) -> Result<(OwnedFd, OwnedFd)> {
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
@ -2126,14 +2165,18 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(
};
Errno::result(res)?;
Ok((fds[0], fds[1]))
// Safe because socketpair returned success.
unsafe {
Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1])))
}
}
/// Listen for connections on a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
let res = unsafe { libc::listen(sockfd, backlog as c_int) };
pub fn listen<F: AsFd>(sock: &F, backlog: usize) -> Result<()> {
let fd = sock.as_fd().as_raw_fd();
let res = unsafe { libc::listen(fd, backlog as c_int) };
Errno::result(res).map(drop)
}
@ -2202,7 +2245,7 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
unsafe {
let ret = libc::recv(
sockfd,
buf.as_ptr() as *mut c_void,
buf.as_mut_ptr() as *mut c_void,
buf.len() as size_t,
flags.bits(),
);
@ -2226,17 +2269,17 @@ pub fn recvfrom<T: SockaddrLike>(
let ret = Errno::result(libc::recvfrom(
sockfd,
buf.as_ptr() as *mut c_void,
buf.as_mut_ptr() as *mut c_void,
buf.len() as size_t,
0,
addr.as_mut_ptr() as *mut libc::sockaddr,
addr.as_mut_ptr() as *mut sockaddr,
&mut len as *mut socklen_t,
))? as usize;
Ok((
ret,
T::from_raw(
addr.assume_init().as_ptr() as *const libc::sockaddr,
addr.assume_init().as_ptr(),
Some(len),
),
))
@ -2293,7 +2336,7 @@ pub trait GetSockOpt: Copy {
type Val;
/// Look up the value of this socket option on the given socket.
fn get(&self, fd: RawFd) -> Result<Self::Val>;
fn get<F: AsFd>(&self, fd: &F) -> Result<Self::Val>;
}
/// Represents a socket option that can be set.
@ -2301,13 +2344,13 @@ pub trait SetSockOpt: Clone {
type Val;
/// Set the value of this socket option on the given socket.
fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()>;
}
/// Get the current value for the requested socket option
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
pub fn getsockopt<F: AsFd, O: GetSockOpt>(fd: &F, opt: O) -> Result<O::Val> {
opt.get(fd)
}
@ -2321,15 +2364,14 @@ pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
/// use nix::sys::socket::setsockopt;
/// use nix::sys::socket::sockopt::KeepAlive;
/// use std::net::TcpListener;
/// use std::os::unix::io::AsRawFd;
///
/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
/// let fd = listener.as_raw_fd();
/// let res = setsockopt(fd, KeepAlive, &true);
/// let fd = listener;
/// let res = setsockopt(&fd, KeepAlive, &true);
/// assert!(res.is_ok());
/// ```
pub fn setsockopt<O: SetSockOpt>(
fd: RawFd,
pub fn setsockopt<F: AsFd, O: SetSockOpt>(
fd: &F,
opt: O,
val: &O::Val,
) -> Result<()> {
@ -2344,11 +2386,8 @@ pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
let ret = libc::getpeername(
fd,
addr.as_mut_ptr() as *mut libc::sockaddr,
&mut len,
);
let ret =
libc::getpeername(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
Errno::result(ret)?;
@ -2364,11 +2403,8 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = T::size();
let ret = libc::getsockname(
fd,
addr.as_mut_ptr() as *mut libc::sockaddr,
&mut len,
);
let ret =
libc::getsockname(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len);
Errno::result(ret)?;
@ -2376,81 +2412,6 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
}
}
/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
/// certain size.
///
/// In C this would usually be done by casting. The `len` argument
/// should be the number of bytes in the `sockaddr_storage` that are actually
/// allocated and valid. It must be at least as large as all the useful parts
/// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
/// include the terminating null.
#[deprecated(
since = "0.24.0",
note = "use SockaddrLike or SockaddrStorage instead"
)]
#[allow(deprecated)]
pub fn sockaddr_storage_to_addr(
addr: &sockaddr_storage,
len: usize,
) -> Result<SockAddr> {
assert!(len <= mem::size_of::<sockaddr_storage>());
if len < mem::size_of_val(&addr.ss_family) {
return Err(Errno::ENOTCONN);
}
match c_int::from(addr.ss_family) {
#[cfg(feature = "net")]
libc::AF_INET => {
assert!(len >= mem::size_of::<sockaddr_in>());
let sin = unsafe {
*(addr as *const sockaddr_storage as *const sockaddr_in)
};
Ok(SockAddr::Inet(InetAddr::V4(sin)))
}
#[cfg(feature = "net")]
libc::AF_INET6 => {
assert!(len >= mem::size_of::<sockaddr_in6>());
let sin6 = unsafe { *(addr as *const _ as *const sockaddr_in6) };
Ok(SockAddr::Inet(InetAddr::V6(sin6)))
}
libc::AF_UNIX => unsafe {
let sun = *(addr as *const _ as *const sockaddr_un);
let sun_len = len.try_into().unwrap();
Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, sun_len)))
},
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
libc::AF_PACKET => {
use libc::sockaddr_ll;
// Don't assert anything about the size.
// Apparently the Linux kernel can return smaller sizes when
// the value in the last element of sockaddr_ll (`sll_addr`) is
// smaller than the declared size of that field
let sll = unsafe { *(addr as *const _ as *const sockaddr_ll) };
Ok(SockAddr::Link(LinkAddr(sll)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_NETLINK => {
use libc::sockaddr_nl;
let snl = unsafe { *(addr as *const _ as *const sockaddr_nl) };
Ok(SockAddr::Netlink(NetlinkAddr(snl)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_ALG => {
use libc::sockaddr_alg;
let salg = unsafe { *(addr as *const _ as *const sockaddr_alg) };
Ok(SockAddr::Alg(AlgAddr(salg)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_VSOCK => {
use libc::sockaddr_vm;
let svm = unsafe { *(addr as *const _ as *const sockaddr_vm) };
Ok(SockAddr::Vsock(VsockAddr(svm)))
}
af => panic!("unexpected address family {}", af),
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Shutdown {
/// Further receptions will be disallowed.
@ -2480,8 +2441,25 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
#[cfg(test)]
mod tests {
#[cfg(not(target_os = "redox"))]
#[test]
fn can_use_cmsg_space() {
let _ = cmsg_space!(u8);
}
#[cfg(not(any(
target_os = "redox",
target_os = "linux",
target_os = "android"
)))]
#[test]
fn can_open_routing_socket() {
let _ = super::socket(
super::AddressFamily::Route,
super::SockType::Raw,
super::SockFlag::empty(),
None,
)
.expect("Failed to open routing socket");
}
}

120
third_party/rust/nix/src/sys/socket/sockopt.rs поставляемый
Просмотреть файл

@ -6,13 +6,10 @@ use crate::Result;
use cfg_if::cfg_if;
use libc::{self, c_int, c_void, socklen_t};
use std::ffi::{OsStr, OsString};
use std::{
convert::TryFrom,
mem::{self, MaybeUninit}
};
use std::mem::{self, MaybeUninit};
#[cfg(target_family = "unix")]
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
// Constants
// TCP_CA_NAME_MAX isn't defined in user space include files
@ -47,12 +44,12 @@ macro_rules! setsockopt_impl {
impl SetSockOpt for $name {
type Val = $ty;
fn set(&self, fd: RawFd, val: &$ty) -> Result<()> {
fn set<F: AsFd>(&self, fd: &F, val: &$ty) -> Result<()> {
unsafe {
let setter: $setter = Set::new(val);
let res = libc::setsockopt(
fd,
fd.as_fd().as_raw_fd(),
$level,
$flag,
setter.ffi_ptr(),
@ -92,12 +89,12 @@ macro_rules! getsockopt_impl {
impl GetSockOpt for $name {
type Val = $ty;
fn get(&self, fd: RawFd) -> Result<$ty> {
fn get<F: AsFd>(&self, fd: &F) -> Result<$ty> {
unsafe {
let mut getter: $getter = Get::uninit();
let res = libc::getsockopt(
fd,
fd.as_fd().as_raw_fd(),
$level,
$flag,
getter.ffi_ptr(),
@ -107,7 +104,7 @@ macro_rules! getsockopt_impl {
match <$ty>::try_from(getter.assume_init()) {
Err(_) => Err(Errno::EINVAL),
Ok(r) => Ok(r)
Ok(r) => Ok(r),
}
}
}
@ -141,7 +138,6 @@ macro_rules! getsockopt_impl {
/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
// Some targets don't use all rules.
#[allow(unknown_lints)]
#[allow(unused_macro_rules)]
macro_rules! sockopt_impl {
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => {
@ -496,6 +492,15 @@ sockopt_impl!(
libc::LOCAL_PEERCRED,
super::XuCred
);
#[cfg(any(target_os = "macos", target_os = "ios"))]
sockopt_impl!(
/// Get the PID of the peer process of a connected unix domain socket.
LocalPeerPid,
GetOnly,
0,
libc::LOCAL_PEERPID,
libc::c_int
);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Return the credentials of the foreign process connected to this socket.
@ -539,13 +544,13 @@ cfg_if! {
sockopt_impl!(
/// The maximum segment size for outgoing TCP packets.
TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
} else {
} else if #[cfg(not(target_os = "redox"))] {
sockopt_impl!(
/// The maximum segment size for outgoing TCP packets.
TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
}
}
#[cfg(not(any(target_os = "openbsd", target_os = "haiku")))]
#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@ -567,7 +572,7 @@ sockopt_impl!(
libc::TCP_REPAIR,
u32
);
#[cfg(not(any(target_os = "openbsd", target_os = "haiku")))]
#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@ -678,7 +683,7 @@ sockopt_impl!(
libc::IP6T_SO_ORIGINAL_DST,
libc::sockaddr_in6
);
#[cfg(any(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Specifies exact type of timestamping information collected by the kernel
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
@ -688,7 +693,7 @@ sockopt_impl!(
libc::SO_TIMESTAMPING,
super::TimestampingFlag
);
#[cfg(not(target_os = "haiku"))]
#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
ReceiveTimestamp,
@ -697,7 +702,7 @@ sockopt_impl!(
libc::SO_TIMESTAMP,
bool
);
#[cfg(all(target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message.
ReceiveTimestampns,
@ -706,6 +711,16 @@ sockopt_impl!(
libc::SO_TIMESTAMPNS,
bool
);
#[cfg(target_os = "freebsd")]
sockopt_impl!(
/// Sets a specific timestamp format instead of the classic `SCM_TIMESTAMP`,
/// to follow up after `SO_TIMESTAMP` is set.
TsClock,
Both,
libc::SOL_SOCKET,
libc::SO_TS_CLOCK,
i32
);
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
@ -741,6 +756,46 @@ sockopt_impl!(
libc::IP_BINDANY,
bool
);
#[cfg(target_os = "freebsd")]
sockopt_impl!(
/// Set the route table (FIB) for this socket up to the `net.fibs` OID limit
/// (more specific than the setfib command line/call which are process based).
Fib,
SetOnly,
libc::SOL_SOCKET,
libc::SO_SETFIB,
i32
);
#[cfg(target_os = "freebsd")]
sockopt_impl!(
/// Set `so_user_cookie` for this socket allowing network traffic based
/// upon it, similar to Linux's netfilter MARK.
UserCookie,
SetOnly,
libc::SOL_SOCKET,
libc::SO_USER_COOKIE,
u32
);
#[cfg(target_os = "openbsd")]
sockopt_impl!(
/// Set the route table for this socket, needs a privileged user if
/// the process/socket had been set to the non default route.
Rtable,
SetOnly,
libc::SOL_SOCKET,
libc::SO_RTABLE,
i32
);
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
sockopt_impl!(
/// Get/set a filter on this socket before accepting connections similarly
/// to Linux's TCP_DEFER_ACCEPT but after the listen's call.
AcceptFilter,
Both,
libc::SOL_SOCKET,
libc::SO_ACCEPTFILTER,
libc::accept_filter_arg
);
#[cfg(target_os = "linux")]
sockopt_impl!(
/// Set the mark for each packet sent through this socket (similar to the
@ -1008,10 +1063,10 @@ pub struct AlgSetAeadAuthSize;
impl SetSockOpt for AlgSetAeadAuthSize {
type Val = usize;
fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
fn set<F: AsFd>(&self, fd: &F, val: &usize) -> Result<()> {
unsafe {
let res = libc::setsockopt(
fd,
fd.as_fd().as_raw_fd(),
libc::SOL_ALG,
libc::ALG_SET_AEAD_AUTHSIZE,
::std::ptr::null(),
@ -1042,10 +1097,10 @@ where
{
type Val = T;
fn set(&self, fd: RawFd, val: &T) -> Result<()> {
fn set<F: AsFd>(&self, fd: &F, val: &T) -> Result<()> {
unsafe {
let res = libc::setsockopt(
fd,
fd.as_fd().as_raw_fd(),
libc::SOL_ALG,
libc::ALG_SET_KEY,
val.as_ref().as_ptr() as *const _,
@ -1358,8 +1413,8 @@ mod test {
SockFlag::empty(),
)
.unwrap();
let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
let a_cred = getsockopt(&a, super::PeerCredentials).unwrap();
let b_cred = getsockopt(&b, super::PeerCredentials).unwrap();
assert_eq!(a_cred, b_cred);
assert_ne!(a_cred.pid(), 0);
}
@ -1367,25 +1422,21 @@ mod test {
#[test]
fn is_socket_type_unix() {
use super::super::*;
use crate::unistd::close;
let (a, b) = socketpair(
let (a, _b) = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
let a_type = getsockopt(a, super::SockType).unwrap();
let a_type = getsockopt(&a, super::SockType).unwrap();
assert_eq!(a_type, SockType::Stream);
close(a).unwrap();
close(b).unwrap();
}
#[test]
fn is_socket_type_dgram() {
use super::super::*;
use crate::unistd::close;
let s = socket(
AddressFamily::Inet,
@ -1394,16 +1445,14 @@ mod test {
None,
)
.unwrap();
let s_type = getsockopt(s, super::SockType).unwrap();
let s_type = getsockopt(&s, super::SockType).unwrap();
assert_eq!(s_type, SockType::Datagram);
close(s).unwrap();
}
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
#[test]
fn can_get_listen_on_tcp_socket() {
use super::super::*;
use crate::unistd::close;
let s = socket(
AddressFamily::Inet,
@ -1412,11 +1461,10 @@ mod test {
None,
)
.unwrap();
let s_listening = getsockopt(s, super::AcceptConn).unwrap();
let s_listening = getsockopt(&s, super::AcceptConn).unwrap();
assert!(!s_listening);
listen(s, 10).unwrap();
let s_listening2 = getsockopt(s, super::AcceptConn).unwrap();
listen(&s, 10).unwrap();
let s_listening2 = getsockopt(&s, super::AcceptConn).unwrap();
assert!(s_listening2);
close(s).unwrap();
}
}

4
third_party/rust/nix/src/sys/stat.rs поставляемый
Просмотреть файл

@ -177,7 +177,7 @@ pub fn mknod<P: ?Sized + NixPath>(
dev: dev_t,
) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
libc::mknod(cstr.as_ptr(), kind.bits() | perm.bits() as mode_t, dev)
})?;
Errno::result(res).map(drop)
@ -202,7 +202,7 @@ pub fn mknodat<P: ?Sized + NixPath>(
libc::mknodat(
dirfd,
cstr.as_ptr(),
kind.bits | perm.bits() as mode_t,
kind.bits() | perm.bits() as mode_t,
dev,
)
})?;

6
third_party/rust/nix/src/sys/statfs.rs поставляемый
Просмотреть файл

@ -5,7 +5,7 @@
use std::ffi::CStr;
use std::fmt::{self, Debug};
use std::mem;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use cfg_if::cfg_if;
@ -740,10 +740,10 @@ pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
/// # Arguments
///
/// `fd` - File descriptor of any open file within the file system to describe
pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
pub fn fstatfs<Fd: AsFd>(fd: Fd) -> Result<Statfs> {
unsafe {
let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr()))
Errno::result(LIBC_FSTATFS(fd.as_fd().as_raw_fd(), stat.as_mut_ptr()))
.map(|_| Statfs(stat.assume_init()))
}
}

7
third_party/rust/nix/src/sys/statvfs.rs поставляемый
Просмотреть файл

@ -3,7 +3,7 @@
//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
//! for more details.
use std::mem;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use libc::{self, c_ulong};
@ -12,7 +12,6 @@ use crate::{errno::Errno, NixPath, Result};
#[cfg(not(target_os = "redox"))]
libc_bitflags!(
/// File system mount Flags
#[repr(C)]
#[derive(Default)]
pub struct FsFlags: c_ulong {
/// Read Only
@ -146,11 +145,11 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
}
/// Return a `Statvfs` object with information about `fd`
pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> Result<Statvfs> {
unsafe {
Errno::clear();
let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
Errno::result(libc::fstatvfs(fd.as_fd().as_raw_fd(), stat.as_mut_ptr()))
.map(|_| Statvfs(stat.assume_init()))
}
}

78
third_party/rust/nix/src/sys/termios.rs поставляемый
Просмотреть файл

@ -222,7 +222,7 @@ use libc::{self, c_int, tcflag_t};
use std::cell::{Ref, RefCell};
use std::convert::From;
use std::mem;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
#[cfg(feature = "process")]
use crate::unistd::Pid;
@ -309,7 +309,7 @@ impl Termios {
let termios = *self.inner.borrow_mut();
self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
self.control_flags = ControlFlags::from_bits_retain(termios.c_cflag);
self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
self.control_chars = termios.c_cc;
#[cfg(any(
@ -355,9 +355,9 @@ libc_enum! {
/// enum.
///
/// B0 is special and will disable the port.
#[cfg_attr(all(any(target_os = "haiku"), target_pointer_width = "64"), repr(u8))]
#[cfg_attr(target_os = "haiku", repr(u8))]
#[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
#[cfg_attr(not(all(any(target_os = "ios", target_os = "macos", target_os = "haiku"), target_pointer_width = "64")), repr(u32))]
#[cfg_attr(all(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), not(target_os = "haiku")), repr(u32))]
#[non_exhaustive]
pub enum BaudRate {
B0,
@ -397,6 +397,8 @@ libc_enum! {
#[cfg_attr(docsrs, doc(cfg(all())))]
B28800,
B38400,
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
B57600,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
@ -405,10 +407,14 @@ libc_enum! {
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
B76800,
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
B115200,
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
B153600,
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
B230400,
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
@ -542,6 +548,8 @@ libc_enum! {
#[repr(usize)]
#[non_exhaustive]
pub enum SpecialCharacterIndices {
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
VDISCARD,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
@ -549,6 +557,7 @@ libc_enum! {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "aix",
target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
VDSUSP,
@ -566,7 +575,7 @@ libc_enum! {
VKILL,
VLNEXT,
#[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
target_os = "illumos", target_os = "solaris")))]
target_os = "illumos", target_os = "solaris", target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
VMIN,
VQUIT,
@ -590,9 +599,11 @@ libc_enum! {
#[cfg_attr(docsrs, doc(cfg(all())))]
VSWTCH,
#[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
target_os = "illumos", target_os = "solaris")))]
target_os = "illumos", target_os = "solaris", target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
VTIME,
#[cfg(not(target_os = "aix"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
VWERASE,
#[cfg(target_os = "dragonfly")]
#[cfg_attr(docsrs, doc(cfg(all())))]
@ -603,7 +614,8 @@ libc_enum! {
#[cfg(any(
all(target_os = "linux", target_arch = "sparc64"),
target_os = "illumos",
target_os = "solaris"
target_os = "solaris",
target_os = "aix",
))]
impl SpecialCharacterIndices {
pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
@ -616,6 +628,7 @@ pub use libc::NCCS;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "aix",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
@ -881,7 +894,7 @@ libc_bitflags! {
PARODD;
HUPCL;
CLOCAL;
#[cfg(not(target_os = "redox"))]
#[cfg(not(any(target_os = "redox", target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
CRTSCTS;
#[cfg(any(target_os = "android", target_os = "linux"))]
@ -967,7 +980,7 @@ libc_bitflags! {
#[cfg_attr(docsrs, doc(cfg(all())))]
ALTWERASE;
IEXTEN;
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "aix")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
EXTPROC;
TOSTOP;
@ -1143,10 +1156,12 @@ pub fn cfmakesane(termios: &mut Termios) {
/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
/// this structure *will not* reconfigure the port, instead the modifications should be done to
/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
pub fn tcgetattr<Fd: AsFd>(fd: Fd) -> Result<Termios> {
let mut termios = mem::MaybeUninit::uninit();
let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
let res = unsafe {
libc::tcgetattr(fd.as_fd().as_raw_fd(), termios.as_mut_ptr())
};
Errno::result(res)?;
@ -1159,18 +1174,26 @@ pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
/// takes affect at a time specified by `actions`. Note that this function may return success if
/// *any* of the parameters were successfully set, not only if all were set successfully.
pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
pub fn tcsetattr<Fd: AsFd>(
fd: Fd,
actions: SetArg,
termios: &Termios,
) -> Result<()> {
let inner_termios = termios.get_libc_termios();
Errno::result(unsafe {
libc::tcsetattr(fd, actions as c_int, &*inner_termios)
libc::tcsetattr(
fd.as_fd().as_raw_fd(),
actions as c_int,
&*inner_termios,
)
})
.map(drop)
}
/// Block until all output data is written (see
/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
pub fn tcdrain(fd: RawFd) -> Result<()> {
Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
pub fn tcdrain<Fd: AsFd>(fd: Fd) -> Result<()> {
Errno::result(unsafe { libc::tcdrain(fd.as_fd().as_raw_fd()) }).map(drop)
}
/// Suspend or resume the transmission or reception of data (see
@ -1178,8 +1201,11 @@ pub fn tcdrain(fd: RawFd) -> Result<()> {
///
/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
/// depending on the value of `action`.
pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
pub fn tcflow<Fd: AsFd>(fd: Fd, action: FlowArg) -> Result<()> {
Errno::result(unsafe {
libc::tcflow(fd.as_fd().as_raw_fd(), action as c_int)
})
.map(drop)
}
/// Discard data in the output or input queue (see
@ -1187,8 +1213,11 @@ pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
///
/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
/// depending on the value of `action`.
pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
pub fn tcflush<Fd: AsFd>(fd: Fd, action: FlushArg) -> Result<()> {
Errno::result(unsafe {
libc::tcflush(fd.as_fd().as_raw_fd(), action as c_int)
})
.map(drop)
}
/// Send a break for a specific duration (see
@ -1196,16 +1225,19 @@ pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
///
/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
/// of zero-valued bits for an implementation-defined duration.
pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
pub fn tcsendbreak<Fd: AsFd>(fd: Fd, duration: c_int) -> Result<()> {
Errno::result(unsafe {
libc::tcsendbreak(fd.as_fd().as_raw_fd(), duration)
})
.map(drop)
}
feature! {
#![feature = "process"]
/// Get the session controlled by the given terminal (see
/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
let res = unsafe { libc::tcgetsid(fd) };
pub fn tcgetsid<Fd: AsFd>(fd: Fd) -> Result<Pid> {
let res = unsafe { libc::tcgetsid(fd.as_fd().as_raw_fd()) };
Errno::result(res).map(Pid::from_raw)
}

35
third_party/rust/nix/src/sys/time.rs поставляемый
Просмотреть файл

@ -91,8 +91,10 @@ pub(crate) mod timer {
#[cfg(any(target_os = "android", target_os = "linux"))]
bitflags! {
/// Flags that are used for arming the timer.
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct TimerSetTimeFlags: libc::c_int {
const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET;
}
}
#[cfg(any(
@ -103,6 +105,7 @@ pub(crate) mod timer {
))]
bitflags! {
/// Flags that are used for arming the timer.
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct TimerSetTimeFlags: libc::c_int {
const TFD_TIMER_ABSTIME = libc::TIMER_ABSTIME;
}
@ -261,8 +264,7 @@ impl TimeValLike for TimeSpec {
fn seconds(seconds: i64) -> TimeSpec {
assert!(
(TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&seconds),
"TimeSpec out of bounds; seconds={}",
seconds
"TimeSpec out of bounds; seconds={seconds}",
);
let mut ts = zero_init_timespec();
ts.tv_sec = seconds as time_t;
@ -428,20 +430,20 @@ impl fmt::Display for TimeSpec {
let sec = abs.tv_sec();
write!(f, "{}", sign)?;
write!(f, "{sign}")?;
if abs.tv_nsec() == 0 {
if abs.tv_sec() == 1 {
write!(f, "{} second", sec)?;
if sec == 1 {
write!(f, "1 second")?;
} else {
write!(f, "{} seconds", sec)?;
write!(f, "{sec} seconds")?;
}
} else if abs.tv_nsec() % 1_000_000 == 0 {
write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?;
write!(f, "{sec}.{:03} seconds", abs.tv_nsec() / 1_000_000)?;
} else if abs.tv_nsec() % 1_000 == 0 {
write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?;
write!(f, "{sec}.{:06} seconds", abs.tv_nsec() / 1_000)?;
} else {
write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?;
write!(f, "{sec}.{:09} seconds", abs.tv_nsec())?;
}
Ok(())
@ -497,8 +499,7 @@ impl TimeValLike for TimeVal {
fn seconds(seconds: i64) -> TimeVal {
assert!(
(TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&seconds),
"TimeVal out of bounds; seconds={}",
seconds
"TimeVal out of bounds; seconds={seconds}"
);
#[cfg_attr(target_env = "musl", allow(deprecated))]
// https://github.com/rust-lang/libc/issues/1848
@ -662,18 +663,18 @@ impl fmt::Display for TimeVal {
let sec = abs.tv_sec();
write!(f, "{}", sign)?;
write!(f, "{sign}")?;
if abs.tv_usec() == 0 {
if abs.tv_sec() == 1 {
write!(f, "{} second", sec)?;
if sec == 1 {
write!(f, "1 second")?;
} else {
write!(f, "{} seconds", sec)?;
write!(f, "{sec} seconds")?;
}
} else if abs.tv_usec() % 1000 == 0 {
write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?;
write!(f, "{sec}.{:03} seconds", abs.tv_usec() / 1000)?;
} else {
write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?;
write!(f, "{sec}.{:06} seconds", abs.tv_usec())?;
}
Ok(())

54
third_party/rust/nix/src/sys/timerfd.rs поставляемый
Просмотреть файл

@ -33,24 +33,28 @@ pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
use crate::unistd::read;
use crate::{errno::Errno, Result};
use libc::c_int;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
/// A timerfd instance. This is also a file descriptor, you can feed it to
/// other interfaces consuming file descriptors, epoll for example.
/// other interfaces taking file descriptors as arguments, [`epoll`] for example.
///
/// [`epoll`]: crate::sys::epoll
#[derive(Debug)]
pub struct TimerFd {
fd: RawFd,
fd: OwnedFd,
}
impl AsRawFd for TimerFd {
fn as_raw_fd(&self) -> RawFd {
self.fd
impl AsFd for TimerFd {
fn as_fd(&self) -> BorrowedFd<'_> {
self.fd.as_fd()
}
}
impl FromRawFd for TimerFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
TimerFd { fd }
TimerFd {
fd: OwnedFd::from_raw_fd(fd),
}
}
}
@ -97,7 +101,9 @@ impl TimerFd {
Errno::result(unsafe {
libc::timerfd_create(clockid as i32, flags.bits())
})
.map(|fd| Self { fd })
.map(|fd| Self {
fd: unsafe { OwnedFd::from_raw_fd(fd) },
})
}
/// Sets a new alarm on the timer.
@ -129,6 +135,13 @@ impl TimerFd {
/// Then the one shot TimeSpec and the delay TimeSpec of the delayed
/// interval are going to be interpreted as absolute.
///
/// # Cancel on a clock change
///
/// If you set a `TFD_TIMER_CANCEL_ON_SET` alongside `TFD_TIMER_ABSTIME`
/// and the clock for this timer is `CLOCK_REALTIME` or `CLOCK_REALTIME_ALARM`,
/// then this timer is marked as cancelable if the real-time clock undergoes
/// a discontinuous change.
///
/// # Disabling alarms
///
/// Note: Only one alarm can be set for any given timer. Setting a new alarm
@ -145,7 +158,7 @@ impl TimerFd {
let timerspec: TimerSpec = expiration.into();
Errno::result(unsafe {
libc::timerfd_settime(
self.fd,
self.fd.as_fd().as_raw_fd(),
flags.bits(),
timerspec.as_ref(),
std::ptr::null_mut(),
@ -159,7 +172,10 @@ impl TimerFd {
pub fn get(&self) -> Result<Option<Expiration>> {
let mut timerspec = TimerSpec::none();
Errno::result(unsafe {
libc::timerfd_gettime(self.fd, timerspec.as_mut())
libc::timerfd_gettime(
self.fd.as_fd().as_raw_fd(),
timerspec.as_mut(),
)
})
.map(|_| {
if timerspec.as_ref().it_interval.tv_sec == 0
@ -179,7 +195,7 @@ impl TimerFd {
pub fn unset(&self) -> Result<()> {
Errno::result(unsafe {
libc::timerfd_settime(
self.fd,
self.fd.as_fd().as_raw_fd(),
TimerSetTimeFlags::empty().bits(),
TimerSpec::none().as_ref(),
std::ptr::null_mut(),
@ -192,7 +208,10 @@ impl TimerFd {
///
/// Note: If the alarm is unset, then you will wait forever.
pub fn wait(&self) -> Result<()> {
while let Err(e) = read(self.fd, &mut [0u8; 8]) {
while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) {
if e == Errno::ECANCELED {
break;
}
if e != Errno::EINTR {
return Err(e);
}
@ -201,14 +220,3 @@ impl TimerFd {
Ok(())
}
}
impl Drop for TimerFd {
fn drop(&mut self) {
if !std::thread::panicking() {
let result = Errno::result(unsafe { libc::close(self.fd) });
if let Err(Errno::EBADF) = result {
panic!("close of TimerFd encountered EBADF");
}
}
}
}

106
third_party/rust/nix/src/sys/uio.rs поставляемый
Просмотреть файл

@ -4,13 +4,12 @@ use crate::errno::Errno;
use crate::Result;
use libc::{self, c_int, c_void, off_t, size_t};
use std::io::{IoSlice, IoSliceMut};
use std::marker::PhantomData;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
/// Low-level vectored write to a raw file descriptor
///
/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html)
pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> {
// SAFETY: to quote the documentation for `IoSlice`:
//
// [IoSlice] is semantically a wrapper around a &[u8], but is
@ -19,7 +18,7 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
//
// Because it is ABI compatible, a pointer cast here is valid
let res = unsafe {
libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
libc::writev(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
};
Errno::result(res).map(|r| r as usize)
@ -28,10 +27,13 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
/// Low-level vectored read from a raw file descriptor
///
/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html)
pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
// Clippy doesn't know that we need to pass iov mutably only because the
// mutation happens after converting iov to a pointer
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
// SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec
let res = unsafe {
libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
libc::readv(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
};
Errno::result(res).map(|r| r as usize)
@ -45,14 +47,14 @@ pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
// SAFETY: same as in writev()
let res = unsafe {
libc::pwritev(
fd,
fd.as_fd().as_raw_fd(),
iov.as_ptr() as *const libc::iovec,
iov.len() as c_int,
offset,
@ -71,8 +73,11 @@ pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn preadv(
fd: RawFd,
// Clippy doesn't know that we need to pass iov mutably only because the
// mutation happens after converting iov to a pointer
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn preadv<Fd: AsFd>(
fd: Fd,
iov: &mut [IoSliceMut<'_>],
offset: off_t,
) -> Result<usize> {
@ -82,7 +87,7 @@ pub fn preadv(
// SAFETY: same as in readv()
let res = unsafe {
libc::preadv(
fd,
fd.as_fd().as_raw_fd(),
iov.as_ptr() as *const libc::iovec,
iov.len() as c_int,
offset,
@ -96,10 +101,10 @@ pub fn preadv(
///
/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html)
// TODO: move to unistd
pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: off_t) -> Result<usize> {
let res = unsafe {
libc::pwrite(
fd,
fd.as_fd().as_raw_fd(),
buf.as_ptr() as *const c_void,
buf.len() as size_t,
offset,
@ -113,10 +118,10 @@ pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
///
/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
// TODO: move to unistd
pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize> {
pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> {
let res = unsafe {
libc::pread(
fd,
fd.as_fd().as_raw_fd(),
buf.as_mut_ptr() as *mut c_void,
buf.len() as size_t,
offset,
@ -145,77 +150,6 @@ pub struct RemoteIoVec {
pub len: usize,
}
/// A vector of buffers.
///
/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for
/// both reading and writing. Each `IoVec` specifies the base address and
/// length of an area in memory.
#[deprecated(
since = "0.24.0",
note = "`IoVec` is no longer used in the public interface, use `IoSlice` or `IoSliceMut` instead"
)]
#[repr(transparent)]
#[allow(renamed_and_removed_lints)]
#[allow(clippy::unknown_clippy_lints)]
// Clippy false positive: https://github.com/rust-lang/rust-clippy/issues/8867
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct IoVec<T>(pub(crate) libc::iovec, PhantomData<T>);
#[allow(deprecated)]
impl<T> IoVec<T> {
/// View the `IoVec` as a Rust slice.
#[deprecated(
since = "0.24.0",
note = "Use the `Deref` impl of `IoSlice` or `IoSliceMut` instead"
)]
#[inline]
pub fn as_slice(&self) -> &[u8] {
use std::slice;
unsafe {
slice::from_raw_parts(self.0.iov_base as *const u8, self.0.iov_len)
}
}
}
#[allow(deprecated)]
impl<'a> IoVec<&'a [u8]> {
/// Create an `IoVec` from a Rust slice.
#[deprecated(since = "0.24.0", note = "Use `IoSlice::new` instead")]
pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
IoVec(
libc::iovec {
iov_base: buf.as_ptr() as *mut c_void,
iov_len: buf.len() as size_t,
},
PhantomData,
)
}
}
#[allow(deprecated)]
impl<'a> IoVec<&'a mut [u8]> {
/// Create an `IoVec` from a mutable Rust slice.
#[deprecated(since = "0.24.0", note = "Use `IoSliceMut::new` instead")]
pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
IoVec(
libc::iovec {
iov_base: buf.as_ptr() as *mut c_void,
iov_len: buf.len() as size_t,
},
PhantomData,
)
}
}
// The only reason IoVec isn't automatically Send+Sync is because libc::iovec
// contains raw pointers.
#[allow(deprecated)]
unsafe impl<T> Send for IoVec<T> where T: Send {}
#[allow(deprecated)]
unsafe impl<T> Sync for IoVec<T> where T: Sync {}
feature! {
#![feature = "process"]

15
third_party/rust/nix/src/sys/wait.rs поставляемый
Просмотреть файл

@ -10,7 +10,7 @@ use std::convert::TryFrom;
target_os = "android",
all(target_os = "linux", not(target_env = "uclibc")),
))]
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsRawFd, BorrowedFd};
libc_bitflags!(
/// Controls the behavior of [`waitpid`].
@ -343,8 +343,8 @@ pub fn wait() -> Result<WaitStatus> {
target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Id {
#[derive(Debug)]
pub enum Id<'fd> {
/// Wait for any child
All,
/// Wait for the child whose process ID matches the given PID
@ -355,7 +355,11 @@ pub enum Id {
PGid(Pid),
/// Wait for the child referred to by the given PID file descriptor
#[cfg(any(target_os = "android", target_os = "linux"))]
PIDFd(RawFd),
PIDFd(BorrowedFd<'fd>),
/// A helper variant to resolve the unused parameter (`'fd`) problem on platforms
/// other than Linux and Android.
#[doc(hidden)]
_Unreachable(std::marker::PhantomData<&'fd std::convert::Infallible>),
}
/// Wait for a process to change status
@ -373,7 +377,8 @@ pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> {
Id::Pid(pid) => (libc::P_PID, pid.as_raw() as libc::id_t),
Id::PGid(pid) => (libc::P_PGID, pid.as_raw() as libc::id_t),
#[cfg(any(target_os = "android", target_os = "linux"))]
Id::PIDFd(fd) => (libc::P_PIDFD, fd as libc::id_t),
Id::PIDFd(fd) => (libc::P_PIDFD, fd.as_raw_fd() as libc::id_t),
Id::_Unreachable(_) => unreachable!("This variant could never be constructed"),
};
let siginfo = unsafe {

1578
third_party/rust/nix/src/unistd.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

10
third_party/rust/nix/test/sys/test_aio.rs поставляемый
Просмотреть файл

@ -21,9 +21,7 @@ use nix::{
};
use tempfile::tempfile;
lazy_static! {
pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
}
pub static SIGNALED: AtomicBool = AtomicBool::new(false);
extern "C" fn sigfunc(_: c_int) {
SIGNALED.store(true, Ordering::Relaxed);
@ -200,7 +198,7 @@ mod aio_read {
assert_eq!(err, Ok(()));
assert_eq!(aior.as_mut().aio_return().unwrap(), EXPECT.len());
}
assert_eq!(EXPECT, rbuf.deref().deref());
assert_eq!(EXPECT, rbuf.deref());
}
// Like ok, but allocates the structure on the stack.
@ -223,7 +221,7 @@ mod aio_read {
assert_eq!(err, Ok(()));
assert_eq!(aior.as_mut().aio_return().unwrap(), EXPECT.len());
}
assert_eq!(EXPECT, rbuf.deref().deref());
assert_eq!(EXPECT, rbuf.deref());
}
}
@ -610,7 +608,7 @@ fn test_aio_suspend() {
let r = aio_suspend(&cbbuf[..], Some(timeout));
match r {
Err(Errno::EINTR) => continue,
Err(e) => panic!("aio_suspend returned {:?}", e),
Err(e) => panic!("aio_suspend returned {e:?}"),
Ok(_) => (),
};
}

2
third_party/rust/nix/test/sys/test_epoll.rs поставляемый
Просмотреть файл

@ -1,3 +1,5 @@
#![allow(deprecated)]
use nix::errno::Errno;
use nix::sys::epoll::{epoll_create1, epoll_ctl};
use nix::sys::epoll::{EpollCreateFlags, EpollEvent, EpollFlags, EpollOp};

14
third_party/rust/nix/test/sys/test_mman.rs поставляемый
Просмотреть файл

@ -1,15 +1,15 @@
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use std::num::NonZeroUsize;
use std::{num::NonZeroUsize, os::unix::io::BorrowedFd};
#[test]
fn test_mmap_anonymous() {
unsafe {
let ptr = mmap(
let ptr = mmap::<BorrowedFd>(
None,
NonZeroUsize::new(1).unwrap(),
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
-1,
None,
0,
)
.unwrap() as *mut u8;
@ -29,12 +29,12 @@ fn test_mremap_grow() {
let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
let mem = mmap(
let mem = mmap::<BorrowedFd>(
None,
one_k_non_zero,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
None,
0,
)
.unwrap();
@ -87,12 +87,12 @@ fn test_mremap_shrink() {
const ONE_K: size_t = 1024;
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
let mem = mmap(
let mem = mmap::<BorrowedFd>(
None,
ten_one_k,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
None,
0,
)
.unwrap();

125
third_party/rust/nix/test/sys/test_prctl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,125 @@
#[cfg(target_os = "linux")]
#[cfg(feature = "process")]
mod test_prctl {
use std::ffi::CStr;
use nix::sys::prctl;
#[cfg_attr(qemu, ignore)]
#[test]
fn test_get_set_subreaper() {
let original = prctl::get_child_subreaper().unwrap();
prctl::set_child_subreaper(true).unwrap();
let subreaper = prctl::get_child_subreaper().unwrap();
assert!(subreaper);
prctl::set_child_subreaper(original).unwrap();
}
#[test]
fn test_get_set_dumpable() {
let original = prctl::get_dumpable().unwrap();
prctl::set_dumpable(false).unwrap();
let dumpable = prctl::get_dumpable().unwrap();
assert!(!dumpable);
prctl::set_dumpable(original).unwrap();
}
#[test]
fn test_get_set_keepcaps() {
let original = prctl::get_keepcaps().unwrap();
prctl::set_keepcaps(true).unwrap();
let keepcaps = prctl::get_keepcaps().unwrap();
assert!(keepcaps);
prctl::set_keepcaps(original).unwrap();
}
#[test]
fn test_get_set_clear_mce_kill() {
use prctl::PrctlMCEKillPolicy::*;
prctl::set_mce_kill(PR_MCE_KILL_LATE).unwrap();
let mce = prctl::get_mce_kill().unwrap();
assert_eq!(mce, PR_MCE_KILL_LATE);
prctl::clear_mce_kill().unwrap();
let mce = prctl::get_mce_kill().unwrap();
assert_eq!(mce, PR_MCE_KILL_DEFAULT);
}
#[cfg_attr(qemu, ignore)]
#[test]
fn test_get_set_pdeathsig() {
use nix::sys::signal::Signal;
let original = prctl::get_pdeathsig().unwrap();
prctl::set_pdeathsig(Signal::SIGUSR1).unwrap();
let sig = prctl::get_pdeathsig().unwrap();
assert_eq!(sig, Some(Signal::SIGUSR1));
prctl::set_pdeathsig(original).unwrap();
}
#[test]
fn test_get_set_name() {
let original = prctl::get_name().unwrap();
let long_name =
CStr::from_bytes_with_nul(b"0123456789abcdefghijklmn\0").unwrap();
prctl::set_name(long_name).unwrap();
let res = prctl::get_name().unwrap();
// name truncated by kernel to TASK_COMM_LEN
assert_eq!(&long_name.to_str().unwrap()[..15], res.to_str().unwrap());
let short_name = CStr::from_bytes_with_nul(b"01234567\0").unwrap();
prctl::set_name(short_name).unwrap();
let res = prctl::get_name().unwrap();
assert_eq!(short_name.to_str().unwrap(), res.to_str().unwrap());
prctl::set_name(&original).unwrap();
}
#[cfg_attr(qemu, ignore)]
#[test]
fn test_get_set_timerslack() {
let original = prctl::get_timerslack().unwrap();
let slack = 60_000;
prctl::set_timerslack(slack).unwrap();
let res = prctl::get_timerslack().unwrap();
assert_eq!(slack, res as u64);
prctl::set_timerslack(original as u64).unwrap();
}
#[test]
fn test_disable_enable_perf_events() {
prctl::task_perf_events_disable().unwrap();
prctl::task_perf_events_enable().unwrap();
}
#[test]
fn test_get_set_no_new_privs() {
prctl::set_no_new_privs().unwrap();
let no_new_privs = prctl::get_no_new_privs().unwrap();
assert!(no_new_privs);
}
#[test]
fn test_get_set_thp_disable() {
let original = prctl::get_thp_disable().unwrap();
prctl::set_thp_disable(true).unwrap();
let thp_disable = prctl::get_thp_disable().unwrap();
assert!(thp_disable);
prctl::set_thp_disable(original).unwrap();
}
}

31
third_party/rust/nix/test/sys/test_select.rs поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ use nix::sys::select::*;
use nix::sys::signal::SigSet;
use nix::sys::time::{TimeSpec, TimeValLike};
use nix::unistd::{pipe, write};
use std::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
#[test]
pub fn test_pselect() {
@ -9,11 +10,13 @@ pub fn test_pselect() {
let (r1, w1) = pipe().unwrap();
write(w1, b"hi!").unwrap();
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
let (r2, _w2) = pipe().unwrap();
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
fd_set.insert(r1);
fd_set.insert(r2);
fd_set.insert(&r1);
fd_set.insert(&r2);
let timeout = TimeSpec::seconds(10);
let sigmask = SigSet::empty();
@ -21,25 +24,27 @@ pub fn test_pselect() {
1,
pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
);
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
assert!(fd_set.contains(&r1));
assert!(!fd_set.contains(&r2));
}
#[test]
pub fn test_pselect_nfds2() {
let (r1, w1) = pipe().unwrap();
write(w1, b"hi!").unwrap();
let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
let (r2, _w2) = pipe().unwrap();
let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
fd_set.insert(r1);
fd_set.insert(r2);
fd_set.insert(&r1);
fd_set.insert(&r2);
let timeout = TimeSpec::seconds(10);
assert_eq!(
1,
pselect(
::std::cmp::max(r1, r2) + 1,
std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
&mut fd_set,
None,
None,
@ -48,8 +53,8 @@ pub fn test_pselect_nfds2() {
)
.unwrap()
);
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
assert!(fd_set.contains(&r1));
assert!(!fd_set.contains(&r2));
}
macro_rules! generate_fdset_bad_fd_tests {
@ -58,17 +63,13 @@ macro_rules! generate_fdset_bad_fd_tests {
#[test]
#[should_panic]
fn $method() {
FdSet::new().$method($fd);
let bad_fd = unsafe{BorrowedFd::borrow_raw($fd)};
FdSet::new().$method(&bad_fd);
}
)*
}
}
mod test_fdset_negative_fd {
use super::*;
generate_fdset_bad_fd_tests!(-1, insert, remove, contains);
}
mod test_fdset_too_large_fd {
use super::*;
use std::convert::TryInto;

12
third_party/rust/nix/test/sys/test_signal.rs поставляемый
Просмотреть файл

@ -54,9 +54,8 @@ fn test_sigprocmask() {
// test don't make sense.
assert!(
!old_signal_set.contains(SIGNAL),
"the {:?} signal is already blocked, please change to a \
different one",
SIGNAL
"the {SIGNAL:?} signal is already blocked, please change to a \
different one"
);
// Now block the signal.
@ -71,8 +70,7 @@ fn test_sigprocmask() {
.expect("expect to be able to retrieve old signals");
assert!(
old_signal_set.contains(SIGNAL),
"expected the {:?} to be blocked",
SIGNAL
"expected the {SIGNAL:?} to be blocked"
);
// Reset the signal.
@ -80,9 +78,7 @@ fn test_sigprocmask() {
.expect("expect to be able to block signals");
}
lazy_static! {
static ref SIGNALED: AtomicBool = AtomicBool::new(false);
}
static SIGNALED: AtomicBool = AtomicBool::new(false);
extern "C" fn test_sigaction_handler(signal: libc::c_int) {
let signal = Signal::try_from(signal).unwrap();

713
third_party/rust/nix/test/sys/test_socket.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

135
third_party/rust/nix/test/sys/test_sockopt.rs поставляемый
Просмотреть файл

@ -5,6 +5,7 @@ use nix::sys::socket::{
SockProtocol, SockType,
};
use rand::{thread_rng, Rng};
use std::os::unix::io::AsRawFd;
// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",))]
@ -22,7 +23,7 @@ pub fn test_local_peercred_seqpacket() {
SockFlag::empty(),
)
.unwrap();
let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
let xucred = getsockopt(&fd1, sockopt::LocalPeerCred).unwrap();
assert_eq!(xucred.version(), 0);
assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
@ -48,12 +49,28 @@ pub fn test_local_peercred_stream() {
SockFlag::empty(),
)
.unwrap();
let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
let xucred = getsockopt(&fd1, sockopt::LocalPeerCred).unwrap();
assert_eq!(xucred.version(), 0);
assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[test]
pub fn test_local_peer_pid() {
use nix::sys::socket::socketpair;
let (fd1, _fd2) = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
let pid = getsockopt(&fd1, sockopt::LocalPeerPid).unwrap();
assert_eq!(pid, std::process::id() as _);
}
#[cfg(target_os = "linux")]
#[test]
fn is_so_mark_functional() {
@ -68,8 +85,8 @@ fn is_so_mark_functional() {
None,
)
.unwrap();
setsockopt(s, sockopt::Mark, &1337).unwrap();
let mark = getsockopt(s, sockopt::Mark).unwrap();
setsockopt(&s, sockopt::Mark, &1337).unwrap();
let mark = getsockopt(&s, sockopt::Mark).unwrap();
assert_eq!(mark, 1337);
}
@ -83,18 +100,18 @@ fn test_so_buf() {
)
.unwrap();
let bufsize: usize = thread_rng().gen_range(4096..131_072);
setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
setsockopt(&fd, sockopt::SndBuf, &bufsize).unwrap();
let actual = getsockopt(&fd, sockopt::SndBuf).unwrap();
assert!(actual >= bufsize);
setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
setsockopt(&fd, sockopt::RcvBuf, &bufsize).unwrap();
let actual = getsockopt(&fd, sockopt::RcvBuf).unwrap();
assert!(actual >= bufsize);
}
#[test]
fn test_so_tcp_maxseg() {
use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn};
use nix::unistd::{close, write};
use nix::unistd::write;
use std::net::SocketAddrV4;
use std::str::FromStr;
@ -108,9 +125,9 @@ fn test_so_tcp_maxseg() {
SockProtocol::Tcp,
)
.unwrap();
bind(rsock, &sock_addr).unwrap();
listen(rsock, 10).unwrap();
let initial = getsockopt(rsock, sockopt::TcpMaxSeg).unwrap();
bind(rsock.as_raw_fd(), &sock_addr).unwrap();
listen(&rsock, 10).unwrap();
let initial = getsockopt(&rsock, sockopt::TcpMaxSeg).unwrap();
// Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
// platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
// than 700
@ -118,7 +135,7 @@ fn test_so_tcp_maxseg() {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
let segsize: u32 = 873;
assert!(initial < segsize);
setsockopt(rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
setsockopt(&rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
} else {
assert!(initial < 700);
}
@ -132,10 +149,10 @@ fn test_so_tcp_maxseg() {
SockProtocol::Tcp,
)
.unwrap();
connect(ssock, &sock_addr).unwrap();
let rsess = accept(rsock).unwrap();
connect(ssock.as_raw_fd(), &sock_addr).unwrap();
let rsess = accept(rsock.as_raw_fd()).unwrap();
write(rsess, b"hello").unwrap();
let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap();
let actual = getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap();
// Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
// TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
cfg_if! {
@ -147,8 +164,6 @@ fn test_so_tcp_maxseg() {
assert!(536 < actual);
}
}
close(rsock).unwrap();
close(ssock).unwrap();
}
#[test]
@ -161,7 +176,7 @@ fn test_so_type() {
)
.unwrap();
assert_eq!(Ok(SockType::Stream), getsockopt(sockfd, sockopt::SockType));
assert_eq!(Ok(SockType::Stream), getsockopt(&sockfd, sockopt::SockType));
}
/// getsockopt(_, sockopt::SockType) should gracefully handle unknown socket
@ -170,12 +185,14 @@ fn test_so_type() {
#[test]
fn test_so_type_unknown() {
use nix::errno::Errno;
use std::os::unix::io::{FromRawFd, OwnedFd};
require_capability!("test_so_type", CAP_NET_RAW);
let sockfd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
assert!(sockfd >= 0, "Error opening socket: {}", nix::Error::last());
let raw_fd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
assert!(raw_fd >= 0, "Error opening socket: {}", nix::Error::last());
let sockfd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
assert_eq!(Err(Errno::EINVAL), getsockopt(sockfd, sockopt::SockType));
assert_eq!(Err(Errno::EINVAL), getsockopt(&sockfd, sockopt::SockType));
}
// The CI doesn't supported getsockopt and setsockopt on emulated processors.
@ -198,17 +215,17 @@ fn test_tcp_congestion() {
)
.unwrap();
let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
let val = getsockopt(&fd, sockopt::TcpCongestion).unwrap();
setsockopt(&fd, sockopt::TcpCongestion, &val).unwrap();
setsockopt(
fd,
&fd,
sockopt::TcpCongestion,
&OsString::from("tcp_congestion_does_not_exist"),
)
.unwrap_err();
assert_eq!(getsockopt(fd, sockopt::TcpCongestion).unwrap(), val);
assert_eq!(getsockopt(&fd, sockopt::TcpCongestion).unwrap(), val);
}
#[test]
@ -224,10 +241,10 @@ fn test_bindtodevice() {
)
.unwrap();
let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
let val = getsockopt(&fd, sockopt::BindToDevice).unwrap();
setsockopt(&fd, sockopt::BindToDevice, &val).unwrap();
assert_eq!(getsockopt(fd, sockopt::BindToDevice).unwrap(), val);
assert_eq!(getsockopt(&fd, sockopt::BindToDevice).unwrap(), val);
}
#[test]
@ -239,8 +256,8 @@ fn test_so_tcp_keepalive() {
SockProtocol::Tcp,
)
.unwrap();
setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
assert!(getsockopt(fd, sockopt::KeepAlive).unwrap());
setsockopt(&fd, sockopt::KeepAlive, &true).unwrap();
assert!(getsockopt(&fd, sockopt::KeepAlive).unwrap());
#[cfg(any(
target_os = "android",
@ -249,17 +266,17 @@ fn test_so_tcp_keepalive() {
target_os = "linux"
))]
{
let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
let x = getsockopt(&fd, sockopt::TcpKeepIdle).unwrap();
setsockopt(&fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
assert_eq!(getsockopt(&fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
let x = getsockopt(&fd, sockopt::TcpKeepCount).unwrap();
setsockopt(&fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
assert_eq!(getsockopt(&fd, sockopt::TcpKeepCount).unwrap(), x + 1);
let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
let x = getsockopt(&fd, sockopt::TcpKeepInterval).unwrap();
setsockopt(&fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
assert_eq!(getsockopt(&fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
}
}
@ -283,11 +300,11 @@ fn test_get_mtu() {
.unwrap();
// Bind and initiate connection
bind(usock, &SockaddrIn::from(std_sa)).unwrap();
connect(usock, &SockaddrIn::from(std_sb)).unwrap();
bind(usock.as_raw_fd(), &SockaddrIn::from(std_sa)).unwrap();
connect(usock.as_raw_fd(), &SockaddrIn::from(std_sb)).unwrap();
// Loopback connections have 2^16 - the maximum - MTU
assert_eq!(getsockopt(usock, sockopt::IpMtu), Ok(u16::MAX as i32))
assert_eq!(getsockopt(&usock, sockopt::IpMtu), Ok(u16::MAX as i32))
}
#[test]
@ -300,7 +317,7 @@ fn test_ttl_opts() {
None,
)
.unwrap();
setsockopt(fd4, sockopt::Ipv4Ttl, &1)
setsockopt(&fd4, sockopt::Ipv4Ttl, &1)
.expect("setting ipv4ttl on an inet socket should succeed");
let fd6 = socket(
AddressFamily::Inet6,
@ -309,7 +326,7 @@ fn test_ttl_opts() {
None,
)
.unwrap();
setsockopt(fd6, sockopt::Ipv6Ttl, &1)
setsockopt(&fd6, sockopt::Ipv6Ttl, &1)
.expect("setting ipv6ttl on an inet6 socket should succeed");
}
@ -323,9 +340,9 @@ fn test_dontfrag_opts() {
SockProtocol::Tcp,
)
.unwrap();
setsockopt(fd4, sockopt::IpDontFrag, &true)
setsockopt(&fd4, sockopt::IpDontFrag, &true)
.expect("setting IP_DONTFRAG on an inet stream socket should succeed");
setsockopt(fd4, sockopt::IpDontFrag, &false).expect(
setsockopt(&fd4, sockopt::IpDontFrag, &false).expect(
"unsetting IP_DONTFRAG on an inet stream socket should succeed",
);
let fd4d = socket(
@ -335,10 +352,10 @@ fn test_dontfrag_opts() {
None,
)
.unwrap();
setsockopt(fd4d, sockopt::IpDontFrag, &true).expect(
setsockopt(&fd4d, sockopt::IpDontFrag, &true).expect(
"setting IP_DONTFRAG on an inet datagram socket should succeed",
);
setsockopt(fd4d, sockopt::IpDontFrag, &false).expect(
setsockopt(&fd4d, sockopt::IpDontFrag, &false).expect(
"unsetting IP_DONTFRAG on an inet datagram socket should succeed",
);
}
@ -361,10 +378,10 @@ fn test_v6dontfrag_opts() {
SockProtocol::Tcp,
)
.unwrap();
setsockopt(fd6, sockopt::Ipv6DontFrag, &true).expect(
setsockopt(&fd6, sockopt::Ipv6DontFrag, &true).expect(
"setting IPV6_DONTFRAG on an inet6 stream socket should succeed",
);
setsockopt(fd6, sockopt::Ipv6DontFrag, &false).expect(
setsockopt(&fd6, sockopt::Ipv6DontFrag, &false).expect(
"unsetting IPV6_DONTFRAG on an inet6 stream socket should succeed",
);
let fd6d = socket(
@ -374,10 +391,10 @@ fn test_v6dontfrag_opts() {
None,
)
.unwrap();
setsockopt(fd6d, sockopt::Ipv6DontFrag, &true).expect(
setsockopt(&fd6d, sockopt::Ipv6DontFrag, &true).expect(
"setting IPV6_DONTFRAG on an inet6 datagram socket should succeed",
);
setsockopt(fd6d, sockopt::Ipv6DontFrag, &false).expect(
setsockopt(&fd6d, sockopt::Ipv6DontFrag, &false).expect(
"unsetting IPV6_DONTFRAG on an inet6 datagram socket should succeed",
);
}
@ -393,8 +410,8 @@ fn test_so_priority() {
)
.unwrap();
let priority = 3;
setsockopt(fd, sockopt::Priority, &priority).unwrap();
assert_eq!(getsockopt(fd, sockopt::Priority).unwrap(), priority);
setsockopt(&fd, sockopt::Priority, &priority).unwrap();
assert_eq!(getsockopt(&fd, sockopt::Priority).unwrap(), priority);
}
#[test]
@ -408,8 +425,8 @@ fn test_ip_tos() {
)
.unwrap();
let tos = 0x80; // CS4
setsockopt(fd, sockopt::IpTos, &tos).unwrap();
assert_eq!(getsockopt(fd, sockopt::IpTos).unwrap(), tos);
setsockopt(&fd, sockopt::IpTos, &tos).unwrap();
assert_eq!(getsockopt(&fd, sockopt::IpTos).unwrap(), tos);
}
#[test]
@ -426,6 +443,6 @@ fn test_ipv6_tclass() {
)
.unwrap();
let class = 0x80; // CS4
setsockopt(fd, sockopt::Ipv6TClass, &class).unwrap();
assert_eq!(getsockopt(fd, sockopt::Ipv6TClass).unwrap(), class);
setsockopt(&fd, sockopt::Ipv6TClass, &class).unwrap();
assert_eq!(getsockopt(&fd, sockopt::Ipv6TClass).unwrap(), class);
}

59
third_party/rust/nix/test/sys/test_termios.rs поставляемый
Просмотреть файл

@ -1,17 +1,17 @@
use std::os::unix::prelude::*;
use std::os::unix::io::{AsFd, AsRawFd};
use tempfile::tempfile;
use nix::errno::Errno;
use nix::fcntl;
use nix::pty::openpty;
use nix::sys::termios::{self, tcgetattr, LocalFlags, OutputFlags};
use nix::unistd::{close, read, write};
use nix::unistd::{read, write};
/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
fn write_all(f: RawFd, buf: &[u8]) {
/// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s
fn write_all<Fd: AsFd>(f: Fd, buf: &[u8]) {
let mut len = 0;
while len < buf.len() {
len += write(f, &buf[len..]).unwrap();
len += write(f.as_fd().as_raw_fd(), &buf[len..]).unwrap();
}
}
@ -22,25 +22,14 @@ fn test_tcgetattr_pty() {
let _m = crate::PTSNAME_MTX.lock();
let pty = openpty(None, None).expect("openpty failed");
termios::tcgetattr(pty.slave).unwrap();
close(pty.master).expect("closing the master failed");
close(pty.slave).expect("closing the slave failed");
termios::tcgetattr(&pty.slave).unwrap();
}
// Test tcgetattr on something that isn't a terminal
#[test]
fn test_tcgetattr_enotty() {
let file = tempfile().unwrap();
assert_eq!(
termios::tcgetattr(file.as_raw_fd()).err(),
Some(Errno::ENOTTY)
);
}
// Test tcgetattr on an invalid file descriptor
#[test]
fn test_tcgetattr_ebadf() {
assert_eq!(termios::tcgetattr(-1).err(), Some(Errno::EBADF));
assert_eq!(termios::tcgetattr(&file).err(), Some(Errno::ENOTTY));
}
// Test modifying output flags
@ -52,12 +41,7 @@ fn test_output_flags() {
// Open one pty to get attributes for the second one
let mut termios = {
let pty = openpty(None, None).expect("openpty failed");
assert!(pty.master > 0);
assert!(pty.slave > 0);
let termios = tcgetattr(pty.slave).expect("tcgetattr failed");
close(pty.master).unwrap();
close(pty.slave).unwrap();
termios
tcgetattr(&pty.slave).expect("tcgetattr failed")
};
// Make sure postprocessing '\r' isn't specified by default or this test is useless.
@ -73,19 +57,15 @@ fn test_output_flags() {
// Open a pty
let pty = openpty(None, &termios).unwrap();
assert!(pty.master > 0);
assert!(pty.slave > 0);
// Write into the master
let string = "foofoofoo\r";
write_all(pty.master, string.as_bytes());
write_all(&pty.master, string.as_bytes());
// Read from the slave verifying that the output has been properly transformed
let mut buf = [0u8; 10];
crate::read_exact(pty.slave, &mut buf);
crate::read_exact(&pty.slave, &mut buf);
let transformed_string = "foofoofoo\n";
close(pty.master).unwrap();
close(pty.slave).unwrap();
assert_eq!(&buf, transformed_string.as_bytes());
}
@ -98,12 +78,7 @@ fn test_local_flags() {
// Open one pty to get attributes for the second one
let mut termios = {
let pty = openpty(None, None).unwrap();
assert!(pty.master > 0);
assert!(pty.slave > 0);
let termios = tcgetattr(pty.slave).unwrap();
close(pty.master).unwrap();
close(pty.slave).unwrap();
termios
tcgetattr(&pty.slave).unwrap()
};
// Make sure echo is specified by default or this test is useless.
@ -114,23 +89,19 @@ fn test_local_flags() {
// Open a new pty with our modified termios settings
let pty = openpty(None, &termios).unwrap();
assert!(pty.master > 0);
assert!(pty.slave > 0);
// Set the master is in nonblocking mode or reading will never return.
let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
let flags = fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_GETFL).unwrap();
let new_flags =
fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_SETFL(new_flags)).unwrap();
// Write into the master
let string = "foofoofoo\r";
write_all(pty.master, string.as_bytes());
write_all(&pty.master, string.as_bytes());
// Try to read from the master, which should not have anything as echoing was disabled.
let mut buf = [0u8; 10];
let read = read(pty.master, &mut buf).unwrap_err();
close(pty.master).unwrap();
close(pty.slave).unwrap();
let read = read(pty.master.as_raw_fd(), &mut buf).unwrap_err();
assert_eq!(read, Errno::EAGAIN);
}

29
third_party/rust/nix/test/sys/test_uio.rs поставляемый
Просмотреть файл

@ -4,7 +4,7 @@ use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::fs::OpenOptions;
use std::io::IoSlice;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{FromRawFd, OwnedFd};
use std::{cmp, iter};
#[cfg(not(target_os = "redox"))]
@ -40,12 +40,16 @@ fn test_writev() {
iovecs.push(IoSlice::new(b));
consumed += slice_len;
}
let pipe_res = pipe();
let (reader, writer) = pipe_res.expect("Couldn't create pipe");
let (reader, writer) = pipe().expect("Couldn't create pipe");
// FileDesc will close its filedesc (reader).
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
// Temporary workaround to cope with the existing RawFd pipe(2), should be
// removed when pipe(2) becomes I/O-safe.
let writer = unsafe { OwnedFd::from_raw_fd(writer) };
// Blocking io, should write all data.
let write_res = writev(writer, &iovecs);
let write_res = writev(&writer, &iovecs);
let written = write_res.expect("couldn't write");
// Check whether we written all data
assert_eq!(to_write.len(), written);
@ -55,7 +59,6 @@ fn test_writev() {
assert_eq!(read, written);
// Check equality of written and read data
assert_eq!(&to_write, &read_buf);
close(writer).expect("closed writer");
close(reader).expect("closed reader");
}
@ -88,7 +91,12 @@ fn test_readv() {
let (reader, writer) = pipe().expect("couldn't create pipe");
// Blocking io, should write all data.
write(writer, &to_write).expect("write failed");
let read = readv(reader, &mut iovecs[..]).expect("read failed");
// Temporary workaround to cope with the existing RawFd pipe(2), should be
// removed when pipe(2) becomes I/O-safe.
let reader = unsafe { OwnedFd::from_raw_fd(reader) };
let read = readv(&reader, &mut iovecs[..]).expect("read failed");
// Check whether we've read all data
assert_eq!(to_write.len(), read);
// Cccumulate data from iovecs
@ -100,7 +108,6 @@ fn test_readv() {
assert_eq!(read_buf.len(), to_write.len());
// Check equality of written and read data
assert_eq!(&read_buf, &to_write);
close(reader).expect("couldn't close reader");
close(writer).expect("couldn't close writer");
}
@ -111,7 +118,7 @@ fn test_pwrite() {
let mut file = tempfile().unwrap();
let buf = [1u8; 8];
assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
assert_eq!(Ok(8), pwrite(&file, &buf, 8));
let mut file_content = Vec::new();
file.read_to_end(&mut file_content).unwrap();
let mut expected = vec![0u8; 8];
@ -137,7 +144,7 @@ fn test_pread() {
file.write_all(&file_content).unwrap();
let mut buf = [0u8; 16];
assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
assert_eq!(Ok(16), pread(&file, &mut buf, 16));
let expected: Vec<_> = (16..32).collect();
assert_eq!(&buf[..], &expected[..]);
}
@ -168,7 +175,7 @@ fn test_pwritev() {
.open(path)
.unwrap();
let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
let written = pwritev(&file, &iovecs, 100).ok().unwrap();
assert_eq!(written, to_write.len());
// Read the data back and make sure it matches
@ -206,7 +213,7 @@ fn test_preadv() {
.iter_mut()
.map(|buf| IoSliceMut::new(&mut buf[..]))
.collect();
assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100));
assert_eq!(Ok(100), preadv(&file, &mut iovecs, 100));
}
let all = buffers.concat();

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

@ -2,8 +2,6 @@
extern crate cfg_if;
#[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)]
extern crate nix;
#[macro_use]
extern crate lazy_static;
mod common;
mod sys;
@ -66,37 +64,35 @@ mod test_unistd;
use nix::unistd::{chdir, getcwd, read};
use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsFd, AsRawFd};
use std::path::PathBuf;
/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
fn read_exact(f: RawFd, buf: &mut [u8]) {
/// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s
fn read_exact<Fd: AsFd>(f: Fd, buf: &mut [u8]) {
let mut len = 0;
while len < buf.len() {
// get_mut would be better than split_at_mut, but it requires nightly
let (_, remaining) = buf.split_at_mut(len);
len += read(f, remaining).unwrap();
len += read(f.as_fd().as_raw_fd(), remaining).unwrap();
}
}
lazy_static! {
/// Any test that changes the process's current working directory must grab
/// the RwLock exclusively. Any process that cares about the current
/// working directory must grab it shared.
pub static ref CWD_LOCK: RwLock<()> = RwLock::new(());
/// Any test that creates child processes must grab this mutex, regardless
/// of what it does with those children.
pub static ref FORK_MTX: Mutex<()> = Mutex::new(());
/// Any test that changes the process's supplementary groups must grab this
/// mutex
pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(());
/// Any tests that loads or unloads kernel modules must grab this mutex
pub static ref KMOD_MTX: Mutex<()> = Mutex::new(());
/// Any test that calls ptsname(3) must grab this mutex.
pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(());
/// Any test that alters signal handling must grab this mutex.
pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(());
}
/// Any test that creates child processes must grab this mutex, regardless
/// of what it does with those children.
pub static FORK_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(());
/// Any test that changes the process's current working directory must grab
/// the RwLock exclusively. Any process that cares about the current
/// working directory must grab it shared.
pub static CWD_LOCK: RwLock<()> = RwLock::new(());
/// Any test that changes the process's supplementary groups must grab this
/// mutex
pub static GROUPS_MTX: Mutex<()> = Mutex::new(());
/// Any tests that loads or unloads kernel modules must grab this mutex
pub static KMOD_MTX: Mutex<()> = Mutex::new(());
/// Any test that calls ptsname(3) must grab this mutex.
pub static PTSNAME_MTX: Mutex<()> = Mutex::new(());
/// Any test that alters signal handling must grab this mutex.
pub static SIGNAL_MTX: Mutex<()> = Mutex::new(());
/// RAII object that restores a test's original directory on drop
struct DirRestore<'a> {

95
third_party/rust/nix/test/test_fcntl.rs поставляемый
Просмотреть файл

@ -26,7 +26,7 @@ use std::io::prelude::*;
#[cfg(not(target_os = "redox"))]
use std::os::unix::fs;
#[cfg(not(target_os = "redox"))]
use tempfile::{self, NamedTempFile};
use tempfile::NamedTempFile;
#[test]
#[cfg(not(target_os = "redox"))]
@ -227,6 +227,51 @@ fn test_readlink() {
);
}
/// This test creates a temporary file containing the contents
/// 'foobarbaz' and uses the `copy_file_range` call to transfer
/// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
/// resulting file is read and should contain the contents `bar`.
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[cfg(any(
target_os = "linux",
// Not available until FreeBSD 13.0
all(target_os = "freebsd", fbsd14),
target_os = "android"
))]
#[test]
// QEMU does not support copy_file_range. Skip under qemu
#[cfg_attr(qemu, ignore)]
fn test_copy_file_range() {
use nix::fcntl::copy_file_range;
use std::os::unix::io::AsFd;
const CONTENTS: &[u8] = b"foobarbaz";
let mut tmp1 = tempfile::tempfile().unwrap();
let mut tmp2 = tempfile::tempfile().unwrap();
tmp1.write_all(CONTENTS).unwrap();
tmp1.flush().unwrap();
let mut from_offset: i64 = 3;
copy_file_range(
tmp1.as_fd(),
Some(&mut from_offset),
tmp2.as_fd(),
None,
3,
)
.unwrap();
let mut res: String = String::new();
tmp2.rewind().unwrap();
tmp2.read_to_string(&mut res).unwrap();
assert_eq!(res, String::from("bar"));
assert_eq!(from_offset, 6);
}
#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
use libc::loff_t;
@ -238,47 +283,11 @@ mod linux_android {
use nix::unistd::{close, pipe, read, write};
use tempfile::tempfile;
#[cfg(any(target_os = "linux"))]
#[cfg(target_os = "linux")]
use tempfile::NamedTempFile;
use crate::*;
/// This test creates a temporary file containing the contents
/// 'foobarbaz' and uses the `copy_file_range` call to transfer
/// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
/// resulting file is read and should contain the contents `bar`.
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[test]
// QEMU does not support copy_file_range. Skip under qemu
#[cfg_attr(qemu, ignore)]
fn test_copy_file_range() {
const CONTENTS: &[u8] = b"foobarbaz";
let mut tmp1 = tempfile().unwrap();
let mut tmp2 = tempfile().unwrap();
tmp1.write_all(CONTENTS).unwrap();
tmp1.flush().unwrap();
let mut from_offset: i64 = 3;
copy_file_range(
tmp1.as_raw_fd(),
Some(&mut from_offset),
tmp2.as_raw_fd(),
None,
3,
)
.unwrap();
let mut res: String = String::new();
tmp2.rewind().unwrap();
tmp2.read_to_string(&mut res).unwrap();
assert_eq!(res, String::from("bar"));
assert_eq!(from_offset, 6);
}
#[test]
fn test_splice() {
const CONTENTS: &[u8] = b"abcdef123456";
@ -340,7 +349,7 @@ mod linux_android {
let buf1 = b"abcdef";
let buf2 = b"defghi";
let iovecs = vec![IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])];
let iovecs = [IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])];
let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
@ -355,7 +364,7 @@ mod linux_android {
close(wr).unwrap();
}
#[cfg(any(target_os = "linux"))]
#[cfg(target_os = "linux")]
#[test]
fn test_fallocate() {
let tmp = NamedTempFile::new().unwrap();
@ -383,7 +392,7 @@ mod linux_android {
let tmp = NamedTempFile::new().unwrap();
let fd = tmp.as_raw_fd();
let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
let statfs = nix::sys::statfs::fstatfs(tmp.as_file()).unwrap();
if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
// OverlayFS is a union file system. It returns one inode value in
// stat(2), but a different one shows up in /proc/locks. So we must
@ -421,7 +430,7 @@ mod linux_android {
let tmp = NamedTempFile::new().unwrap();
let fd = tmp.as_raw_fd();
let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
let statfs = nix::sys::statfs::fstatfs(tmp.as_file()).unwrap();
if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
// OverlayFS is a union file system. It returns one inode value in
// stat(2), but a different one shows up in /proc/locks. So we must
@ -559,7 +568,7 @@ mod test_posix_fallocate {
let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
match err {
Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
errno => panic!("unexpected errno {}", errno,),
errno => panic!("unexpected errno {errno}",),
}
}
}

42
third_party/rust/nix/test/test_mount.rs поставляемый
Просмотреть файл

@ -38,7 +38,7 @@ exit 23";
MsFlags::empty(),
NONE,
)
.unwrap_or_else(|e| panic!("mount failed: {}", e));
.unwrap_or_else(|e| panic!("mount failed: {e}"));
let test_path = tempdir.path().join("test");
@ -67,17 +67,17 @@ exit 23";
.unwrap();
process::exit(0);
} else {
panic!("open failed: {}", e);
panic!("open failed: {e}");
}
})
.and_then(|mut f| f.write(SCRIPT_CONTENTS))
.unwrap_or_else(|e| panic!("write failed: {}", e));
.unwrap_or_else(|e| panic!("write failed: {e}"));
// Verify read.
let mut buf = Vec::new();
File::open(&test_path)
.and_then(|mut f| f.read_to_end(&mut buf))
.unwrap_or_else(|e| panic!("read failed: {}", e));
.unwrap_or_else(|e| panic!("read failed: {e}"));
assert_eq!(buf, SCRIPT_CONTENTS);
// Verify execute.
@ -85,13 +85,12 @@ exit 23";
EXPECTED_STATUS,
Command::new(&test_path)
.status()
.unwrap_or_else(|e| panic!("exec failed: {}", e))
.unwrap_or_else(|e| panic!("exec failed: {e}"))
.code()
.unwrap_or_else(|| panic!("child killed by signal"))
);
umount(tempdir.path())
.unwrap_or_else(|e| panic!("umount failed: {}", e));
umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
}
pub fn test_mount_rdonly_disallows_write() {
@ -104,7 +103,7 @@ exit 23";
MsFlags::MS_RDONLY,
NONE,
)
.unwrap_or_else(|e| panic!("mount failed: {}", e));
.unwrap_or_else(|e| panic!("mount failed: {e}"));
// EROFS: Read-only file system
assert_eq!(
@ -115,8 +114,7 @@ exit 23";
.unwrap()
);
umount(tempdir.path())
.unwrap_or_else(|e| panic!("umount failed: {}", e));
umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
}
pub fn test_mount_noexec_disallows_exec() {
@ -129,7 +127,7 @@ exit 23";
MsFlags::MS_NOEXEC,
NONE,
)
.unwrap_or_else(|e| panic!("mount failed: {}", e));
.unwrap_or_else(|e| panic!("mount failed: {e}"));
let test_path = tempdir.path().join("test");
@ -139,13 +137,13 @@ exit 23";
.mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
.open(&test_path)
.and_then(|mut f| f.write(SCRIPT_CONTENTS))
.unwrap_or_else(|e| panic!("write failed: {}", e));
.unwrap_or_else(|e| panic!("write failed: {e}"));
// Verify that we cannot execute despite a+x permissions being set.
let mode = stat::Mode::from_bits_truncate(
fs::metadata(&test_path)
.map(|md| md.permissions().mode())
.unwrap_or_else(|e| panic!("metadata failed: {}", e)),
.unwrap_or_else(|e| panic!("metadata failed: {e}")),
);
assert!(
@ -164,8 +162,7 @@ exit 23";
.unwrap()
);
umount(tempdir.path())
.unwrap_or_else(|e| panic!("umount failed: {}", e));
umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
}
pub fn test_mount_bind() {
@ -182,7 +179,7 @@ exit 23";
MsFlags::MS_BIND,
NONE,
)
.unwrap_or_else(|e| panic!("mount failed: {}", e));
.unwrap_or_else(|e| panic!("mount failed: {e}"));
fs::OpenOptions::new()
.create(true)
@ -190,10 +187,10 @@ exit 23";
.mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
.open(mount_point.path().join(file_name))
.and_then(|mut f| f.write(SCRIPT_CONTENTS))
.unwrap_or_else(|e| panic!("write failed: {}", e));
.unwrap_or_else(|e| panic!("write failed: {e}"));
umount(mount_point.path())
.unwrap_or_else(|e| panic!("umount failed: {}", e));
.unwrap_or_else(|e| panic!("umount failed: {e}"));
}
// Verify the file written in the mount shows up in source directory, even
@ -202,7 +199,7 @@ exit 23";
let mut buf = Vec::new();
File::open(tempdir.path().join(file_name))
.and_then(|mut f| f.read_to_end(&mut buf))
.unwrap_or_else(|e| panic!("read failed: {}", e));
.unwrap_or_else(|e| panic!("read failed: {e}"));
assert_eq!(buf, SCRIPT_CONTENTS);
}
@ -214,8 +211,7 @@ exit 23";
let stderr = io::stderr();
let mut handle = stderr.lock();
writeln!(handle,
"unshare failed: {}. Are unprivileged user namespaces available?",
e).unwrap();
"unshare failed: {e}. Are unprivileged user namespaces available?").unwrap();
writeln!(handle, "mount is not being tested").unwrap();
// Exit with success because not all systems support unprivileged user namespaces, and
// that's not what we're testing for.
@ -226,8 +222,8 @@ exit 23";
fs::OpenOptions::new()
.write(true)
.open("/proc/self/uid_map")
.and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes()))
.unwrap_or_else(|e| panic!("could not write uid map: {}", e));
.and_then(|mut f| f.write(format!("1000 {uid} 1\n").as_bytes()))
.unwrap_or_else(|e| panic!("could not write uid map: {e}"));
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше