Bug 1977514 - Updated nix to version 0.30.1 a=RyanVM
Original Revision: https://phabricator.services.mozilla.com/D258707 Differential Revision: https://phabricator.services.mozilla.com/D262344
This commit is contained in:
committed by
rvandermeulen@mozilla.com
parent
714b7245e2
commit
9e514a4382
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -1154,7 +1154,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"crash_helper_common",
|
||||
"minidump-writer",
|
||||
"nix 0.29.0",
|
||||
"nix 0.30.1",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"rust_minidump_writer_linux",
|
||||
@@ -1166,7 +1166,7 @@ name = "crash_helper_common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"minidump-writer",
|
||||
"nix 0.29.0",
|
||||
"nix 0.30.1",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"thiserror 2.0.9",
|
||||
@@ -1190,7 +1190,7 @@ dependencies = [
|
||||
"mozannotation_server",
|
||||
"mozbuild",
|
||||
"mozilla-central-workspace-hack",
|
||||
"nix 0.29.0",
|
||||
"nix 0.30.1",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
@@ -4831,14 +4831,21 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
name = "nix"
|
||||
version = "0.26.99"
|
||||
dependencies = [
|
||||
"nix 0.29.0",
|
||||
"nix 0.30.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
dependencies = [
|
||||
"nix 0.30.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"cfg-if",
|
||||
|
||||
@@ -166,8 +166,11 @@ bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
|
||||
# and for bug 1945218
|
||||
bindgen = { path = "third_party/rust/bindgen" }
|
||||
|
||||
# Patch nix 0.26 to 0.29
|
||||
nix = { path = "build/rust/nix" }
|
||||
# Patch nix 0.26 to 0.30+
|
||||
nix_0_26 = { package = "nix", path = "build/rust/nix" }
|
||||
|
||||
# Patch nix 0.29 to 0.30+
|
||||
nix_0_30 = { package = "nix", path = "build/rust/nix-0.29" }
|
||||
|
||||
# Patch derive_more 0.99 to 1.0.0-beta
|
||||
derive_more = { path = "build/rust/derive_more" }
|
||||
|
||||
37
build/rust/nix-0.29/Cargo.toml
Normal file
37
build/rust/nix-0.29/Cargo.toml
Normal file
@@ -0,0 +1,37 @@
|
||||
[package]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.nix]
|
||||
version = "0.30"
|
||||
defaultfeatures = false
|
||||
|
||||
[features]
|
||||
acct = ["nix/acct"]
|
||||
aio = ["nix/aio"]
|
||||
default = ["nix/default"]
|
||||
dir = ["nix/dir"]
|
||||
env = ["nix/env"]
|
||||
event = ["nix/event"]
|
||||
feature = ["nix/feature"]
|
||||
fs = ["nix/fs"]
|
||||
hostname = ["nix/hostname"]
|
||||
inotify = ["nix/inotify"]
|
||||
ioctl = ["nix/ioctl"]
|
||||
kmod = ["nix/kmod"]
|
||||
mman = ["nix/mman"]
|
||||
mount = ["nix/mount"]
|
||||
mqueue = ["nix/mqueue"]
|
||||
net = ["nix/net"]
|
||||
poll = ["nix/poll"]
|
||||
process = ["nix/process"]
|
||||
ptrace = ["nix/ptrace"]
|
||||
signal = ["nix/signal"]
|
||||
socket = ["nix/socket"]
|
||||
uio = ["nix/uio"]
|
||||
user = ["nix/user"]
|
||||
5
build/rust/nix-0.29/lib.rs
Normal file
5
build/rust/nix-0.29/lib.rs
Normal file
@@ -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 nix::*;
|
||||
@@ -8,8 +8,8 @@ license = "MPL-2.0"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.nix]
|
||||
version = "0.29"
|
||||
default-features = false
|
||||
version = "0.30"
|
||||
defaultfeatures = false
|
||||
|
||||
[features]
|
||||
acct = ["nix/acct"]
|
||||
@@ -28,3 +28,10 @@ mman = ["nix/mman"]
|
||||
mount = ["nix/mount"]
|
||||
mqueue = ["nix/mqueue"]
|
||||
net = ["nix/net"]
|
||||
poll = ["nix/poll"]
|
||||
process = ["nix/process"]
|
||||
ptrace = ["nix/ptrace"]
|
||||
signal = ["nix/signal"]
|
||||
socket = ["nix/socket"]
|
||||
uio = ["nix/uio"]
|
||||
user = ["nix/user"]
|
||||
|
||||
@@ -3859,6 +3859,12 @@ who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.28.0 -> 0.29.0"
|
||||
|
||||
[[audits.nix]]
|
||||
who = "Gabriele Svelto <gsvelto@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.29.0 -> 0.30.1"
|
||||
notes = "Some new wrappers, support for minor platforms and lots of work around type safety that reduces the unsafe surafce."
|
||||
|
||||
[[audits.nom]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
2
third_party/rust/nix/.cargo-checksum.json
vendored
2
third_party/rust/nix/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
155
third_party/rust/nix/CHANGELOG.md
vendored
155
third_party/rust/nix/CHANGELOG.md
vendored
@@ -3,6 +3,161 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
# Change Log
|
||||
|
||||
## [0.30.1] - 2025-05-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- doc.rs build
|
||||
([#2634](https://github.com/nix-rust/nix/pull/2634))
|
||||
|
||||
|
||||
## [0.30.0] - 2025-04-29
|
||||
|
||||
|
||||
### Added
|
||||
|
||||
- Add socket option `IPV6_PKTINFO` for BSDs/Linux/Android, also
|
||||
`IPV6_RECVPKTINFO` for DragonFlyBSD
|
||||
([#2113](https://github.com/nix-rust/nix/pull/2113))
|
||||
- Add `fcntl`'s `F_PREALLOCATE` constant for Apple targets.
|
||||
([#2393](https://github.com/nix-rust/nix/pull/2393))
|
||||
- Improve support for extracting the TTL / Hop Limit from incoming packets
|
||||
and support for DSCP (ToS / Traffic Class).
|
||||
([#2425](https://github.com/nix-rust/nix/pull/2425))
|
||||
- Add socket option IP_TOS (nix::sys::socket::sockopt::IpTos) IPV6_TCLASS
|
||||
(nix::sys::socket::sockopt::Ipv6TClass) on Android/FreeBSD
|
||||
([#2464](https://github.com/nix-rust/nix/pull/2464))
|
||||
- Add `SeekData` and `SeekHole` to `Whence` for hurd and apple targets
|
||||
([#2473](https://github.com/nix-rust/nix/pull/2473))
|
||||
- Add `From` trait implementation between `SocketAddr` and `Sockaddr`,
|
||||
`Sockaddr6` ([#2474](https://github.com/nix-rust/nix/pull/2474))
|
||||
- Added wrappers for `posix_spawn` API
|
||||
([#2475](https://github.com/nix-rust/nix/pull/2475))
|
||||
- Add the support for Emscripten.
|
||||
([#2477](https://github.com/nix-rust/nix/pull/2477))
|
||||
- Add fcntl constant `F_RDADVISE` for Apple target
|
||||
([#2480](https://github.com/nix-rust/nix/pull/2480))
|
||||
- Add fcntl constant `F_RDAHEAD` for Apple target
|
||||
([#2482](https://github.com/nix-rust/nix/pull/2482))
|
||||
- Add `F_LOG2PHYS` and `F_LOG2PHYS_EXT` for Apple target
|
||||
([#2483](https://github.com/nix-rust/nix/pull/2483))
|
||||
- `MAP_SHARED_VALIDATE` was added for all linux targets. & `MAP_SYNC` was added
|
||||
for linux with the exclusion of mips architecures, and uclibc
|
||||
([#2499](https://github.com/nix-rust/nix/pull/2499))
|
||||
- Add `getregs()`/`getregset()`/`setregset()` for Linux/musl/aarch64
|
||||
([#2502](https://github.com/nix-rust/nix/pull/2502))
|
||||
- Add FcntlArgs `F_TRANSFEREXTENTS` constant for Apple targets
|
||||
([#2504](https://github.com/nix-rust/nix/pull/2504))
|
||||
- Add `MapFlags::MAP_STACK` in `sys::man` for netbsd
|
||||
([#2526](https://github.com/nix-rust/nix/pull/2526))
|
||||
- Add support for `libc::LOCAL_PEERTOKEN` in `getsockopt`.
|
||||
([#2529](https://github.com/nix-rust/nix/pull/2529))
|
||||
- Add support for `syslog`, `openlog`, `closelog` on all `unix`.
|
||||
([#2537](https://github.com/nix-rust/nix/pull/2537))
|
||||
- Add the `TCP_FUNCTION_BLK` sockopt, on FreeBSD.
|
||||
([#2539](https://github.com/nix-rust/nix/pull/2539))
|
||||
- Implements `Into<OwnedFd>` for `PtyMaster/Fanotify/Inotify/SignalFd/TimerFd`
|
||||
([#2548](https://github.com/nix-rust/nix/pull/2548))
|
||||
- Add `MremapFlags::MREMAP_DONTUNMAP` to `sys::mman::mremap` for linux target.
|
||||
([#2555](https://github.com/nix-rust/nix/pull/2555))
|
||||
- Added `sockopt_impl!` to the public API. It's now possible for users to
|
||||
define
|
||||
their own sockopts without needing to make a PR to Nix.
|
||||
([#2556](https://github.com/nix-rust/nix/pull/2556))
|
||||
- Add the `TCP_FUNCTION_ALIAS` sockopt, on FreeBSD.
|
||||
([#2558](https://github.com/nix-rust/nix/pull/2558))
|
||||
- Add `sys::mman::MmapAdvise` `MADV_PAGEOUT`, `MADV_COLD`, `MADV_WIPEONFORK`,
|
||||
`MADV_KEEPONFORK` for Linux and Android targets
|
||||
([#2559](https://github.com/nix-rust/nix/pull/2559))
|
||||
- Add socket protocol `Sctp`, as well as `MSG_NOTIFICATION` for non-Android
|
||||
Linux targets. ([#2562](https://github.com/nix-rust/nix/pull/2562))
|
||||
- Added `from_owned_fd` constructor to `EventFd`
|
||||
([#2563](https://github.com/nix-rust/nix/pull/2563))
|
||||
- Add `sys::mman::MmapAdvise` `MADV_POPULATE_READ`, `MADV_POPULATE_WRITE` for
|
||||
Linux and Android targets
|
||||
([#2565](https://github.com/nix-rust/nix/pull/2565))
|
||||
- Added `from_owned_fd` constructor to
|
||||
`PtyMaster/Fanotify/Inotify/SignalFd/TimerFd`
|
||||
([#2566](https://github.com/nix-rust/nix/pull/2566))
|
||||
- Added `FcntlArg::F_READAHEAD` for FreeBSD target
|
||||
([#2569](https://github.com/nix-rust/nix/pull/2569))
|
||||
- Added `sockopt::LingerSec` for Apple targets
|
||||
([#2572](https://github.com/nix-rust/nix/pull/2572))
|
||||
- Added `sockopt::EsclBind` for solarish targets
|
||||
([#2573](https://github.com/nix-rust/nix/pull/2573))
|
||||
- Exposed the ```std::os::fd::AsRawFd``` trait method for
|
||||
```nix::sys::fanotify::Fanotify``` struct
|
||||
([#2575](https://github.com/nix-rust/nix/pull/2575))
|
||||
- Add support for syslog's `setlogmask` on all `unix`.
|
||||
([#2579](https://github.com/nix-rust/nix/pull/2579))
|
||||
- Added Fuchsia support for `ioctl`.
|
||||
([#2580](https://github.com/nix-rust/nix/pull/2580))
|
||||
- Add ```sys::socket::SockProtocol::EthIp```,
|
||||
```sys::socket::SockProtocol::EthIpv6```,
|
||||
```sys::socket::SockProtocol::EthLoop```
|
||||
([#2581](https://github.com/nix-rust/nix/pull/2581))
|
||||
- Add OpenHarmony target into CI and Update documents.
|
||||
([#2599](https://github.com/nix-rust/nix/pull/2599))
|
||||
- Added the TcpMaxSeg `setsockopt` option for apple targets
|
||||
([#2603](https://github.com/nix-rust/nix/pull/2603))
|
||||
- Add `FilAttach` and `FilDetach` to socket::sockopt for Illumos
|
||||
([#2611](https://github.com/nix-rust/nix/pull/2611))
|
||||
- Add `PeerPidfd` (`SO_PEERPIDFD`) to `socket::sockopt` for Linux
|
||||
([#2620](https://github.com/nix-rust/nix/pull/2620))
|
||||
- Added `socket::sockopt::AttachReusePortCbpf` for Linux
|
||||
([#2621](https://github.com/nix-rust/nix/pull/2621))
|
||||
- Add `ptrace::syscall_info` for linux/glibc
|
||||
([#2627](https://github.com/nix-rust/nix/pull/2627))
|
||||
|
||||
### Changed
|
||||
|
||||
- Module sys/signal now adopts I/O safety
|
||||
([#1936](https://github.com/nix-rust/nix/pull/1936))
|
||||
- Change the type of the `name` argument of `memfd_create()` from `&CStr` to
|
||||
`<P: NixPath>(name: &P)` ([#2431](https://github.com/nix-rust/nix/pull/2431))
|
||||
- Public interfaces in `fcntl.rs` and `dir.rs` now use I/O-safe types.
|
||||
([#2434](https://github.com/nix-rust/nix/pull/2434))
|
||||
- Module `sys/stat` now adopts I/O safety.
|
||||
([#2439](https://github.com/nix-rust/nix/pull/2439))
|
||||
- Module unistd now adopts I/O safety.
|
||||
([#2440](https://github.com/nix-rust/nix/pull/2440))
|
||||
- Module sys/fanotify now adopts I/O safety
|
||||
([#2443](https://github.com/nix-rust/nix/pull/2443))
|
||||
- Socket option `IpTos` has been renamed to `Ipv4Tos`, the old symbol is
|
||||
deprecated since 0.30.0 ([#2465](https://github.com/nix-rust/nix/pull/2465))
|
||||
- Rename Flags `EventFlag` to `EvFlags`, and `MemFdCreateFlag` to `MFdFlags`
|
||||
([#2476](https://github.com/nix-rust/nix/pull/2476))
|
||||
- Made `nix::sys::socket::UnknownCmsg` public and more readable
|
||||
([#2520](https://github.com/nix-rust/nix/pull/2520))
|
||||
- recvmsg: take slice for cmsg_buffer instead of Vec
|
||||
([#2524](https://github.com/nix-rust/nix/pull/2524))
|
||||
- linkat: allow distinct types for path arguments
|
||||
([#2582](https://github.com/nix-rust/nix/pull/2582))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Disable unsupported signals on sparc-linux
|
||||
([#2454](https://github.com/nix-rust/nix/pull/2454))
|
||||
- Fix cmsg_len() return type on OpenHarmony
|
||||
([#2456](https://github.com/nix-rust/nix/pull/2456))
|
||||
- The `ns` argument of `sys::prctl::set_timerslack()` should be of type
|
||||
`c_ulong` ([#2505](https://github.com/nix-rust/nix/pull/2505))
|
||||
- Properly exclude NUL characters from `OSString`s returned by `getsockopt`.
|
||||
([#2557](https://github.com/nix-rust/nix/pull/2557))
|
||||
- Fixes the build on OpenHarmony
|
||||
([#2587](https://github.com/nix-rust/nix/pull/2587))
|
||||
|
||||
### Removed
|
||||
|
||||
- Type `SigevNotify` is no longer `PartialEq`, `Eq` and `Hash` due to the use
|
||||
of `BorrowedFd` ([#1936](https://github.com/nix-rust/nix/pull/1936))
|
||||
- `EventFd::defuse()` is removed because it does nothing, `EventFd::arm()` is
|
||||
also removed for symmetry reasons.
|
||||
([#2452](https://github.com/nix-rust/nix/pull/2452))
|
||||
- Removed the `Copy` trait from `PollFd`
|
||||
([#2631](https://github.com/nix-rust/nix/pull/2631))
|
||||
|
||||
|
||||
## [0.29.0] - 2024-05-24
|
||||
|
||||
|
||||
|
||||
48
third_party/rust/nix/Cargo.lock
generated
vendored
48
third_party/rust/nix/Cargo.lock
generated
vendored
@@ -72,20 +72,21 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
@@ -114,7 +115,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
version = "0.30.1"
|
||||
dependencies = [
|
||||
"assert-impl",
|
||||
"bitflags 2.5.0",
|
||||
@@ -185,21 +186,26 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
@@ -207,9 +213,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
@@ -337,9 +343,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
@@ -422,3 +431,12 @@ name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
]
|
||||
|
||||
125
third_party/rust/nix/Cargo.toml
vendored
125
third_party/rust/nix/Cargo.toml
vendored
@@ -13,8 +13,9 @@
|
||||
edition = "2021"
|
||||
rust-version = "1.69"
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
version = "0.30.1"
|
||||
authors = ["The nix-rust Project Developers"]
|
||||
build = "build.rs"
|
||||
include = [
|
||||
"build.rs",
|
||||
"src/**/*",
|
||||
@@ -23,6 +24,11 @@ include = [
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
]
|
||||
autolib = false
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "Rust friendly bindings to *nix APIs"
|
||||
readme = "README.md"
|
||||
categories = ["os::unix-apis"]
|
||||
@@ -44,70 +50,18 @@ targets = [
|
||||
"x86_64-unknown-openbsd",
|
||||
"x86_64-unknown-netbsd",
|
||||
"x86_64-unknown-dragonfly",
|
||||
"x86_64-fuchsia",
|
||||
"x86_64-unknown-fuchsia",
|
||||
"x86_64-unknown-redox",
|
||||
"x86_64-unknown-illumos",
|
||||
]
|
||||
|
||||
[[test]]
|
||||
name = "test"
|
||||
path = "test/test.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-aio-drop"
|
||||
path = "test/sys/test_aio_drop.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-clearenv"
|
||||
path = "test/test_clearenv.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-prctl"
|
||||
path = "test/sys/test_prctl.rs"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "2.3.1"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2.155"
|
||||
features = ["extra_traits"]
|
||||
|
||||
[dependencies.memoffset]
|
||||
version = "0.9"
|
||||
optional = true
|
||||
|
||||
[dependencies.pin-utils]
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.assert-impl]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.parking_lot]
|
||||
version = "0.12"
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[dev-dependencies.semver]
|
||||
version = "1.0.7"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3.7.1"
|
||||
|
||||
[build-dependencies.cfg_aliases]
|
||||
version = "0.2"
|
||||
|
||||
[features]
|
||||
acct = []
|
||||
aio = ["pin-utils"]
|
||||
default = []
|
||||
dir = ["fs"]
|
||||
env = []
|
||||
event = []
|
||||
event = ["poll"]
|
||||
fanotify = []
|
||||
feature = []
|
||||
fs = []
|
||||
@@ -130,6 +84,7 @@ resource = []
|
||||
sched = ["process"]
|
||||
signal = ["process"]
|
||||
socket = ["memoffset"]
|
||||
syslog = []
|
||||
term = []
|
||||
time = []
|
||||
ucontext = ["signal"]
|
||||
@@ -140,8 +95,64 @@ zerocopy = [
|
||||
"uio",
|
||||
]
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
|
||||
[lib]
|
||||
name = "nix"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test"
|
||||
path = "test/test.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-aio-drop"
|
||||
path = "test/sys/test_aio_drop.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-clearenv"
|
||||
path = "test/test_clearenv.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test-prctl"
|
||||
path = "test/sys/test_prctl.rs"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "2.3.3"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2.171"
|
||||
features = ["extra_traits"]
|
||||
|
||||
[dependencies.memoffset]
|
||||
version = "0.9"
|
||||
optional = true
|
||||
|
||||
[dependencies.pin-utils]
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.assert-impl]
|
||||
version = "0.1"
|
||||
|
||||
[dev-dependencies.parking_lot]
|
||||
version = "0.12"
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.9"
|
||||
|
||||
[dev-dependencies.semver]
|
||||
version = "1.0.7"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3.7.1"
|
||||
|
||||
[build-dependencies.cfg_aliases]
|
||||
version = "0.2.1"
|
||||
|
||||
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dev-dependencies.caps]
|
||||
version = "0.5.3"
|
||||
|
||||
[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
|
||||
[target.'cfg(target_os = "freebsd")'.dev-dependencies.sysctl]
|
||||
version = "0.4"
|
||||
|
||||
14
third_party/rust/nix/README.md
vendored
14
third_party/rust/nix/README.md
vendored
@@ -2,9 +2,9 @@
|
||||
|
||||
[](https://cirrus-ci.com/github/nix-rust/nix)
|
||||
[](https://crates.io/crates/nix)
|
||||
[](https://github.com/nix-rust/nix/issues/2132)
|
||||
|
||||
[Documentation (Releases)](https://docs.rs/nix/)
|
||||
[](https://docs.rs/nix)
|
||||

|
||||
[](https://www.rust-lang.org)
|
||||
|
||||
Nix seeks to provide friendly bindings to various *nix platform APIs (Linux, Darwin,
|
||||
...). The goal is to not provide a 100% unified interface, but to unify
|
||||
@@ -81,19 +81,23 @@ The following targets are supported by `nix`:
|
||||
<ul>
|
||||
<li>aarch64-apple-ios</li>
|
||||
<li>aarch64-linux-android</li>
|
||||
<li>aarch64-unknown-linux-ohos</li>
|
||||
<li>arm-linux-androideabi</li>
|
||||
<li>arm-unknown-linux-musleabi</li>
|
||||
<li>armv7-linux-androideabi</li>
|
||||
<li>armv7-unknown-linux-ohos</li>
|
||||
<li>i686-linux-android</li>
|
||||
<li>loongarch64-unknown-linux-gnu</li>
|
||||
<li>s390x-unknown-linux-gnu</li>
|
||||
<li>x86_64-linux-android</li>
|
||||
<li>x86_64-unknown-illumos</li>
|
||||
<li>x86_64-unknown-linux-ohos</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-fuchsia</li>
|
||||
<li>x86_64-unknown-dragonfly</li>
|
||||
<li>x86_64-unknown-haiku</li>
|
||||
<li>x86_64-unknown-linux-gnux32</li>
|
||||
@@ -114,7 +118,7 @@ changed in the future without bumping the major or minor version.
|
||||
Contributions are very welcome. Please See [CONTRIBUTING](CONTRIBUTING.md) for
|
||||
additional details.
|
||||
|
||||
Feel free to join us in [the nix-rust/nix](https://gitter.im/nix-rust/nix) channel on Gitter to
|
||||
Feel free to join us in [the nix-rust/nix](https://discord.com/invite/rkBeJUsmyd) channel on Discord to
|
||||
discuss `nix` development.
|
||||
|
||||
## License
|
||||
|
||||
11
third_party/rust/nix/build.rs
vendored
11
third_party/rust/nix/build.rs
vendored
@@ -27,14 +27,9 @@ fn main() {
|
||||
solarish: { any(illumos, solaris) },
|
||||
}
|
||||
|
||||
// Below are Nix's custom cfg values that we need to let the compiler know
|
||||
println!("cargo:rustc-check-cfg=cfg(apple_targets)");
|
||||
println!("cargo:rustc-check-cfg=cfg(bsd)");
|
||||
println!("cargo:rustc-check-cfg=cfg(bsd_without_apple)");
|
||||
println!("cargo:rustc-check-cfg=cfg(linux_android)");
|
||||
println!("cargo:rustc-check-cfg=cfg(freebsdlike)");
|
||||
println!("cargo:rustc-check-cfg=cfg(netbsdlike)");
|
||||
println!("cargo:rustc-check-cfg=cfg(solarish)");
|
||||
// Below are custom cfg values set during some CI steps.
|
||||
println!("cargo:rustc-check-cfg=cfg(fbsd14)");
|
||||
println!("cargo:rustc-check-cfg=cfg(qemu)");
|
||||
// Cygwin target, added in 1.86
|
||||
println!("cargo:rustc-check-cfg=cfg(target_os, values(\"cygwin\"))");
|
||||
}
|
||||
|
||||
103
third_party/rust/nix/src/dir.rs
vendored
103
third_party/rust/nix/src/dir.rs
vendored
@@ -3,7 +3,7 @@
|
||||
use crate::errno::Errno;
|
||||
use crate::fcntl::{self, OFlag};
|
||||
use crate::sys;
|
||||
use crate::{Error, NixPath, Result};
|
||||
use crate::{NixPath, Result};
|
||||
use cfg_if::cfg_if;
|
||||
use std::ffi;
|
||||
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||
@@ -17,17 +17,38 @@ use libc::{dirent, readdir_r};
|
||||
|
||||
/// An open directory.
|
||||
///
|
||||
/// This is a lower-level interface than `std::fs::ReadDir`. Notable differences:
|
||||
/// * can be opened from a file descriptor (as returned by `openat`, perhaps before knowing
|
||||
/// if the path represents a file or directory).
|
||||
/// * implements `AsRawFd`, so it can be passed to `fstat`, `openat`, etc.
|
||||
/// The file descriptor continues to be owned by the `Dir`, so callers must not keep a `RawFd`
|
||||
/// after the `Dir` is dropped.
|
||||
/// This is a lower-level interface than [`std::fs::ReadDir`]. Notable differences:
|
||||
/// * can be opened from a file descriptor (as returned by [`openat`][openat],
|
||||
/// perhaps before knowing if the path represents a file or directory).
|
||||
/// * implements [`AsFd`][AsFd], so it can be passed to [`fstat`][fstat],
|
||||
/// [`openat`][openat], etc. The file descriptor continues to be owned by the
|
||||
/// `Dir`, so callers must not keep a `RawFd` after the `Dir` is dropped.
|
||||
/// * can be iterated through multiple times without closing and reopening the file
|
||||
/// descriptor. Each iteration rewinds when finished.
|
||||
/// * returns entries for `.` (current directory) and `..` (parent directory).
|
||||
/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
|
||||
/// * returns entries' names as a [`CStr`][cstr] (no allocation or conversion beyond whatever libc
|
||||
/// does).
|
||||
///
|
||||
/// [AsFd]: std::os::fd::AsFd
|
||||
/// [fstat]: crate::sys::stat::fstat
|
||||
/// [openat]: crate::fcntl::openat
|
||||
/// [cstr]: std::ffi::CStr
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Traverse the current directory, and print entries' names:
|
||||
///
|
||||
/// ```
|
||||
/// use nix::dir::Dir;
|
||||
/// use nix::fcntl::OFlag;
|
||||
/// use nix::sys::stat::Mode;
|
||||
///
|
||||
/// let mut cwd = Dir::open(".", OFlag::O_RDONLY | OFlag::O_CLOEXEC, Mode::empty()).unwrap();
|
||||
/// for res_entry in cwd.iter() {
|
||||
/// let entry = res_entry.unwrap();
|
||||
/// println!("File name: {}", entry.file_name().to_string_lossy());
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Dir(ptr::NonNull<libc::DIR>);
|
||||
|
||||
@@ -43,8 +64,8 @@ impl Dir {
|
||||
}
|
||||
|
||||
/// Opens the given path as with `fcntl::openat`.
|
||||
pub fn openat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn openat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
oflag: OFlag,
|
||||
mode: sys::stat::Mode,
|
||||
@@ -54,21 +75,46 @@ impl Dir {
|
||||
}
|
||||
|
||||
/// Converts from a descriptor-based object, closing the descriptor on success or failure.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is only safe if `fd` is an owned file descriptor.
|
||||
#[inline]
|
||||
pub fn from<F: IntoRawFd>(fd: F) -> Result<Self> {
|
||||
Dir::from_fd(fd.into_raw_fd())
|
||||
#[deprecated(
|
||||
since = "0.30.0",
|
||||
note = "Deprecate this since it is not I/O-safe, use from_fd instead."
|
||||
)]
|
||||
pub unsafe fn from<F: IntoRawFd>(fd: F) -> Result<Self> {
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::fd::OwnedFd;
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// This is indeed unsafe is `fd` it not an owned fd.
|
||||
let owned_fd = unsafe { OwnedFd::from_raw_fd(fd.into_raw_fd()) };
|
||||
Dir::from_fd(owned_fd)
|
||||
}
|
||||
|
||||
/// Converts from a file descriptor, closing it on failure.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `ENOTDIR` would be returned if `fd` does not refer to a directory:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::os::fd::OwnedFd;
|
||||
/// use nix::dir::Dir;
|
||||
///
|
||||
/// let temp_file = tempfile::tempfile().unwrap();
|
||||
/// let temp_file_fd: OwnedFd = temp_file.into();
|
||||
/// let never = Dir::from_fd(temp_file_fd).unwrap();
|
||||
/// ```
|
||||
#[doc(alias("fdopendir"))]
|
||||
pub fn from_fd(fd: RawFd) -> Result<Self> {
|
||||
let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(
|
||||
|| {
|
||||
let e = Error::last();
|
||||
unsafe { libc::close(fd) };
|
||||
e
|
||||
},
|
||||
)?;
|
||||
pub fn from_fd(fd: std::os::fd::OwnedFd) -> Result<Self> {
|
||||
// take the ownership as the constructed `Dir` is now the owner
|
||||
let raw_fd = fd.into_raw_fd();
|
||||
let d = ptr::NonNull::new(unsafe { libc::fdopendir(raw_fd) })
|
||||
.ok_or(Errno::last())?;
|
||||
Ok(Dir(d))
|
||||
}
|
||||
|
||||
@@ -86,6 +132,18 @@ impl Dir {
|
||||
// `Dir` is safe to pass from one thread to another, as it's not reference-counted.
|
||||
unsafe impl Send for Dir {}
|
||||
|
||||
impl std::os::fd::AsFd for Dir {
|
||||
fn as_fd(&self) -> std::os::fd::BorrowedFd {
|
||||
let raw_fd = self.as_raw_fd();
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// `raw_fd` should be open and valid for the lifetime of the returned
|
||||
// `BorrowedFd` as it is extracted from `&self`.
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(raw_fd) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Dir {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
unsafe { libc::dirfd(self.0.as_ptr()) }
|
||||
@@ -132,7 +190,7 @@ fn next(dir: &mut Dir) -> Option<Result<Entry>> {
|
||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Iter<'d>(&'d mut Dir);
|
||||
|
||||
impl<'d> Iterator for Iter<'d> {
|
||||
impl Iterator for Iter<'_> {
|
||||
type Item = Result<Entry>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@@ -140,7 +198,7 @@ impl<'d> Iterator for Iter<'d> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Drop for Iter<'d> {
|
||||
impl Drop for Iter<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { libc::rewinddir((self.0).0.as_ptr()) }
|
||||
}
|
||||
@@ -229,6 +287,7 @@ impl Entry {
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "cygwin",
|
||||
solarish,
|
||||
linux_android,
|
||||
apple_targets))] {
|
||||
|
||||
663
third_party/rust/nix/src/errno.rs
vendored
663
third_party/rust/nix/src/errno.rs
vendored
@@ -24,7 +24,7 @@ cfg_if! {
|
||||
unsafe fn errno_location() -> *mut c_int {
|
||||
unsafe { libc::__error() }
|
||||
}
|
||||
} else if #[cfg(any(target_os = "android", netbsdlike))] {
|
||||
} else if #[cfg(any(target_os = "android", netbsdlike, target_os = "cygwin"))] {
|
||||
unsafe fn errno_location() -> *mut c_int {
|
||||
unsafe { libc::__errno() }
|
||||
}
|
||||
@@ -32,7 +32,8 @@ cfg_if! {
|
||||
target_os = "redox",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"))] {
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten"))] {
|
||||
unsafe fn errno_location() -> *mut c_int {
|
||||
unsafe { libc::__errno_location() }
|
||||
}
|
||||
@@ -277,7 +278,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ECHRNG => "Channel number out of range",
|
||||
|
||||
@@ -285,7 +288,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EL2NSYNC => "Level 2 not synchronized",
|
||||
|
||||
@@ -293,7 +298,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EL3HLT => "Level 3 halted",
|
||||
|
||||
@@ -301,7 +308,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EL3RST => "Level 3 reset",
|
||||
|
||||
@@ -309,7 +318,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELNRNG => "Link number out of range",
|
||||
|
||||
@@ -317,7 +328,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EUNATCH => "Protocol driver not attached",
|
||||
|
||||
@@ -325,7 +338,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOCSI => "No CSI structure available",
|
||||
|
||||
@@ -333,36 +348,82 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EL2HLT => "Level 2 halted",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADE => "Invalid exchange",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADR => "Invalid request descriptor",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EXFULL => "Exchange full",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOANO => "No anode",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADRQC => "Invalid request code",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADSLT => "Invalid slot",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBFONT => "Bad font file format",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOSTR => "Device not a stream",
|
||||
|
||||
@@ -370,7 +431,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENODATA => "No data available",
|
||||
|
||||
@@ -378,7 +441,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ETIME => "Timer expired",
|
||||
|
||||
@@ -386,21 +451,37 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOSR => "Out of streams resources",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENONET => "Machine is not on the network",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOPKG => "Package not installed",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EREMOTE => "Object is remote",
|
||||
|
||||
@@ -408,17 +489,36 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ENOLINK => "Link has been severed",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EADV => "Advertise error",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ESRMNT => "Srmount error",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ECOMM => "Communication error on send",
|
||||
|
||||
#[cfg(any(
|
||||
@@ -426,6 +526,8 @@ fn desc(errno: Errno) -> &'static str {
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EPROTO => "Protocol error",
|
||||
|
||||
@@ -433,14 +535,26 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EMULTIHOP => "Multihop attempted",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EDOTDOT => "RFS specific error",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "aix", target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADMSG => "Not a data message",
|
||||
|
||||
#[cfg(solarish)]
|
||||
@@ -451,36 +565,82 @@ fn desc(errno: Errno) -> &'static str {
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EOVERFLOW => "Value too large for defined data type",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOTUNIQ => "Name not unique on network",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EBADFD => "File descriptor in bad state",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EREMCHG => "Remote address changed",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELIBACC => "Can not access a needed shared library",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELIBBAD => "Accessing a corrupted shared library",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELIBSCN => ".lib section in a.out corrupted",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELIBMAX => "Attempting to link in too many shared libraries",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ELIBEXEC => "Cannot exec a shared library directly",
|
||||
|
||||
@@ -489,7 +649,9 @@ fn desc(errno: Errno) -> &'static str {
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "openbsd"
|
||||
target_os = "openbsd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EILSEQ => "Illegal byte sequence",
|
||||
|
||||
@@ -497,57 +659,106 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ERESTART => "Interrupted system call should be restarted",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ESTRPIPE => "Streams pipe error",
|
||||
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EUSERS => "Too many users",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EOPNOTSUPP => "Operation not supported on transport endpoint",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", target_os = "hurd"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ESTALE => "Stale file handle",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EUCLEAN => "Structure needs cleaning",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ENOTNAM => "Not a XENIX named type file",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ENAVAIL => "No XENIX semaphores available",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EISNAM => "Is a named type file",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EREMOTEIO => "Remote I/O error",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EDQUOT => "Quota exceeded",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly"
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOMEDIUM => "No medium found",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "openbsd"
|
||||
target_os = "openbsd",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EMEDIUMTYPE => "Wrong medium type",
|
||||
|
||||
@@ -555,34 +766,60 @@ fn desc(errno: Errno) -> &'static str {
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ECANCELED => "Operation canceled",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ENOKEY => "Required key not available",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EKEYEXPIRED => "Key has expired",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EKEYREVOKED => "Key has been revoked",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EKEYREJECTED => "Key was rejected by service",
|
||||
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
EOWNERDEAD => "Owner died",
|
||||
|
||||
#[cfg(solarish)]
|
||||
EOWNERDEAD => "Process died with lock",
|
||||
|
||||
#[cfg(any(linux_android, target_os = "aix", target_os = "fuchsia"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
target_os = "aix",
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
ENOTRECOVERABLE => "State not recoverable",
|
||||
|
||||
#[cfg(solarish)]
|
||||
@@ -590,23 +827,35 @@ fn desc(errno: Errno) -> &'static str {
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "linux", not(target_arch = "mips")),
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
ERFKILL => "Operation not possible due to RF-kill",
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "linux", not(target_arch = "mips")),
|
||||
target_os = "fuchsia"
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
))]
|
||||
EHWPOISON => "Memory page has hardware error",
|
||||
|
||||
#[cfg(freebsdlike)]
|
||||
EDOOFUS => "Programming error",
|
||||
|
||||
#[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))]
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
EMULTIHOP => "Multihop attempted",
|
||||
|
||||
#[cfg(any(freebsdlike, target_os = "hurd", target_os = "redox"))]
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
ENOLINK => "Link has been severed",
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
@@ -666,11 +915,17 @@ fn desc(errno: Errno) -> &'static str {
|
||||
target_os = "aix",
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
ENOTSUP => "Operation not supported",
|
||||
|
||||
#[cfg(any(bsd, target_os = "aix", target_os = "hurd"))]
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
target_os = "aix",
|
||||
target_os = "hurd",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
EPROCLIM => "Too many processes",
|
||||
|
||||
#[cfg(any(
|
||||
@@ -718,7 +973,7 @@ fn desc(errno: Errno) -> &'static str {
|
||||
#[cfg(any(bsd, target_os = "hurd"))]
|
||||
EPROCUNAVAIL => "Bad procedure for program",
|
||||
|
||||
#[cfg(any(bsd, target_os = "hurd"))]
|
||||
#[cfg(any(bsd, target_os = "hurd", target_os = "cygwin"))]
|
||||
EFTYPE => "Inappropriate file type or format",
|
||||
|
||||
#[cfg(any(bsd, target_os = "hurd"))]
|
||||
@@ -806,7 +1061,7 @@ fn desc(errno: Errno) -> &'static str {
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
EASYNC => "Async",
|
||||
|
||||
#[cfg(solarish)]
|
||||
#[cfg(any(solarish, target_os = "cygwin"))]
|
||||
EDEADLOCK => "Resource deadlock would occur",
|
||||
|
||||
#[cfg(solarish)]
|
||||
@@ -832,7 +1087,7 @@ fn desc(errno: Errno) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", target_os = "emscripten"))]
|
||||
mod consts {
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
@@ -3334,3 +3589,271 @@ mod consts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "cygwin")]
|
||||
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,
|
||||
ENOMSG = libc::ENOMSG,
|
||||
EIDRM = libc::EIDRM,
|
||||
ECHRNG = libc::ECHRNG,
|
||||
EL2NSYNC = libc::EL2NSYNC,
|
||||
EL3HLT = libc::EL3HLT,
|
||||
EL3RST = libc::EL3RST,
|
||||
ELNRNG = libc::ELNRNG,
|
||||
EUNATCH = libc::EUNATCH,
|
||||
ENOCSI = libc::ENOCSI,
|
||||
EL2HLT = libc::EL2HLT,
|
||||
EDEADLK = libc::EDEADLK,
|
||||
ENOLCK = libc::ENOLCK,
|
||||
EBADE = libc::EBADE,
|
||||
EBADR = libc::EBADR,
|
||||
EXFULL = libc::EXFULL,
|
||||
ENOANO = libc::ENOANO,
|
||||
EBADRQC = libc::EBADRQC,
|
||||
EBADSLT = libc::EBADSLT,
|
||||
EDEADLOCK = libc::EDEADLOCK,
|
||||
EBFONT = libc::EBFONT,
|
||||
ENOSTR = libc::ENOSTR,
|
||||
ENODATA = libc::ENODATA,
|
||||
ETIME = libc::ETIME,
|
||||
ENOSR = libc::ENOSR,
|
||||
ENONET = libc::ENONET,
|
||||
ENOPKG = libc::ENOPKG,
|
||||
EREMOTE = libc::EREMOTE,
|
||||
ENOLINK = libc::ENOLINK,
|
||||
EADV = libc::EADV,
|
||||
ESRMNT = libc::ESRMNT,
|
||||
ECOMM = libc::ECOMM,
|
||||
EPROTO = libc::EPROTO,
|
||||
EMULTIHOP = libc::EMULTIHOP,
|
||||
EDOTDOT = libc::EDOTDOT,
|
||||
EBADMSG = libc::EBADMSG,
|
||||
EFTYPE = libc::EFTYPE,
|
||||
ENOTUNIQ = libc::ENOTUNIQ,
|
||||
EBADFD = libc::EBADFD,
|
||||
EREMCHG = libc::EREMCHG,
|
||||
ELIBACC = libc::ELIBACC,
|
||||
ELIBBAD = libc::ELIBBAD,
|
||||
ELIBSCN = libc::ELIBSCN,
|
||||
ELIBMAX = libc::ELIBMAX,
|
||||
ELIBEXEC = libc::ELIBEXEC,
|
||||
ENOSYS = libc::ENOSYS,
|
||||
ENOTEMPTY = libc::ENOTEMPTY,
|
||||
ENAMETOOLONG = libc::ENAMETOOLONG,
|
||||
ELOOP = libc::ELOOP,
|
||||
EOPNOTSUPP = libc::EOPNOTSUPP,
|
||||
EPFNOSUPPORT = libc::EPFNOSUPPORT,
|
||||
ECONNRESET = libc::ECONNRESET,
|
||||
ENOBUFS = libc::ENOBUFS,
|
||||
EAFNOSUPPORT = libc::EAFNOSUPPORT,
|
||||
EPROTOTYPE = libc::EPROTOTYPE,
|
||||
ENOTSOCK = libc::ENOTSOCK,
|
||||
ENOPROTOOPT = libc::ENOPROTOOPT,
|
||||
ESHUTDOWN = libc::ESHUTDOWN,
|
||||
ECONNREFUSED = libc::ECONNREFUSED,
|
||||
EADDRINUSE = libc::EADDRINUSE,
|
||||
ECONNABORTED = libc::ECONNABORTED,
|
||||
ENETUNREACH = libc::ENETUNREACH,
|
||||
ENETDOWN = libc::ENETDOWN,
|
||||
ETIMEDOUT = libc::ETIMEDOUT,
|
||||
EHOSTDOWN = libc::EHOSTDOWN,
|
||||
EHOSTUNREACH = libc::EHOSTUNREACH,
|
||||
EINPROGRESS = libc::EINPROGRESS,
|
||||
EALREADY = libc::EALREADY,
|
||||
EDESTADDRREQ = libc::EDESTADDRREQ,
|
||||
EMSGSIZE = libc::EMSGSIZE,
|
||||
EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
|
||||
ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
|
||||
EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
|
||||
ENETRESET = libc::ENETRESET,
|
||||
EISCONN = libc::EISCONN,
|
||||
ENOTCONN = libc::ENOTCONN,
|
||||
ETOOMANYREFS = libc::ETOOMANYREFS,
|
||||
EPROCLIM = libc::EPROCLIM,
|
||||
EUSERS = libc::EUSERS,
|
||||
EDQUOT = libc::EDQUOT,
|
||||
ESTALE = libc::ESTALE,
|
||||
ENOTSUP = libc::ENOTSUP,
|
||||
ENOMEDIUM = libc::ENOMEDIUM,
|
||||
EILSEQ = libc::EILSEQ,
|
||||
EOVERFLOW = libc::EOVERFLOW,
|
||||
ECANCELED = libc::ECANCELED,
|
||||
ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
|
||||
EOWNERDEAD = libc::EOWNERDEAD,
|
||||
ESTRPIPE = libc::ESTRPIPE,
|
||||
}
|
||||
|
||||
impl Errno {
|
||||
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
|
||||
pub const EDEADLOCK: Errno = Errno::EDEADLK;
|
||||
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
|
||||
}
|
||||
|
||||
pub(crate) 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::ENOMSG => ENOMSG,
|
||||
libc::EIDRM => EIDRM,
|
||||
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::EDEADLK => EDEADLK,
|
||||
libc::ENOLCK => ENOLCK,
|
||||
libc::EBADE => EBADE,
|
||||
libc::EBADR => EBADR,
|
||||
libc::EXFULL => EXFULL,
|
||||
libc::ENOANO => ENOANO,
|
||||
libc::EBADRQC => EBADRQC,
|
||||
libc::EBADSLT => EBADSLT,
|
||||
libc::EDEADLOCK => EDEADLOCK,
|
||||
libc::EBFONT => EBFONT,
|
||||
libc::ENOSTR => ENOSTR,
|
||||
libc::ENODATA => ENODATA,
|
||||
libc::ETIME => ETIME,
|
||||
libc::ENOSR => ENOSR,
|
||||
libc::ENONET => ENONET,
|
||||
libc::ENOPKG => ENOPKG,
|
||||
libc::EREMOTE => EREMOTE,
|
||||
libc::ENOLINK => ENOLINK,
|
||||
libc::EADV => EADV,
|
||||
libc::ESRMNT => ESRMNT,
|
||||
libc::ECOMM => ECOMM,
|
||||
libc::EPROTO => EPROTO,
|
||||
libc::EMULTIHOP => EMULTIHOP,
|
||||
libc::EDOTDOT => EDOTDOT,
|
||||
libc::EBADMSG => EBADMSG,
|
||||
libc::EFTYPE => EFTYPE,
|
||||
libc::ENOTUNIQ => ENOTUNIQ,
|
||||
libc::EBADFD => EBADFD,
|
||||
libc::EREMCHG => EREMCHG,
|
||||
libc::ELIBACC => ELIBACC,
|
||||
libc::ELIBBAD => ELIBBAD,
|
||||
libc::ELIBSCN => ELIBSCN,
|
||||
libc::ELIBMAX => ELIBMAX,
|
||||
libc::ELIBEXEC => ELIBEXEC,
|
||||
libc::ENOSYS => ENOSYS,
|
||||
libc::ENOTEMPTY => ENOTEMPTY,
|
||||
libc::ENAMETOOLONG => ENAMETOOLONG,
|
||||
libc::ELOOP => ELOOP,
|
||||
libc::EOPNOTSUPP => EOPNOTSUPP,
|
||||
libc::EPFNOSUPPORT => EPFNOSUPPORT,
|
||||
libc::ECONNRESET => ECONNRESET,
|
||||
libc::ENOBUFS => ENOBUFS,
|
||||
libc::EAFNOSUPPORT => EAFNOSUPPORT,
|
||||
libc::EPROTOTYPE => EPROTOTYPE,
|
||||
libc::ENOTSOCK => ENOTSOCK,
|
||||
libc::ENOPROTOOPT => ENOPROTOOPT,
|
||||
libc::ESHUTDOWN => ESHUTDOWN,
|
||||
libc::ECONNREFUSED => ECONNREFUSED,
|
||||
libc::EADDRINUSE => EADDRINUSE,
|
||||
libc::ECONNABORTED => ECONNABORTED,
|
||||
libc::ENETUNREACH => ENETUNREACH,
|
||||
libc::ENETDOWN => ENETDOWN,
|
||||
libc::ETIMEDOUT => ETIMEDOUT,
|
||||
libc::EHOSTDOWN => EHOSTDOWN,
|
||||
libc::EHOSTUNREACH => EHOSTUNREACH,
|
||||
libc::EINPROGRESS => EINPROGRESS,
|
||||
libc::EALREADY => EALREADY,
|
||||
libc::EDESTADDRREQ => EDESTADDRREQ,
|
||||
libc::EMSGSIZE => EMSGSIZE,
|
||||
libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
|
||||
libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
|
||||
libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
|
||||
libc::ENETRESET => ENETRESET,
|
||||
libc::EISCONN => EISCONN,
|
||||
libc::ENOTCONN => ENOTCONN,
|
||||
libc::ETOOMANYREFS => ETOOMANYREFS,
|
||||
libc::EPROCLIM => EPROCLIM,
|
||||
libc::EUSERS => EUSERS,
|
||||
libc::EDQUOT => EDQUOT,
|
||||
libc::ESTALE => ESTALE,
|
||||
libc::ENOTSUP => ENOTSUP,
|
||||
libc::ENOMEDIUM => ENOMEDIUM,
|
||||
libc::EILSEQ => EILSEQ,
|
||||
libc::EOVERFLOW => EOVERFLOW,
|
||||
libc::ECANCELED => ECANCELED,
|
||||
libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
|
||||
libc::EOWNERDEAD => EOWNERDEAD,
|
||||
libc::ESTRPIPE => ESTRPIPE,
|
||||
_ => UnknownErrno,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
368
third_party/rust/nix/src/fcntl.rs
vendored
368
third_party/rust/nix/src/fcntl.rs
vendored
@@ -1,4 +1,4 @@
|
||||
//! file control options
|
||||
//! File control options
|
||||
use crate::errno::Errno;
|
||||
#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
|
||||
use core::slice;
|
||||
@@ -13,12 +13,10 @@ use std::ffi::CStr;
|
||||
use std::ffi::OsString;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::os::raw;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::os::unix::io::OwnedFd;
|
||||
use std::os::unix::io::RawFd;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
|
||||
use std::os::unix::io::{AsRawFd, OwnedFd};
|
||||
#[cfg(any(
|
||||
target_os = "netbsd",
|
||||
apple_targets,
|
||||
@@ -27,7 +25,7 @@ use std::os::unix::io::{AsRawFd, OwnedFd};
|
||||
))]
|
||||
use std::path::PathBuf;
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
use std::{os::unix::io::AsFd, ptr};
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::{sys::stat::Mode, NixPath, Result};
|
||||
@@ -43,6 +41,42 @@ use crate::{sys::stat::Mode, NixPath, Result};
|
||||
#[cfg(feature = "fs")]
|
||||
pub use self::posix_fadvise::{posix_fadvise, PosixFadviseAdvice};
|
||||
|
||||
/// A file descriptor referring to the working directory of the current process
|
||||
/// **that should be ONLY passed to the `dirfd` argument of those `xxat()` functions**.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Use it in [`openat()`]:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use nix::fcntl::AT_FDCWD;
|
||||
/// use nix::fcntl::openat;
|
||||
/// use nix::fcntl::OFlag;
|
||||
/// use nix::sys::stat::Mode;
|
||||
///
|
||||
/// let fd = openat(AT_FDCWD, "foo", OFlag::O_RDONLY | OFlag::O_CLOEXEC, Mode::empty()).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// # WARNING
|
||||
///
|
||||
/// Do NOT pass this symbol to non-`xxat()` functions, it won't work:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use nix::errno::Errno;
|
||||
/// use nix::fcntl::AT_FDCWD;
|
||||
/// use nix::sys::stat::fstat;
|
||||
///
|
||||
/// let never = fstat(AT_FDCWD).unwrap();
|
||||
/// ```
|
||||
//
|
||||
// SAFETY:
|
||||
// 1. `AT_FDCWD` is usable for the whole process life, so it is `'static`.
|
||||
// 2. It is not a valid file descriptor, but OS will handle it for us when passed
|
||||
// to `xxat(2)` calls.
|
||||
#[cfg(not(target_os = "redox"))] // Redox does not have this
|
||||
pub const AT_FDCWD: std::os::fd::BorrowedFd<'static> =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(libc::AT_FDCWD) };
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[cfg(any(feature = "fs", feature = "process", feature = "user"))]
|
||||
libc_bitflags! {
|
||||
@@ -94,7 +128,8 @@ libc_bitflags!(
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "aix",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
O_ASYNC;
|
||||
/// Closes the file descriptor once an `execve` call is made.
|
||||
@@ -107,7 +142,7 @@ libc_bitflags!(
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
O_DIRECT;
|
||||
@@ -139,7 +174,7 @@ libc_bitflags!(
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
O_NOCTTY;
|
||||
/// Same as `O_NONBLOCK`.
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "cygwin")))]
|
||||
O_NDELAY;
|
||||
/// `open()` will fail if the given path is a symbolic link.
|
||||
O_NOFOLLOW;
|
||||
@@ -198,16 +233,6 @@ libc_bitflags!(
|
||||
}
|
||||
);
|
||||
|
||||
/// Computes the raw fd consumed by a function of the form `*at`.
|
||||
#[cfg(any(
|
||||
all(feature = "fs", not(target_os = "redox")),
|
||||
all(feature = "process", linux_android),
|
||||
all(feature = "fanotify", target_os = "linux")
|
||||
))]
|
||||
pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
|
||||
fd.unwrap_or(libc::AT_FDCWD)
|
||||
}
|
||||
|
||||
feature! {
|
||||
#![feature = "fs"]
|
||||
|
||||
@@ -221,35 +246,49 @@ pub fn open<P: ?Sized + NixPath>(
|
||||
path: &P,
|
||||
oflag: OFlag,
|
||||
mode: Mode,
|
||||
) -> Result<RawFd> {
|
||||
) -> Result<std::os::fd::OwnedFd> {
|
||||
use std::os::fd::FromRawFd;
|
||||
|
||||
let fd = path.with_nix_path(|cstr| unsafe {
|
||||
libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
|
||||
})?;
|
||||
Errno::result(fd)?;
|
||||
|
||||
Errno::result(fd)
|
||||
// SAFETY:
|
||||
//
|
||||
// `open(2)` should return a valid owned fd on success
|
||||
Ok( unsafe { std::os::fd::OwnedFd::from_raw_fd(fd) } )
|
||||
}
|
||||
|
||||
/// open or create a file for reading, writing or executing
|
||||
///
|
||||
/// The `openat` function is equivalent to the [`open`] function except in the case where the path
|
||||
/// specifies a relative path. In that case, the file to be opened is determined relative to the
|
||||
/// directory associated with the file descriptor `fd`.
|
||||
/// directory associated with the file descriptor `dirfd`.
|
||||
///
|
||||
/// # See Also
|
||||
/// [`openat`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html)
|
||||
// The conversion is not identical on all operating systems.
|
||||
#[allow(clippy::useless_conversion)]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn openat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn openat<P: ?Sized + NixPath, Fd: std::os::fd::AsFd>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
oflag: OFlag,
|
||||
mode: Mode,
|
||||
) -> Result<RawFd> {
|
||||
) -> Result<OwnedFd> {
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::fd::FromRawFd;
|
||||
|
||||
let fd = path.with_nix_path(|cstr| unsafe {
|
||||
libc::openat(at_rawfd(dirfd), cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
|
||||
libc::openat(dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint)
|
||||
})?;
|
||||
Errno::result(fd)
|
||||
Errno::result(fd)?;
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// `openat(2)` should return a valid owned fd on success
|
||||
Ok( unsafe { OwnedFd::from_raw_fd(fd) } )
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
@@ -287,9 +326,11 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies how [openat2] should open a pathname.
|
||||
/// Specifies how [`openat2()`] should open a pathname.
|
||||
///
|
||||
/// See <https://man7.org/linux/man-pages/man2/open_how.2type.html>
|
||||
/// # Reference
|
||||
///
|
||||
/// * [Linux](https://man7.org/linux/man-pages/man2/open_how.2type.html)
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct OpenHow(libc::open_how);
|
||||
@@ -345,22 +386,29 @@ cfg_if::cfg_if! {
|
||||
/// # See also
|
||||
///
|
||||
/// [openat2](https://man7.org/linux/man-pages/man2/openat2.2.html)
|
||||
pub fn openat2<P: ?Sized + NixPath>(
|
||||
dirfd: RawFd,
|
||||
pub fn openat2<P: ?Sized + NixPath, Fd: std::os::fd::AsFd>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
mut how: OpenHow,
|
||||
) -> Result<RawFd> {
|
||||
) -> Result<OwnedFd> {
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::fd::FromRawFd;
|
||||
|
||||
let fd = path.with_nix_path(|cstr| unsafe {
|
||||
libc::syscall(
|
||||
libc::SYS_openat2,
|
||||
dirfd,
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
&mut how as *mut OpenHow,
|
||||
std::mem::size_of::<libc::open_how>(),
|
||||
)
|
||||
})?;
|
||||
})? as RawFd;
|
||||
Errno::result(fd)?;
|
||||
|
||||
Errno::result(fd as RawFd)
|
||||
// SAFETY:
|
||||
//
|
||||
// `openat2(2)` should return a valid owned fd on success
|
||||
Ok( unsafe { OwnedFd::from_raw_fd(fd) } )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,18 +422,20 @@ cfg_if::cfg_if! {
|
||||
/// # See Also
|
||||
/// [`renameat`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html)
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
|
||||
old_dirfd: Option<RawFd>,
|
||||
pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
|
||||
old_dirfd: Fd1,
|
||||
old_path: &P1,
|
||||
new_dirfd: Option<RawFd>,
|
||||
new_dirfd: Fd2,
|
||||
new_path: &P2,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = old_path.with_nix_path(|old_cstr| {
|
||||
new_path.with_nix_path(|new_cstr| unsafe {
|
||||
libc::renameat(
|
||||
at_rawfd(old_dirfd),
|
||||
old_dirfd.as_fd().as_raw_fd(),
|
||||
old_cstr.as_ptr(),
|
||||
at_rawfd(new_dirfd),
|
||||
new_dirfd.as_fd().as_raw_fd(),
|
||||
new_cstr.as_ptr(),
|
||||
)
|
||||
})
|
||||
@@ -422,19 +472,21 @@ feature! {
|
||||
/// # See Also
|
||||
/// * [`rename`](https://man7.org/linux/man-pages/man2/rename.2.html)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
|
||||
old_dirfd: Option<RawFd>,
|
||||
pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
|
||||
old_dirfd: Fd1,
|
||||
old_path: &P1,
|
||||
new_dirfd: Option<RawFd>,
|
||||
new_dirfd: Fd2,
|
||||
new_path: &P2,
|
||||
flags: RenameFlags,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = old_path.with_nix_path(|old_cstr| {
|
||||
new_path.with_nix_path(|new_cstr| unsafe {
|
||||
libc::renameat2(
|
||||
at_rawfd(old_dirfd),
|
||||
old_dirfd.as_fd().as_raw_fd(),
|
||||
old_cstr.as_ptr(),
|
||||
at_rawfd(new_dirfd),
|
||||
new_dirfd.as_fd().as_raw_fd(),
|
||||
new_cstr.as_ptr(),
|
||||
flags.bits(),
|
||||
)
|
||||
@@ -449,7 +501,16 @@ fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
|
||||
Ok(OsString::from_vec(v.to_vec()))
|
||||
}
|
||||
|
||||
fn readlink_maybe_at<P: ?Sized + NixPath>(
|
||||
/// Read the symlink specified by `path` and `dirfd` and put the contents in `v`.
|
||||
/// Return the number of bytes placed in `v`.
|
||||
///
|
||||
/// This function can call `readlink(2)` or `readlinkat(2)` depending on if `dirfd`
|
||||
/// is some, if it is, then `readlinkat(2)` is called, otherwise, call `readlink(2)`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is not I/O-safe considering it employs the `RawFd` type.
|
||||
unsafe fn readlink_maybe_at<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
path: &P,
|
||||
v: &mut Vec<u8>,
|
||||
@@ -457,7 +518,7 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
|
||||
path.with_nix_path(|cstr| unsafe {
|
||||
match dirfd {
|
||||
#[cfg(target_os = "redox")]
|
||||
Some(_) => unreachable!(),
|
||||
Some(_) => unreachable!("redox does not have readlinkat(2)"),
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
Some(dirfd) => libc::readlinkat(
|
||||
dirfd,
|
||||
@@ -474,7 +535,15 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
|
||||
})
|
||||
}
|
||||
|
||||
fn inner_readlink<P: ?Sized + NixPath>(
|
||||
/// The actual implementation of [`readlink(2)`] or [`readlinkat(2)`].
|
||||
///
|
||||
/// This function can call `readlink(2)` or `readlinkat(2)` depending on if `dirfd`
|
||||
/// is some, if it is, then `readlinkat(2)` is called, otherwise, call `readlink(2)`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is marked unsafe because it uses `RawFd`.
|
||||
unsafe fn inner_readlink<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
path: &P,
|
||||
) -> Result<OsString> {
|
||||
@@ -486,7 +555,12 @@ fn inner_readlink<P: ?Sized + NixPath>(
|
||||
|
||||
{
|
||||
// simple case: result is strictly less than `PATH_MAX`
|
||||
let res = readlink_maybe_at(dirfd, path, &mut v)?;
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// If this call of `readlink_maybe_at()` is safe or not depends on the
|
||||
// usage of `unsafe fn inner_readlink()`.
|
||||
let res = unsafe { readlink_maybe_at(dirfd, path, &mut v)? };
|
||||
let len = Errno::result(res)?;
|
||||
debug_assert!(len >= 0);
|
||||
if (len as usize) < v.capacity() {
|
||||
@@ -499,16 +573,23 @@ fn inner_readlink<P: ?Sized + NixPath>(
|
||||
let mut try_size = {
|
||||
let reported_size = match dirfd {
|
||||
#[cfg(target_os = "redox")]
|
||||
Some(_) => unreachable!(),
|
||||
Some(_) => unreachable!("redox does not have readlinkat(2)"),
|
||||
#[cfg(any(linux_android, target_os = "freebsd", target_os = "hurd"))]
|
||||
Some(dirfd) => {
|
||||
// SAFETY:
|
||||
//
|
||||
// If this call of `borrow_raw()` is safe or not depends on the
|
||||
// usage of `unsafe fn inner_readlink()`.
|
||||
let dirfd = unsafe {
|
||||
std::os::fd::BorrowedFd::borrow_raw(dirfd)
|
||||
};
|
||||
let flags = if path.is_empty() {
|
||||
AtFlags::AT_EMPTY_PATH
|
||||
} else {
|
||||
AtFlags::empty()
|
||||
};
|
||||
super::sys::stat::fstatat(
|
||||
Some(dirfd),
|
||||
dirfd,
|
||||
path,
|
||||
flags | AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||
)
|
||||
@@ -519,11 +600,16 @@ fn inner_readlink<P: ?Sized + NixPath>(
|
||||
target_os = "freebsd",
|
||||
target_os = "hurd"
|
||||
)))]
|
||||
Some(dirfd) => super::sys::stat::fstatat(
|
||||
Some(dirfd),
|
||||
path,
|
||||
AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||
),
|
||||
Some(dirfd) => {
|
||||
// SAFETY:
|
||||
//
|
||||
// If this call of `borrow_raw()` is safe or not depends on the
|
||||
// usage of `unsafe fn inner_readlink()`.
|
||||
let dirfd = unsafe {
|
||||
std::os::fd::BorrowedFd::borrow_raw(dirfd)
|
||||
};
|
||||
super::sys::stat::fstatat(dirfd, path, AtFlags::AT_SYMLINK_NOFOLLOW)
|
||||
},
|
||||
None => super::sys::stat::lstat(path),
|
||||
}
|
||||
.map(|x| x.st_size)
|
||||
@@ -543,7 +629,11 @@ fn inner_readlink<P: ?Sized + NixPath>(
|
||||
loop {
|
||||
{
|
||||
v.reserve_exact(try_size);
|
||||
let res = readlink_maybe_at(dirfd, path, &mut v)?;
|
||||
// SAFETY:
|
||||
//
|
||||
// If this call of `readlink_maybe_at()` is safe or not depends on the
|
||||
// usage of `unsafe fn inner_readlink()`.
|
||||
let res = unsafe { readlink_maybe_at(dirfd, path, &mut v)? };
|
||||
let len = Errno::result(res)?;
|
||||
debug_assert!(len >= 0);
|
||||
if (len as usize) < v.capacity() {
|
||||
@@ -566,23 +656,39 @@ fn inner_readlink<P: ?Sized + NixPath>(
|
||||
/// # See Also
|
||||
/// * [`readlink`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html)
|
||||
pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
|
||||
inner_readlink(None, path)
|
||||
// argument `dirfd` should be `None` since we call it from `readlink()`
|
||||
//
|
||||
// Do NOT call it with `Some(AT_CWD)` as in that way, we are emulating
|
||||
// `readlink(2)` with `readlinkat(2)`, which will make us lose `readlink(2)`
|
||||
// on Redox.
|
||||
//
|
||||
// SAFETY:
|
||||
//
|
||||
// It is definitely safe because the argument involving `RawFd` is `None`
|
||||
unsafe { inner_readlink(None, path) }
|
||||
}
|
||||
|
||||
/// Read value of a symbolic link.
|
||||
///
|
||||
/// Equivalent to [`readlink` ] except where `path` specifies a relative path. In that case,
|
||||
/// interpret `path` relative to open file specified by `dirfd`.
|
||||
/// Equivalent to [`readlink` ] except for the case where `path` specifies a
|
||||
/// relative path, `path` will be interpreted relative to the path specified
|
||||
/// by `dirfd`. (Use [`AT_FDCWD`] to make it relative to the working directory).
|
||||
///
|
||||
/// # See Also
|
||||
/// * [`readlink`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html)
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn readlinkat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn readlinkat<Fd: std::os::fd::AsFd,P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
) -> Result<OsString> {
|
||||
let dirfd = at_rawfd(dirfd);
|
||||
inner_readlink(Some(dirfd), path)
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
// argument `dirfd` should be `Some` since we call it from `readlinkat()`
|
||||
//
|
||||
// SAFETY:
|
||||
//
|
||||
// The passed `RawFd` should be valid since it is borrowed from `Fd: AsFd`.
|
||||
unsafe { inner_readlink(Some(dirfd.as_fd().as_raw_fd()), path) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,6 +798,39 @@ pub enum FcntlArg<'a> {
|
||||
/// Return the full path without firmlinks of the fd.
|
||||
#[cfg(apple_targets)]
|
||||
F_GETPATH_NOFIRMLINK(&'a mut PathBuf),
|
||||
/// Issue an advisory read async with no copy to user
|
||||
#[cfg(apple_targets)]
|
||||
F_RDADVISE(libc::radvisory),
|
||||
/// Turn read ahead off/on
|
||||
#[cfg(apple_targets)]
|
||||
F_RDAHEAD(bool),
|
||||
/// Pre-allocate storage with different policies on fd.
|
||||
/// Note that we want a mutable reference for the OUT
|
||||
/// fstore_t field fst_bytesalloc.
|
||||
#[cfg(apple_targets)]
|
||||
F_PREALLOCATE(&'a mut libc::fstore_t),
|
||||
#[cfg(apple_targets)]
|
||||
/// Get disk device information. In practice,
|
||||
/// only the file offset data is set.
|
||||
F_LOG2PHYS(&'a mut libc::off_t),
|
||||
#[cfg(apple_targets)]
|
||||
/// Get disk device information. In practice,
|
||||
/// only the file offset data is set.
|
||||
/// The difference with F_LOG2PHYS is the struct passed
|
||||
/// is used as both IN/OUT as both its l2p_devoffset and
|
||||
/// l2p_contigbytes can be used for more specific queries.
|
||||
F_LOG2PHYS_EXT(&'a mut libc::log2phys),
|
||||
/// Transfer any extra space in the file past the logical EOF
|
||||
/// (as previously allocated via F_PREALLOCATE) to another file.
|
||||
/// The other file is specified via a file descriptor as the lone extra argument.
|
||||
/// Both descriptors must reference regular files in the same volume.
|
||||
#[cfg(apple_targets)]
|
||||
F_TRANSFEREXTENTS(RawFd),
|
||||
/// Set or clear the read ahead (pre-fetch) amount for sequential access or
|
||||
/// disable it with 0 or to system default for any value < 0.
|
||||
/// It manages how the kernel caches file data.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
F_READAHEAD(c_int),
|
||||
// TODO: Rest of flags
|
||||
}
|
||||
|
||||
@@ -720,7 +859,10 @@ pub use self::FcntlArg::*;
|
||||
/// # See Also
|
||||
/// * [`fcntl`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html)
|
||||
// TODO: Figure out how to handle value fcntl returns
|
||||
pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
|
||||
pub fn fcntl<Fd: std::os::fd::AsFd>(fd: Fd, arg: FcntlArg) -> Result<c_int> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let fd = fd.as_fd().as_raw_fd();
|
||||
let res = unsafe {
|
||||
match arg {
|
||||
F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
|
||||
@@ -797,6 +939,39 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
|
||||
*path = PathBuf::from(OsString::from(optr.to_str().unwrap()));
|
||||
return Ok(ok_res)
|
||||
},
|
||||
#[cfg(apple_targets)]
|
||||
F_RDADVISE(rad) => {
|
||||
libc::fcntl(fd, libc::F_RDADVISE, &rad)
|
||||
},
|
||||
#[cfg(apple_targets)]
|
||||
F_LOG2PHYS(offset) => {
|
||||
let mut info: libc::log2phys = std::mem::zeroed();
|
||||
let res = libc::fcntl(fd, libc::F_LOG2PHYS, &mut info);
|
||||
let ok_res = Errno::result(res)?;
|
||||
*offset = info.l2p_devoffset;
|
||||
return Ok(ok_res)
|
||||
}
|
||||
#[cfg(apple_targets)]
|
||||
F_LOG2PHYS_EXT(info) => {
|
||||
libc::fcntl(fd, libc::F_LOG2PHYS_EXT, info)
|
||||
}
|
||||
#[cfg(apple_targets)]
|
||||
F_RDAHEAD(on) => {
|
||||
let val = if on { 1 } else { 0 };
|
||||
libc::fcntl(fd, libc::F_RDAHEAD, val)
|
||||
},
|
||||
#[cfg(apple_targets)]
|
||||
F_PREALLOCATE(st) => {
|
||||
libc::fcntl(fd, libc::F_PREALLOCATE, st)
|
||||
},
|
||||
#[cfg(apple_targets)]
|
||||
F_TRANSFEREXTENTS(rawfd) => {
|
||||
libc::fcntl(fd, libc::F_TRANSFEREXTENTS, rawfd)
|
||||
},
|
||||
#[cfg(target_os = "freebsd")]
|
||||
F_READAHEAD(val) => {
|
||||
libc::fcntl(fd, libc::F_READAHEAD, val)
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -853,7 +1028,7 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
|
||||
/// # Safety
|
||||
/// Types implementing this must not be `Clone`.
|
||||
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
|
||||
pub unsafe trait Flockable: AsRawFd {}
|
||||
pub unsafe trait Flockable: std::os::fd::AsRawFd {}
|
||||
|
||||
/// Represents an owned flock, which unlocks on drop.
|
||||
///
|
||||
@@ -1037,13 +1212,15 @@ feature! {
|
||||
// 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(linux_android, target_os = "freebsd"))]
|
||||
pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
|
||||
pub fn copy_file_range<Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
|
||||
fd_in: Fd1,
|
||||
off_in: Option<&mut i64>,
|
||||
fd_out: Fd2,
|
||||
off_out: Option<&mut i64>,
|
||||
len: usize,
|
||||
) -> Result<usize> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let off_in = off_in
|
||||
.map(|offset| offset as *mut i64)
|
||||
.unwrap_or(ptr::null_mut());
|
||||
@@ -1087,7 +1264,7 @@ pub fn copy_file_range<Fd1: AsFd, Fd2: AsFd>(
|
||||
/// # See Also
|
||||
/// *[`splice`](https://man7.org/linux/man-pages/man2/splice.2.html)
|
||||
#[cfg(linux_android)]
|
||||
pub fn splice<Fd1: AsFd, Fd2: AsFd>(
|
||||
pub fn splice<Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
|
||||
fd_in: Fd1,
|
||||
off_in: Option<&mut libc::loff_t>,
|
||||
fd_out: Fd2,
|
||||
@@ -1095,6 +1272,8 @@ pub fn splice<Fd1: AsFd, Fd2: AsFd>(
|
||||
len: usize,
|
||||
flags: SpliceFFlags,
|
||||
) -> Result<usize> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let off_in = off_in
|
||||
.map(|offset| offset as *mut libc::loff_t)
|
||||
.unwrap_or(ptr::null_mut());
|
||||
@@ -1113,12 +1292,14 @@ pub fn splice<Fd1: AsFd, Fd2: AsFd>(
|
||||
/// # See Also
|
||||
/// *[`tee`](https://man7.org/linux/man-pages/man2/tee.2.html)
|
||||
#[cfg(linux_android)]
|
||||
pub fn tee<Fd1: AsFd, Fd2: AsFd>(
|
||||
pub fn tee<Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
|
||||
fd_in: Fd1,
|
||||
fd_out: Fd2,
|
||||
len: usize,
|
||||
flags: SpliceFFlags,
|
||||
) -> Result<usize> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let ret = unsafe { libc::tee(fd_in.as_fd().as_raw_fd(), fd_out.as_fd().as_raw_fd(), len, flags.bits()) };
|
||||
Errno::result(ret).map(|r| r as usize)
|
||||
}
|
||||
@@ -1128,11 +1309,13 @@ pub fn tee<Fd1: AsFd, Fd2: AsFd>(
|
||||
/// # See Also
|
||||
/// *[`vmsplice`](https://man7.org/linux/man-pages/man2/vmsplice.2.html)
|
||||
#[cfg(linux_android)]
|
||||
pub fn vmsplice<F: AsFd>(
|
||||
pub fn vmsplice<F: std::os::fd::AsFd>(
|
||||
fd: F,
|
||||
iov: &[std::io::IoSlice<'_>],
|
||||
flags: SpliceFFlags,
|
||||
) -> Result<usize> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let ret = unsafe {
|
||||
libc::vmsplice(
|
||||
fd.as_fd().as_raw_fd(),
|
||||
@@ -1173,7 +1356,7 @@ libc_bitflags!(
|
||||
FALLOC_FL_INSERT_RANGE;
|
||||
/// Shared file data extants are made private to the file.
|
||||
///
|
||||
/// Gaurantees that a subsequent write will not fail due to lack of space.
|
||||
/// Guarantees that a subsequent write will not fail due to lack of space.
|
||||
FALLOC_FL_UNSHARE_RANGE;
|
||||
}
|
||||
);
|
||||
@@ -1187,13 +1370,15 @@ feature! {
|
||||
/// file referred to by fd.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(feature = "fs")]
|
||||
pub fn fallocate(
|
||||
fd: RawFd,
|
||||
pub fn fallocate<Fd: std::os::fd::AsFd>(
|
||||
fd: Fd,
|
||||
mode: FallocateFlags,
|
||||
offset: libc::off_t,
|
||||
len: libc::off_t,
|
||||
) -> Result<()> {
|
||||
let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = unsafe { libc::fallocate(fd.as_fd().as_raw_fd(), mode.bits(), offset, len) };
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
|
||||
@@ -1260,7 +1445,7 @@ impl SpacectlRange {
|
||||
/// f.write_all(INITIAL).unwrap();
|
||||
/// let mut range = SpacectlRange(3, 6);
|
||||
/// while (!range.is_empty()) {
|
||||
/// range = fspacectl(f.as_raw_fd(), range).unwrap();
|
||||
/// range = fspacectl(&f, range).unwrap();
|
||||
/// }
|
||||
/// let mut buf = vec![0; INITIAL.len()];
|
||||
/// f.read_exact_at(&mut buf, 0).unwrap();
|
||||
@@ -1268,14 +1453,16 @@ impl SpacectlRange {
|
||||
/// ```
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[inline] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined
|
||||
pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
|
||||
pub fn fspacectl<Fd: std::os::fd::AsFd>(fd: Fd, range: SpacectlRange) -> Result<SpacectlRange> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let mut rqsr = libc::spacectl_range {
|
||||
r_offset: range.0,
|
||||
r_len: range.1,
|
||||
};
|
||||
let res = unsafe {
|
||||
libc::fspacectl(
|
||||
fd,
|
||||
fd.as_fd().as_raw_fd(),
|
||||
libc::SPACECTL_DEALLOC, // Only one command is supported ATM
|
||||
&rqsr,
|
||||
0, // No flags are currently supported
|
||||
@@ -1310,18 +1497,20 @@ pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result<SpacectlRange> {
|
||||
/// const INITIAL: &[u8] = b"0123456789abcdef";
|
||||
/// let mut f = tempfile().unwrap();
|
||||
/// f.write_all(INITIAL).unwrap();
|
||||
/// fspacectl_all(f.as_raw_fd(), 3, 6).unwrap();
|
||||
/// fspacectl_all(&f, 3, 6).unwrap();
|
||||
/// let mut buf = vec![0; INITIAL.len()];
|
||||
/// f.read_exact_at(&mut buf, 0).unwrap();
|
||||
/// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef");
|
||||
/// ```
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[inline] // Delays codegen, preventing linker errors with dylibs and --no-allow-shlib-undefined
|
||||
pub fn fspacectl_all(
|
||||
fd: RawFd,
|
||||
pub fn fspacectl_all<Fd: std::os::fd::AsFd>(
|
||||
fd: Fd,
|
||||
offset: libc::off_t,
|
||||
len: libc::off_t,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let mut rqsr = libc::spacectl_range {
|
||||
r_offset: offset,
|
||||
r_len: len,
|
||||
@@ -1329,7 +1518,7 @@ pub fn fspacectl_all(
|
||||
while rqsr.r_len > 0 {
|
||||
let res = unsafe {
|
||||
libc::fspacectl(
|
||||
fd,
|
||||
fd.as_fd().as_raw_fd(),
|
||||
libc::SPACECTL_DEALLOC, // Only one command is supported ATM
|
||||
&rqsr,
|
||||
0, // No flags are currently supported
|
||||
@@ -1352,7 +1541,6 @@ pub fn fspacectl_all(
|
||||
mod posix_fadvise {
|
||||
use crate::errno::Errno;
|
||||
use crate::Result;
|
||||
use std::os::unix::io::RawFd;
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
libc_enum! {
|
||||
@@ -1384,13 +1572,15 @@ mod posix_fadvise {
|
||||
///
|
||||
/// # See Also
|
||||
/// * [`posix_fadvise`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html)
|
||||
pub fn posix_fadvise(
|
||||
fd: RawFd,
|
||||
pub fn posix_fadvise<Fd: std::os::fd::AsFd>(
|
||||
fd: Fd,
|
||||
offset: libc::off_t,
|
||||
len: libc::off_t,
|
||||
advice: PosixFadviseAdvice,
|
||||
) -> Result<()> {
|
||||
let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = unsafe { libc::posix_fadvise(fd.as_fd().as_raw_fd(), offset, len, advice as libc::c_int) };
|
||||
|
||||
if res == 0 {
|
||||
Ok(())
|
||||
@@ -1412,12 +1602,14 @@ mod posix_fadvise {
|
||||
target_os = "fuchsia",
|
||||
target_os = "wasi",
|
||||
))]
|
||||
pub fn posix_fallocate(
|
||||
fd: RawFd,
|
||||
pub fn posix_fallocate<Fd: std::os::fd::AsFd>(
|
||||
fd: Fd,
|
||||
offset: libc::off_t,
|
||||
len: libc::off_t,
|
||||
) -> Result<()> {
|
||||
let res = unsafe { libc::posix_fallocate(fd, offset, len) };
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = unsafe { libc::posix_fallocate(fd.as_fd().as_raw_fd(), offset, len) };
|
||||
match Errno::result(res) {
|
||||
Err(err) => Err(err),
|
||||
Ok(0) => Ok(()),
|
||||
|
||||
5
third_party/rust/nix/src/features.rs
vendored
5
third_party/rust/nix/src/features.rs
vendored
@@ -1,7 +1,7 @@
|
||||
//! Feature tests for OS functionality
|
||||
pub use self::os::*;
|
||||
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(any(linux_android, target_os = "emscripten"))]
|
||||
mod os {
|
||||
use crate::sys::utsname::uname;
|
||||
use crate::Result;
|
||||
@@ -92,7 +92,7 @@ mod os {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_parsing_kernel_version() {
|
||||
fn test_parsing_kernel_version() {
|
||||
assert!(kernel_version().unwrap() > 0);
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,7 @@ mod os {
|
||||
target_os = "hurd", // Since glibc 2.28
|
||||
target_os = "illumos", // Since ???
|
||||
target_os = "redox", // Since 1-july-2020
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
mod os {
|
||||
/// Check if the OS supports atomic close-on-exec for sockets
|
||||
|
||||
2
third_party/rust/nix/src/ifaddrs.rs
vendored
2
third_party/rust/nix/src/ifaddrs.rs
vendored
@@ -93,7 +93,7 @@ impl InterfaceAddress {
|
||||
let netmask =
|
||||
unsafe { SockaddrStorage::from_raw(info.ifa_netmask, None) };
|
||||
let mut addr = InterfaceAddress {
|
||||
interface_name: ifname.to_string_lossy().to_string(),
|
||||
interface_name: ifname.to_string_lossy().into_owned(),
|
||||
flags: InterfaceFlags::from_bits_truncate(
|
||||
info.ifa_flags as IflagsType,
|
||||
),
|
||||
|
||||
39
third_party/rust/nix/src/lib.rs
vendored
39
third_party/rust/nix/src/lib.rs
vendored
@@ -34,6 +34,7 @@
|
||||
//! * `sched` - Manipulate process's scheduling
|
||||
//! * `socket` - Sockets, whether for networking or local use
|
||||
//! * `signal` - Send and receive signals to processes
|
||||
//! * `syslog` - System logging
|
||||
//! * `term` - Terminal control APIs
|
||||
//! * `time` - Query the operating system's clocks
|
||||
//! * `ucontext` - User thread context
|
||||
@@ -43,9 +44,12 @@
|
||||
#![crate_name = "nix"]
|
||||
#![cfg(unix)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![cfg_attr(test, deny(warnings))]
|
||||
// A clear document is a good document no matter if it has a summary in its
|
||||
// first paragraph or not.
|
||||
#![allow(clippy::too_long_first_doc_paragraph)]
|
||||
#![recursion_limit = "500"]
|
||||
#![deny(unused)]
|
||||
#![deny(unexpected_cfgs)]
|
||||
#![allow(unused_macros)]
|
||||
#![cfg_attr(
|
||||
not(all(
|
||||
@@ -76,6 +80,7 @@
|
||||
feature = "sched",
|
||||
feature = "socket",
|
||||
feature = "signal",
|
||||
feature = "syslog",
|
||||
feature = "term",
|
||||
feature = "time",
|
||||
feature = "ucontext",
|
||||
@@ -92,6 +97,11 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![deny(clippy::cast_ptr_alignment)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
// I found the change suggested by this rules could hurt code readability. I cannot
|
||||
// remeber every type's default value, in such cases, it forces me to open
|
||||
// the std doc to insepct the Default value, which is unnecessary with
|
||||
// `.unwrap_or(value)`.
|
||||
#![allow(clippy::unwrap_or_default)]
|
||||
|
||||
// Re-exported external crates
|
||||
pub use libc;
|
||||
@@ -140,7 +150,11 @@ feature! {
|
||||
#![feature = "mount"]
|
||||
pub mod mount;
|
||||
}
|
||||
#[cfg(any(freebsdlike, target_os = "linux", target_os = "netbsd"))]
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
all(target_os = "linux", not(target_env = "ohos")),
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
feature! {
|
||||
#![feature = "mqueue"]
|
||||
pub mod mqueue;
|
||||
@@ -185,6 +199,23 @@ pub mod unistd;
|
||||
#[cfg(any(feature = "poll", feature = "event"))]
|
||||
mod poll_timeout;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
apple_targets
|
||||
))]
|
||||
feature! {
|
||||
#![feature = "process"]
|
||||
pub mod spawn;
|
||||
}
|
||||
|
||||
feature! {
|
||||
#![feature = "syslog"]
|
||||
pub mod syslog;
|
||||
}
|
||||
|
||||
use std::ffi::{CStr, CString, OsStr};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
@@ -205,7 +236,7 @@ pub type Result<T> = result::Result<T, Errno>;
|
||||
/// * `Eq`
|
||||
/// * Small size
|
||||
/// * Represents all of the system's errnos, instead of just the most common
|
||||
/// ones.
|
||||
/// ones.
|
||||
pub type Error = Errno;
|
||||
|
||||
/// Common trait used to represent file system paths by many Nix functions.
|
||||
@@ -289,7 +320,7 @@ impl NixPath for [u8] {
|
||||
F: FnOnce(&CStr) -> T,
|
||||
{
|
||||
// The real PATH_MAX is typically 4096, but it's statistically unlikely to have a path
|
||||
// longer than ~300 bytes. See the the PR description to get stats for your own machine.
|
||||
// longer than ~300 bytes. See the PR description to get stats for your own machine.
|
||||
// https://github.com/nix-rust/nix/pull/1656
|
||||
//
|
||||
// By being smaller than a memory page, we also avoid the compiler inserting a probe frame:
|
||||
|
||||
@@ -387,7 +387,7 @@ impl<'a> Nmount<'a> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
impl<'a> Drop for Nmount<'a> {
|
||||
impl Drop for Nmount<'_> {
|
||||
fn drop(&mut self) {
|
||||
for (iov, is_owned) in self.iov.iter().zip(self.is_owned.iter()) {
|
||||
if *is_owned {
|
||||
|
||||
8
third_party/rust/nix/src/mqueue.rs
vendored
8
third_party/rust/nix/src/mqueue.rs
vendored
@@ -260,9 +260,11 @@ pub fn mq_getattr(mqd: &MqdT) -> Result<MqAttr> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
|
||||
/// Returns the old attributes
|
||||
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
|
||||
/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set,
|
||||
/// everything else will be ignored. Returns the old attributes.
|
||||
///
|
||||
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()`
|
||||
/// convenience functions as they are easier to use.
|
||||
///
|
||||
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
|
||||
pub fn mq_setattr(mqd: &MqdT, newattr: &MqAttr) -> Result<MqAttr> {
|
||||
|
||||
13
third_party/rust/nix/src/net/if_.rs
vendored
13
third_party/rust/nix/src/net/if_.rs
vendored
@@ -51,7 +51,7 @@ libc_bitflags!(
|
||||
IFF_BROADCAST as IflagsType;
|
||||
/// Internal debugging flag. (see
|
||||
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "cygwin")))]
|
||||
IFF_DEBUG as IflagsType;
|
||||
/// Interface is a loopback interface. (see
|
||||
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
|
||||
@@ -66,7 +66,8 @@ libc_bitflags!(
|
||||
solarish,
|
||||
apple_targets,
|
||||
target_os = "fuchsia",
|
||||
target_os = "netbsd"))]
|
||||
target_os = "netbsd",
|
||||
target_os = "cygwin"))]
|
||||
IFF_NOTRAILERS as IflagsType;
|
||||
/// Interface manages own routes.
|
||||
#[cfg(any(target_os = "dragonfly"))]
|
||||
@@ -77,7 +78,8 @@ libc_bitflags!(
|
||||
linux_android,
|
||||
bsd,
|
||||
solarish,
|
||||
target_os = "fuchsia"))]
|
||||
target_os = "fuchsia",
|
||||
target_os = "cygwin"))]
|
||||
IFF_RUNNING as IflagsType;
|
||||
/// No arp protocol, L2 destination address not set. (see
|
||||
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
|
||||
@@ -87,6 +89,7 @@ libc_bitflags!(
|
||||
IFF_PROMISC as IflagsType;
|
||||
/// Receive all multicast packets. (see
|
||||
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
|
||||
#[cfg(not(target_os = "cygwin"))]
|
||||
IFF_ALLMULTI as IflagsType;
|
||||
/// Master of a load balancing bundle. (see
|
||||
/// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
|
||||
@@ -145,7 +148,7 @@ libc_bitflags!(
|
||||
#[cfg(solarish)]
|
||||
IFF_PRIVATE as IflagsType;
|
||||
/// Driver signals L1 up. Volatile.
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "linux", target_os = "cygwin"))]
|
||||
IFF_LOWER_UP;
|
||||
/// Interface is in polling mode.
|
||||
#[cfg(any(target_os = "dragonfly"))]
|
||||
@@ -157,7 +160,7 @@ libc_bitflags!(
|
||||
#[cfg(solarish)]
|
||||
IFF_NOXMIT as IflagsType;
|
||||
/// Driver signals dormant. Volatile.
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "linux", target_os = "cygwin"))]
|
||||
IFF_DORMANT;
|
||||
/// User-requested promisc mode.
|
||||
#[cfg(freebsdlike)]
|
||||
|
||||
53
third_party/rust/nix/src/poll.rs
vendored
53
third_party/rust/nix/src/poll.rs
vendored
@@ -2,7 +2,7 @@
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd};
|
||||
|
||||
use crate::errno::Errno;
|
||||
pub use crate::poll_timeout::PollTimeout;
|
||||
pub use crate::poll_timeout::{PollTimeout, PollTimeoutTryFromError};
|
||||
use crate::Result;
|
||||
|
||||
/// This is a wrapper around `libc::pollfd`.
|
||||
@@ -11,10 +11,10 @@ use crate::Result;
|
||||
/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest
|
||||
/// for a specific file descriptor.
|
||||
///
|
||||
/// After a call to `poll` or `ppoll`, the events that occurred can be
|
||||
/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
|
||||
/// After a call to `poll` or `ppoll`, the events that occurred can be retrieved by calling
|
||||
/// [`revents()`](#method.revents) on the `PollFd` object from the array passed to `poll`.
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct PollFd<'fd> {
|
||||
pollfd: libc::pollfd,
|
||||
_fd: std::marker::PhantomData<BorrowedFd<'fd>>,
|
||||
@@ -33,11 +33,8 @@ impl<'fd> PollFd<'fd> {
|
||||
/// # };
|
||||
/// let (r, w) = pipe().unwrap();
|
||||
/// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN);
|
||||
/// let mut fds = [pfd];
|
||||
/// poll(&mut fds, PollTimeout::NONE).unwrap();
|
||||
/// let mut buf = [0u8; 80];
|
||||
/// read(r.as_raw_fd(), &mut buf[..]);
|
||||
/// ```
|
||||
/// These are placed in an array and passed to [`poll`] or [`ppoll`](fn.ppoll.html).
|
||||
// Unlike I/O functions, constructors like this must take `BorrowedFd`
|
||||
// instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be
|
||||
// dropped at the end of the method, leaving the structure referencing a
|
||||
@@ -61,7 +58,7 @@ impl<'fd> PollFd<'fd> {
|
||||
|
||||
/// Returns the events that occurred in the last call to `poll` or `ppoll`. Will only return
|
||||
/// `None` if the kernel provides status flags that Nix does not know about.
|
||||
pub fn revents(self) -> Option<PollFlags> {
|
||||
pub fn revents(&self) -> Option<PollFlags> {
|
||||
PollFlags::from_bits(self.pollfd.revents)
|
||||
}
|
||||
|
||||
@@ -71,7 +68,7 @@ impl<'fd> PollFd<'fd> {
|
||||
/// Equivalent to `x.revents()? != PollFlags::empty()`.
|
||||
///
|
||||
/// This is marginally more efficient than [`PollFd::all`].
|
||||
pub fn any(self) -> Option<bool> {
|
||||
pub fn any(&self) -> Option<bool> {
|
||||
Some(self.revents()? != PollFlags::empty())
|
||||
}
|
||||
|
||||
@@ -81,12 +78,12 @@ impl<'fd> PollFd<'fd> {
|
||||
/// Equivalent to `x.revents()? & x.events() == x.events()`.
|
||||
///
|
||||
/// This is marginally less efficient than [`PollFd::any`].
|
||||
pub fn all(self) -> Option<bool> {
|
||||
pub fn all(&self) -> Option<bool> {
|
||||
Some(self.revents()? & self.events() == self.events())
|
||||
}
|
||||
|
||||
/// The events of interest for this `PollFd`.
|
||||
pub fn events(self) -> PollFlags {
|
||||
pub fn events(&self) -> PollFlags {
|
||||
PollFlags::from_bits(self.pollfd.events).unwrap()
|
||||
}
|
||||
|
||||
@@ -96,7 +93,7 @@ impl<'fd> PollFd<'fd> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'fd> AsFd for PollFd<'fd> {
|
||||
impl AsFd for PollFd<'_> {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
// Safety:
|
||||
//
|
||||
@@ -196,6 +193,34 @@ libc_bitflags! {
|
||||
/// in timeout means an infinite timeout. Specifying a timeout of
|
||||
/// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file
|
||||
/// descriptors are ready.
|
||||
///
|
||||
/// The return value contains the number of `fds` which have selected events ([`PollFd::revents`]).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```no_run
|
||||
/// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd};
|
||||
/// # use nix::{
|
||||
/// # poll::{PollTimeout, PollFd, PollFlags, poll},
|
||||
/// # unistd::{pipe, read}
|
||||
/// # };
|
||||
/// let (r0, w0) = pipe().unwrap();
|
||||
/// let (r1, w1) = pipe().unwrap();
|
||||
///
|
||||
/// let mut pollfds = [
|
||||
/// PollFd::new(r0.as_fd(), PollFlags::POLLIN),
|
||||
/// PollFd::new(r1.as_fd(), PollFlags::POLLIN),
|
||||
/// ];
|
||||
///
|
||||
/// let nready = poll(&mut pollfds, PollTimeout::NONE).unwrap();
|
||||
/// assert!(nready >= 1); // Since there is no timeout
|
||||
///
|
||||
/// let mut buf = [0u8; 80];
|
||||
/// if pollfds[0].any().unwrap_or_default() {
|
||||
/// read(&r0, &mut buf[..]);
|
||||
/// } else if pollfds[1].any().unwrap_or_default() {
|
||||
/// read(&r1, &mut buf[..]);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn poll<T: Into<PollTimeout>>(
|
||||
fds: &mut [PollFd],
|
||||
timeout: T,
|
||||
@@ -217,7 +242,7 @@ feature! {
|
||||
/// descriptor becomes ready or until a signal is caught.
|
||||
/// ([`poll(2)`](https://man7.org/linux/man-pages/man2/poll.2.html))
|
||||
///
|
||||
/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
|
||||
/// `ppoll` behaves like [`poll`], but let you specify what signals may interrupt it
|
||||
/// with the `sigmask` argument. If you want `ppoll` to block indefinitely,
|
||||
/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`).
|
||||
/// If `sigmask` is `None`, then no signal mask manipulation is performed,
|
||||
|
||||
27
third_party/rust/nix/src/pty.rs
vendored
27
third_party/rust/nix/src/pty.rs
vendored
@@ -52,6 +52,17 @@ pub enum ForkptyResult {
|
||||
#[derive(Debug)]
|
||||
pub struct PtyMaster(OwnedFd);
|
||||
|
||||
impl PtyMaster {
|
||||
/// Constructs a `PytMaster` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid `PtyMaster`.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for PtyMaster {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
@@ -64,6 +75,12 @@ impl AsFd for PtyMaster {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PtyMaster> for OwnedFd {
|
||||
fn from(value: PtyMaster) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for PtyMaster {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
let fd = self.0;
|
||||
@@ -73,7 +90,7 @@ impl IntoRawFd for PtyMaster {
|
||||
|
||||
impl io::Read for PtyMaster {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
|
||||
unistd::read(&self.0, buf).map_err(io::Error::from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +105,7 @@ impl io::Write for PtyMaster {
|
||||
|
||||
impl io::Read for &PtyMaster {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
|
||||
unistd::read(&self.0, buf).map_err(io::Error::from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,9 +334,9 @@ feature! {
|
||||
/// # Safety
|
||||
///
|
||||
/// In a multithreaded program, only [async-signal-safe] functions like `pause`
|
||||
/// and `_exit` may be called by the child (the parent isn't restricted). Note
|
||||
/// that memory allocation may **not** be async-signal-safe and thus must be
|
||||
/// prevented.
|
||||
/// and `_exit` may be called by the child (the parent isn't restricted) until
|
||||
/// a call of `execve(2)`. Note that memory allocation may **not** be
|
||||
/// async-signal-safe and thus must be prevented.
|
||||
///
|
||||
/// Those functions are only a small subset of your operating system's API, so
|
||||
/// special care must be taken to only invoke code you can control and audit.
|
||||
|
||||
5
third_party/rust/nix/src/sched.rs
vendored
5
third_party/rust/nix/src/sched.rs
vendored
@@ -120,7 +120,10 @@ mod sched_linux_like {
|
||||
let ptr = stack.as_mut_ptr().add(stack.len());
|
||||
let ptr_aligned = ptr.sub(ptr as usize % 16);
|
||||
libc::clone(
|
||||
mem::transmute(
|
||||
mem::transmute::<
|
||||
extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
|
||||
extern "C" fn(*mut libc::c_void) -> i32,
|
||||
>(
|
||||
callback
|
||||
as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
|
||||
),
|
||||
|
||||
431
third_party/rust/nix/src/spawn.rs
vendored
Normal file
431
third_party/rust/nix/src/spawn.rs
vendored
Normal file
@@ -0,0 +1,431 @@
|
||||
//! Safe wrappers around posix_spawn* functions found in the libc "spawn.h" header.
|
||||
|
||||
use std::{ffi::CStr, mem, os::fd::RawFd};
|
||||
|
||||
#[cfg(any(feature = "fs", feature = "term"))]
|
||||
use crate::fcntl::OFlag;
|
||||
#[cfg(feature = "signal")]
|
||||
use crate::sys::signal::SigSet;
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::sys::stat::Mode;
|
||||
use crate::{errno::Errno, unistd::Pid, NixPath, Result};
|
||||
|
||||
/// A spawn attributes object. See [posix_spawnattr_t](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_init.html).
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct PosixSpawnAttr {
|
||||
attr: libc::posix_spawnattr_t,
|
||||
}
|
||||
|
||||
impl PosixSpawnAttr {
|
||||
/// Initialize the spawn attributes object. See
|
||||
/// [posix_spawnattr_init](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_init.html).
|
||||
#[doc(alias("posix_spawnattr_init"))]
|
||||
pub fn init() -> Result<PosixSpawnAttr> {
|
||||
let mut attr = mem::MaybeUninit::uninit();
|
||||
let res = unsafe { libc::posix_spawnattr_init(attr.as_mut_ptr()) };
|
||||
|
||||
Errno::result(res)?;
|
||||
|
||||
let attr = unsafe { attr.assume_init() };
|
||||
Ok(PosixSpawnAttr { attr })
|
||||
}
|
||||
|
||||
/// Reinitialize the spawn attributes object.
|
||||
/// This is a wrapper around
|
||||
/// [posix_spawnattr_destroy](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_destroy.html)
|
||||
/// followed by
|
||||
/// [posix_spawnattr_init](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_init.html).
|
||||
#[doc(alias("posix_spawnattr_destroy"))]
|
||||
pub fn reinit(mut self) -> Result<PosixSpawnAttr> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_destroy(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_init(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Set spawn flags. See
|
||||
/// [posix_spawnattr_setflags](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setflags.html).
|
||||
#[doc(alias("posix_spawnattr_setflags"))]
|
||||
pub fn set_flags(&mut self, flags: PosixSpawnFlags) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_setflags(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
flags.bits() as libc::c_short,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get spawn flags. See
|
||||
/// [posix_spawnattr_getflags](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getflags.html).
|
||||
#[doc(alias("posix_spawnattr_getflags"))]
|
||||
pub fn flags(&self) -> Result<PosixSpawnFlags> {
|
||||
let mut flags: libc::c_short = 0;
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_getflags(
|
||||
&self.attr as *const libc::posix_spawnattr_t,
|
||||
&mut flags,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(PosixSpawnFlags::from_bits_truncate(flags.into()))
|
||||
}
|
||||
|
||||
/// Set spawn pgroup. See
|
||||
/// [posix_spawnattr_setpgroup](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setpgroup.html).
|
||||
#[doc(alias("posix_spawnattr_setpgroup"))]
|
||||
pub fn set_pgroup(&mut self, pgroup: Pid) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_setpgroup(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
pgroup.as_raw(),
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get spawn pgroup. See
|
||||
/// [posix_spawnattr_getpgroup](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getpgroup.html).
|
||||
#[doc(alias("posix_spawnattr_getpgroup"))]
|
||||
pub fn pgroup(&self) -> Result<Pid> {
|
||||
let mut pid: libc::pid_t = 0;
|
||||
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_getpgroup(
|
||||
&self.attr as *const libc::posix_spawnattr_t,
|
||||
&mut pid,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(Pid::from_raw(pid))
|
||||
}
|
||||
|
||||
feature! {
|
||||
#![feature = "signal"]
|
||||
/// Set spawn sigdefault. See
|
||||
/// [posix_spawnattr_setsigdefault](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setsigdefault.html).
|
||||
#[doc(alias("posix_spawnattr_setsigdefault"))]
|
||||
pub fn set_sigdefault(&mut self, sigdefault: &SigSet) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_setsigdefault(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
sigdefault.as_ref(),
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get spawn sigdefault. See
|
||||
/// [posix_spawnattr_getsigdefault](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getsigdefault.html).
|
||||
#[doc(alias("posix_spawnattr_getsigdefault"))]
|
||||
pub fn sigdefault(&self) -> Result<SigSet> {
|
||||
let mut sigset = mem::MaybeUninit::uninit();
|
||||
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_getsigdefault(
|
||||
&self.attr as *const libc::posix_spawnattr_t,
|
||||
sigset.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
let sigdefault =
|
||||
unsafe { SigSet::from_sigset_t_unchecked(sigset.assume_init()) };
|
||||
Ok(sigdefault)
|
||||
}
|
||||
|
||||
/// Set spawn sigmask. See
|
||||
/// [posix_spawnattr_setsigmask](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setsigmask.html).
|
||||
#[doc(alias("posix_spawnattr_setsigmask"))]
|
||||
pub fn set_sigmask(&mut self, sigdefault: &SigSet) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_setsigmask(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
sigdefault.as_ref(),
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get spawn sigmask. See
|
||||
/// [posix_spawnattr_getsigmask](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_getsigmask.html).
|
||||
#[doc(alias("posix_spawnattr_getsigmask"))]
|
||||
pub fn sigmask(&self) -> Result<SigSet> {
|
||||
let mut sigset = mem::MaybeUninit::uninit();
|
||||
|
||||
let res = unsafe {
|
||||
libc::posix_spawnattr_getsigmask(
|
||||
&self.attr as *const libc::posix_spawnattr_t,
|
||||
sigset.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
let sigdefault =
|
||||
unsafe { SigSet::from_sigset_t_unchecked(sigset.assume_init()) };
|
||||
Ok(sigdefault)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PosixSpawnAttr {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
libc::posix_spawnattr_destroy(
|
||||
&mut self.attr as *mut libc::posix_spawnattr_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libc_bitflags!(
|
||||
/// Process attributes to be changed in the new process image when invoking [`posix_spawn`]
|
||||
/// or [`posix_spawnp`]. See
|
||||
/// [posix_spawn](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html).
|
||||
pub struct PosixSpawnFlags: libc::c_int {
|
||||
/// Reset effective user ID of the child process to parent's real user ID.
|
||||
POSIX_SPAWN_RESETIDS;
|
||||
/// Put the child in a process group specified by the spawn-pgroup attribute. See
|
||||
/// [posix_spawnattr_setpgroup](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setpgroup.html).
|
||||
POSIX_SPAWN_SETPGROUP;
|
||||
/// Force set signals to default signal handling in child process. See
|
||||
/// [posix_spawnattr_setsigdefault](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setsigdefault.html).
|
||||
#[cfg(feature = "signal")]
|
||||
POSIX_SPAWN_SETSIGDEF;
|
||||
/// Set signal mask of child process. See
|
||||
/// [posix_spawnattr_setsigmask](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnattr_setsigmask.html).
|
||||
#[cfg(feature = "signal")]
|
||||
POSIX_SPAWN_SETSIGMASK;
|
||||
// TODO: Add support for the following two flags whenever support for
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html
|
||||
// is added to nix.
|
||||
// POSIX_SPAWN_SETSCHEDPARAM;
|
||||
// POSIX_SPAWN_SETSCHEDULER;
|
||||
}
|
||||
);
|
||||
|
||||
/// A spawn file actions object. See [posix_spawn_file_actions_t](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_addclose.html).
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct PosixSpawnFileActions {
|
||||
fa: libc::posix_spawn_file_actions_t,
|
||||
}
|
||||
|
||||
impl PosixSpawnFileActions {
|
||||
/// Initialize the spawn file actions object. See
|
||||
/// [posix_spawn_file_actions_init](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_init.html).
|
||||
#[doc(alias("posix_spawn_file_actions_init"))]
|
||||
pub fn init() -> Result<PosixSpawnFileActions> {
|
||||
let mut actions = mem::MaybeUninit::uninit();
|
||||
let res = unsafe {
|
||||
libc::posix_spawn_file_actions_init(actions.as_mut_ptr())
|
||||
};
|
||||
Errno::result(res)?;
|
||||
Ok(unsafe {
|
||||
PosixSpawnFileActions {
|
||||
fa: actions.assume_init(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Reinitialize the spawn file actions object.
|
||||
/// This is a wrapper around
|
||||
/// [posix_spawn_file_actions_destroy](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_destroy.html).
|
||||
/// followed by
|
||||
/// [posix_spawn_file_actions_init](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_init.html).
|
||||
#[doc(alias("posix_spawn_file_actions_destroy"))]
|
||||
pub fn reinit(mut self) -> Result<PosixSpawnFileActions> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawn_file_actions_destroy(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
let res = unsafe {
|
||||
libc::posix_spawn_file_actions_init(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Add a [dup2](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html) action. See
|
||||
/// [posix_spawn_file_actions_adddup2](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_adddup2.html).
|
||||
#[doc(alias("posix_spawn_file_actions_adddup2"))]
|
||||
pub fn add_dup2(&mut self, fd: RawFd, newfd: RawFd) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawn_file_actions_adddup2(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
fd,
|
||||
newfd,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
feature! {
|
||||
#![all(feature = "fs", feature = "term")]
|
||||
/// Add an open action. See
|
||||
/// [posix_spawn_file_actions_addopen](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_addopen.html).
|
||||
#[doc(alias("posix_spawn_file_actions_addopen"))]
|
||||
pub fn add_open<P: ?Sized + NixPath>(
|
||||
&mut self,
|
||||
fd: RawFd,
|
||||
path: &P,
|
||||
oflag: OFlag,
|
||||
mode: Mode,
|
||||
) -> Result<()> {
|
||||
let res = path.with_nix_path(|cstr| unsafe {
|
||||
libc::posix_spawn_file_actions_addopen(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
fd,
|
||||
cstr.as_ptr(),
|
||||
oflag.bits(),
|
||||
mode.bits(),
|
||||
)
|
||||
})?;
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a close action. See
|
||||
/// [posix_spawn_file_actions_addclose](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn_file_actions_addclose.html).
|
||||
#[doc(alias("posix_spawn_file_actions_addclose"))]
|
||||
pub fn add_close(&mut self, fd: RawFd) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::posix_spawn_file_actions_addclose(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
fd,
|
||||
)
|
||||
};
|
||||
Errno::result(res)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PosixSpawnFileActions {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
libc::posix_spawn_file_actions_destroy(
|
||||
&mut self.fa as *mut libc::posix_spawn_file_actions_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The POSIX standard requires those `args` and `envp` to be of type `*const *mut [c_char]`,
|
||||
// but implementations won't modify them, making the `mut` type redundant. Considering this,
|
||||
// Nix does not expose this mutability, but we have to change the interface when calling the
|
||||
// underlying libc interfaces , this helper function does the conversion job.
|
||||
//
|
||||
// SAFETY:
|
||||
// It is safe to add the mutability in types as implementations won't mutable them.
|
||||
unsafe fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*mut libc::c_char> {
|
||||
let mut v: Vec<*mut libc::c_char> = args
|
||||
.iter()
|
||||
.map(|s| s.as_ref().as_ptr().cast_mut())
|
||||
.collect();
|
||||
v.push(std::ptr::null_mut());
|
||||
v
|
||||
}
|
||||
|
||||
/// Create a new child process from the specified process image. See
|
||||
/// [posix_spawn](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html).
|
||||
pub fn posix_spawn<P, SA, SE>(
|
||||
path: &P,
|
||||
file_actions: &PosixSpawnFileActions,
|
||||
attr: &PosixSpawnAttr,
|
||||
args: &[SA],
|
||||
envp: &[SE],
|
||||
) -> Result<Pid>
|
||||
where
|
||||
P: NixPath + ?Sized,
|
||||
SA: AsRef<CStr>,
|
||||
SE: AsRef<CStr>,
|
||||
{
|
||||
let mut pid = 0;
|
||||
|
||||
let ret = unsafe {
|
||||
let args_p = to_exec_array(args);
|
||||
let env_p = to_exec_array(envp);
|
||||
|
||||
path.with_nix_path(|c_str| {
|
||||
libc::posix_spawn(
|
||||
&mut pid as *mut libc::pid_t,
|
||||
c_str.as_ptr(),
|
||||
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
|
||||
&attr.attr as *const libc::posix_spawnattr_t,
|
||||
args_p.as_ptr(),
|
||||
env_p.as_ptr(),
|
||||
)
|
||||
})?
|
||||
};
|
||||
|
||||
if ret != 0 {
|
||||
return Err(Errno::from_raw(ret));
|
||||
}
|
||||
|
||||
Ok(Pid::from_raw(pid))
|
||||
}
|
||||
|
||||
/// Create a new child process from the specified process image. See
|
||||
/// [posix_spawnp](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawnp.html).
|
||||
pub fn posix_spawnp<SA: AsRef<CStr>, SE: AsRef<CStr>>(
|
||||
path: &CStr,
|
||||
file_actions: &PosixSpawnFileActions,
|
||||
attr: &PosixSpawnAttr,
|
||||
args: &[SA],
|
||||
envp: &[SE],
|
||||
) -> Result<Pid> {
|
||||
let mut pid = 0;
|
||||
|
||||
let ret = unsafe {
|
||||
let args_p = to_exec_array(args);
|
||||
let env_p = to_exec_array(envp);
|
||||
|
||||
libc::posix_spawnp(
|
||||
&mut pid as *mut libc::pid_t,
|
||||
path.as_ptr(),
|
||||
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
|
||||
&attr.attr as *const libc::posix_spawnattr_t,
|
||||
args_p.as_ptr(),
|
||||
env_p.as_ptr(),
|
||||
)
|
||||
};
|
||||
|
||||
if ret != 0 {
|
||||
return Err(Errno::from_raw(ret));
|
||||
}
|
||||
|
||||
Ok(Pid::from_raw(pid))
|
||||
}
|
||||
45
third_party/rust/nix/src/sys/aio.rs
vendored
45
third_party/rust/nix/src/sys/aio.rs
vendored
@@ -193,7 +193,7 @@ impl<'a> AioCb<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for AioCb<'a> {
|
||||
impl Debug for AioCb<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("AioCb")
|
||||
.field("aiocb", &self.aiocb.0)
|
||||
@@ -202,7 +202,7 @@ impl<'a> Debug for AioCb<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for AioCb<'a> {
|
||||
impl Drop for AioCb<'_> {
|
||||
/// If the `AioCb` has no remaining state in the kernel, just drop it.
|
||||
/// Otherwise, dropping constitutes a resource leak, which is an error
|
||||
fn drop(&mut self) {
|
||||
@@ -455,10 +455,9 @@ impl<'a> AioFsync<'a> {
|
||||
/// * `fd`: File descriptor to sync.
|
||||
/// * `mode`: Whether to sync file metadata too, or just data.
|
||||
/// * `prio`: If POSIX Prioritized IO is supported, then the
|
||||
/// operation will be prioritized at the process's
|
||||
/// priority level minus `prio`.
|
||||
/// * `sigev_notify`: Determines how you will be notified of event
|
||||
/// completion.
|
||||
/// operation will be prioritized at the process's priority level minus
|
||||
/// `prio`.
|
||||
/// * `sigev_notify`: Determines how you will be notified of event completion.
|
||||
pub fn new(
|
||||
fd: BorrowedFd<'a>,
|
||||
mode: AioFsyncMode,
|
||||
@@ -499,7 +498,7 @@ impl<'a> Aio for AioFsync<'a> {
|
||||
|
||||
// AioFsync does not need AsMut, since it can't be used with lio_listio
|
||||
|
||||
impl<'a> AsRef<libc::aiocb> for AioFsync<'a> {
|
||||
impl AsRef<libc::aiocb> for AioFsync<'_> {
|
||||
fn as_ref(&self) -> &libc::aiocb {
|
||||
&self.aiocb.aiocb.0
|
||||
}
|
||||
@@ -573,11 +572,9 @@ impl<'a> AioRead<'a> {
|
||||
/// * `fd`: File descriptor to read from
|
||||
/// * `offs`: File offset
|
||||
/// * `buf`: A memory buffer. It must outlive the `AioRead`.
|
||||
/// * `prio`: If POSIX Prioritized IO is supported, then the
|
||||
/// operation will be prioritized at the process's
|
||||
/// priority level minus `prio`
|
||||
/// * `sigev_notify`: Determines how you will be notified of event
|
||||
/// completion.
|
||||
/// * `prio`: If POSIX Prioritized IO is supported, then the operation
|
||||
/// will be prioritized at the process's priority level minus `prio`
|
||||
/// * `sigev_notify`: Determines how you will be notified of event completion.
|
||||
pub fn new(
|
||||
fd: BorrowedFd<'a>,
|
||||
offs: off_t,
|
||||
@@ -609,13 +606,13 @@ impl<'a> Aio for AioRead<'a> {
|
||||
aio_methods!(aio_read);
|
||||
}
|
||||
|
||||
impl<'a> AsMut<libc::aiocb> for AioRead<'a> {
|
||||
impl AsMut<libc::aiocb> for AioRead<'_> {
|
||||
fn as_mut(&mut self) -> &mut libc::aiocb {
|
||||
&mut self.aiocb.aiocb.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRef<libc::aiocb> for AioRead<'a> {
|
||||
impl AsRef<libc::aiocb> for AioRead<'_> {
|
||||
fn as_ref(&self) -> &libc::aiocb {
|
||||
&self.aiocb.aiocb.0
|
||||
}
|
||||
@@ -732,14 +729,14 @@ impl<'a> Aio for AioReadv<'a> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
impl<'a> AsMut<libc::aiocb> for AioReadv<'a> {
|
||||
impl AsMut<libc::aiocb> for AioReadv<'_> {
|
||||
fn as_mut(&mut self) -> &mut libc::aiocb {
|
||||
&mut self.aiocb.aiocb.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
impl<'a> AsRef<libc::aiocb> for AioReadv<'a> {
|
||||
impl AsRef<libc::aiocb> for AioReadv<'_> {
|
||||
fn as_ref(&self) -> &libc::aiocb {
|
||||
&self.aiocb.aiocb.0
|
||||
}
|
||||
@@ -805,11 +802,9 @@ impl<'a> AioWrite<'a> {
|
||||
/// * `fd`: File descriptor to write to
|
||||
/// * `offs`: File offset
|
||||
/// * `buf`: A memory buffer. It must outlive the `AioWrite`.
|
||||
/// * `prio`: If POSIX Prioritized IO is supported, then the
|
||||
/// operation will be prioritized at the process's
|
||||
/// priority level minus `prio`
|
||||
/// * `sigev_notify`: Determines how you will be notified of event
|
||||
/// completion.
|
||||
/// * `prio`: If POSIX Prioritized IO is supported, then the operation
|
||||
/// will be prioritized at the process's priority level minus `prio`
|
||||
/// * `sigev_notify`: Determines how you will be notified of event completion.
|
||||
pub fn new(
|
||||
fd: BorrowedFd<'a>,
|
||||
offs: off_t,
|
||||
@@ -845,13 +840,13 @@ impl<'a> Aio for AioWrite<'a> {
|
||||
aio_methods!(aio_write);
|
||||
}
|
||||
|
||||
impl<'a> AsMut<libc::aiocb> for AioWrite<'a> {
|
||||
impl AsMut<libc::aiocb> for AioWrite<'_> {
|
||||
fn as_mut(&mut self) -> &mut libc::aiocb {
|
||||
&mut self.aiocb.aiocb.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRef<libc::aiocb> for AioWrite<'a> {
|
||||
impl AsRef<libc::aiocb> for AioWrite<'_> {
|
||||
fn as_ref(&self) -> &libc::aiocb {
|
||||
&self.aiocb.aiocb.0
|
||||
}
|
||||
@@ -965,14 +960,14 @@ impl<'a> Aio for AioWritev<'a> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
impl<'a> AsMut<libc::aiocb> for AioWritev<'a> {
|
||||
impl AsMut<libc::aiocb> for AioWritev<'_> {
|
||||
fn as_mut(&mut self) -> &mut libc::aiocb {
|
||||
&mut self.aiocb.aiocb.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
impl<'a> AsRef<libc::aiocb> for AioWritev<'a> {
|
||||
impl AsRef<libc::aiocb> for AioWritev<'_> {
|
||||
fn as_ref(&self) -> &libc::aiocb {
|
||||
&self.aiocb.aiocb.0
|
||||
}
|
||||
|
||||
8
third_party/rust/nix/src/sys/epoll.rs
vendored
8
third_party/rust/nix/src/sys/epoll.rs
vendored
@@ -1,5 +1,6 @@
|
||||
use crate::errno::Errno;
|
||||
pub use crate::poll_timeout::PollTimeout as EpollTimeout;
|
||||
pub use crate::poll_timeout::PollTimeoutTryFromError as EpollTimeoutTryFromError;
|
||||
use crate::Result;
|
||||
use libc::{self, c_int};
|
||||
use std::mem;
|
||||
@@ -88,7 +89,7 @@ impl EpollEvent {
|
||||
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
|
||||
///
|
||||
/// // Arm eventfd & Time wait
|
||||
/// eventfd.arm()?;
|
||||
/// eventfd.write(1)?;
|
||||
/// let now = Instant::now();
|
||||
///
|
||||
/// // Wait on event
|
||||
@@ -205,7 +206,10 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
|
||||
Errno::result(res)
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.27.0", note = "Use Epoll::epoll_ctl() instead")]
|
||||
#[deprecated(
|
||||
since = "0.27.0",
|
||||
note = "Use corresponding Epoll methods instead"
|
||||
)]
|
||||
#[inline]
|
||||
pub fn epoll_ctl<'a, T>(
|
||||
epfd: RawFd,
|
||||
|
||||
14
third_party/rust/nix/src/sys/event.rs
vendored
14
third_party/rust/nix/src/sys/event.rs
vendored
@@ -173,7 +173,7 @@ 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 {
|
||||
pub struct EvFlags: type_of_event_flag {
|
||||
#[allow(missing_docs)]
|
||||
EV_ADD;
|
||||
#[allow(missing_docs)]
|
||||
@@ -216,6 +216,10 @@ libc_bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.30.0", note = "Use `EvFlags instead`")]
|
||||
/// The deprecated EventFlag type alias
|
||||
pub type EventFlag = EvFlags;
|
||||
|
||||
libc_bitflags!(
|
||||
/// Filter-specific flags. See the man page for details.
|
||||
// There's no useful documentation we can write for the individual flags
|
||||
@@ -347,7 +351,7 @@ impl KEvent {
|
||||
pub fn new(
|
||||
ident: uintptr_t,
|
||||
filter: EventFilter,
|
||||
flags: EventFlag,
|
||||
flags: EvFlags,
|
||||
fflags: FilterFlag,
|
||||
data: intptr_t,
|
||||
udata: intptr_t,
|
||||
@@ -382,8 +386,8 @@ impl KEvent {
|
||||
|
||||
/// 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()
|
||||
pub fn flags(&self) -> EvFlags {
|
||||
EvFlags::from_bits(self.kevent.flags).unwrap()
|
||||
}
|
||||
|
||||
/// Filter-specific flags.
|
||||
@@ -443,7 +447,7 @@ pub fn ev_set(
|
||||
ev: &mut KEvent,
|
||||
ident: usize,
|
||||
filter: EventFilter,
|
||||
flags: EventFlag,
|
||||
flags: EvFlags,
|
||||
fflags: FilterFlag,
|
||||
udata: intptr_t,
|
||||
) {
|
||||
|
||||
84
third_party/rust/nix/src/sys/eventfd.rs
vendored
84
third_party/rust/nix/src/sys/eventfd.rs
vendored
@@ -1,69 +1,102 @@
|
||||
use crate::errno::Errno;
|
||||
use crate::{Result,unistd};
|
||||
use std::os::unix::io::{FromRawFd, OwnedFd, AsRawFd, AsFd, RawFd, BorrowedFd};
|
||||
use crate::{unistd, Result};
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
|
||||
|
||||
libc_bitflags! {
|
||||
/// Eventfd flags.
|
||||
pub struct EfdFlags: libc::c_int {
|
||||
/// Set the close-on-exec (`FD_CLOEXEC`) flag on the new event file descriptor.
|
||||
EFD_CLOEXEC; // Since Linux 2.6.27/FreeBSD 13.0
|
||||
/// Set the `O_NONBLOCK` file status flag on the new event file description.
|
||||
EFD_NONBLOCK; // Since Linux 2.6.27/FreeBSD 13.0
|
||||
/// Provide semaphore-like semantics for reads from the new event file
|
||||
/// descriptor.
|
||||
EFD_SEMAPHORE; // Since Linux 2.6.30/FreeBSD 13.0
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.28.0", note = "Use EventFd::from_value_and_flags() instead")]
|
||||
#[deprecated(
|
||||
since = "0.28.0",
|
||||
note = "Use EventFd::from_value_and_flags() instead"
|
||||
)]
|
||||
#[allow(missing_docs)]
|
||||
pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
|
||||
let res = unsafe { libc::eventfd(initval, flags.bits()) };
|
||||
|
||||
Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) })
|
||||
}
|
||||
|
||||
/// An eventfd file descriptor.
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct EventFd(OwnedFd);
|
||||
|
||||
impl EventFd {
|
||||
/// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`.
|
||||
pub fn new() -> Result<Self> {
|
||||
Self::from_value_and_flags(0, EfdFlags::empty())
|
||||
}
|
||||
|
||||
/// Constructs [`EventFd`] with the given `init_val` and `flags`.
|
||||
///
|
||||
///
|
||||
/// Wrapper around [`libc::eventfd`].
|
||||
pub fn from_value_and_flags(init_val: u32, flags: EfdFlags) -> Result<Self> {
|
||||
pub fn from_value_and_flags(
|
||||
init_val: u32,
|
||||
flags: EfdFlags,
|
||||
) -> Result<Self> {
|
||||
let res = unsafe { libc::eventfd(init_val, flags.bits()) };
|
||||
Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) }))
|
||||
}
|
||||
|
||||
/// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`.
|
||||
pub fn from_flags(flags: EfdFlags) -> Result<Self> {
|
||||
Self::from_value_and_flags(0, flags)
|
||||
}
|
||||
|
||||
/// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`.
|
||||
pub fn from_value(init_val: u32) -> Result<Self> {
|
||||
Self::from_value_and_flags(init_val, EfdFlags::empty())
|
||||
}
|
||||
/// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately.
|
||||
///
|
||||
/// [`EventFd::write`] with `1`.
|
||||
pub fn arm(&self) -> Result<usize> {
|
||||
self.write(1)
|
||||
|
||||
/// Constructs an `EventFd` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid eventfd.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
/// Defuses `self`, a following call to `poll`, `select` or `epoll` will block.
|
||||
///
|
||||
/// [`EventFd::write`] with `0`.
|
||||
pub fn defuse(&self) -> Result<usize> {
|
||||
self.write(0)
|
||||
}
|
||||
/// Enqueues `value` triggers.
|
||||
///
|
||||
|
||||
/// Enqueues `value` triggers, i.e., adds the integer value supplied in `value`
|
||||
/// to the counter.
|
||||
///
|
||||
/// The next `value` calls to `poll`, `select` or `epoll` will return immediately.
|
||||
///
|
||||
///
|
||||
/// [`EventFd::write`] with `value`.
|
||||
pub fn write(&self, value: u64) -> Result<usize> {
|
||||
unistd::write(&self.0,&value.to_ne_bytes())
|
||||
pub fn write(&self, value: u64) -> Result<usize> {
|
||||
unistd::write(&self.0, &value.to_ne_bytes())
|
||||
}
|
||||
// Reads the value from the file descriptor.
|
||||
|
||||
/// Reads the value from the file descriptor.
|
||||
///
|
||||
/// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was not specified and
|
||||
/// the eventfd counter has a nonzero value, then this function returns
|
||||
/// an `u64` containing that value, and the counter's value is reset to
|
||||
/// zero.
|
||||
///
|
||||
/// * If [`EFD_SEMAPHORE`](EfdFlags::EFD_SEMAPHORE) was specified and the
|
||||
/// eventfd counter has a nonzero value, then this function returns an
|
||||
/// `u64` containing the value 1, and the counter's value is decremented
|
||||
/// by 1.
|
||||
///
|
||||
/// * If the eventfd counter is zero at the time of this call, then the
|
||||
/// call either blocks until the counter becomes nonzero (at which time,
|
||||
/// this function proceeds as described above) or fails with the error
|
||||
/// `EAGAIN` if the file descriptor has been made nonblocking with
|
||||
/// [`EFD_NONBLOCK`](EfdFlags::EFD_NONBLOCK).
|
||||
pub fn read(&self) -> Result<u64> {
|
||||
let mut arr = [0; std::mem::size_of::<u64>()];
|
||||
unistd::read(self.0.as_raw_fd(),&mut arr)?;
|
||||
unistd::read(&self.0, &mut arr)?;
|
||||
Ok(u64::from_ne_bytes(arr))
|
||||
}
|
||||
}
|
||||
@@ -77,8 +110,9 @@ impl AsRawFd for EventFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EventFd> for OwnedFd {
|
||||
fn from(x: EventFd) -> OwnedFd {
|
||||
x.0
|
||||
fn from(value: EventFd) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
51
third_party/rust/nix/src/sys/fanotify.rs
vendored
51
third_party/rust/nix/src/sys/fanotify.rs
vendored
@@ -11,7 +11,7 @@
|
||||
//! [fanotify(7)](https://man7.org/linux/man-pages/man7/fanotify.7.html).
|
||||
|
||||
use crate::errno::Errno;
|
||||
use crate::fcntl::{at_rawfd, OFlag};
|
||||
use crate::fcntl::OFlag;
|
||||
use crate::unistd::{close, read, write};
|
||||
use crate::{NixPath, Result};
|
||||
use std::marker::PhantomData;
|
||||
@@ -20,8 +20,8 @@ use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
|
||||
use std::ptr;
|
||||
|
||||
libc_bitflags! {
|
||||
/// Mask for defining which events shall be listened with
|
||||
/// [`fanotify_mark`](fn.fanotify_mark.html) and for querying notifications.
|
||||
/// Mask for defining which events shall be listened with [`Fanotify::mark()`]
|
||||
/// and for querying notifications.
|
||||
pub struct MaskFlags: u64 {
|
||||
/// File was accessed.
|
||||
FAN_ACCESS;
|
||||
@@ -80,7 +80,7 @@ libc_bitflags! {
|
||||
}
|
||||
|
||||
libc_bitflags! {
|
||||
/// Configuration options for [`fanotify_init`](fn.fanotify_init.html).
|
||||
/// Configuration options for [`Fanotify::init()`].
|
||||
pub struct InitFlags: libc::c_uint {
|
||||
/// Close-on-exec flag set on the file descriptor.
|
||||
FAN_CLOEXEC;
|
||||
@@ -162,7 +162,7 @@ impl From<EventFFlags> for OFlag {
|
||||
}
|
||||
|
||||
libc_bitflags! {
|
||||
/// Configuration options for [`fanotify_mark`](fn.fanotify_mark.html).
|
||||
/// Configuration options for [`Fanotify::mark()`].
|
||||
pub struct MarkFlags: libc::c_uint {
|
||||
/// Add the events to the marks.
|
||||
FAN_MARK_ADD;
|
||||
@@ -198,8 +198,8 @@ libc_bitflags! {
|
||||
/// Compile version number of fanotify API.
|
||||
pub const FANOTIFY_METADATA_VERSION: u8 = libc::FANOTIFY_METADATA_VERSION;
|
||||
|
||||
/// Abstract over `libc::fanotify_event_metadata`, which represents an event
|
||||
/// received via `Fanotify::read_events`.
|
||||
/// Abstract over [`libc::fanotify_event_metadata`], which represents an event
|
||||
/// received via [`Fanotify::read_events`].
|
||||
// Is not Clone due to fd field, to avoid use-after-close scenarios.
|
||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
||||
#[repr(transparent)]
|
||||
@@ -281,7 +281,7 @@ impl<'a> FanotifyResponse<'a> {
|
||||
}
|
||||
|
||||
libc_bitflags! {
|
||||
/// Response to be wrapped in `FanotifyResponse` and sent to the `Fanotify`
|
||||
/// Response to be wrapped in [`FanotifyResponse`] and sent to the [`Fanotify`]
|
||||
/// group to allow or deny an event.
|
||||
pub struct Response: u32 {
|
||||
/// Allow the event.
|
||||
@@ -317,16 +317,15 @@ impl Fanotify {
|
||||
}
|
||||
|
||||
/// Add, remove, or modify an fanotify mark on a filesystem object.
|
||||
/// If `dirfd` is `None`, `AT_FDCWD` is used.
|
||||
///
|
||||
/// Returns a Result containing either `()` on success or errno otherwise.
|
||||
///
|
||||
/// For more information, see [fanotify_mark(2)](https://man7.org/linux/man-pages/man7/fanotify_mark.2.html).
|
||||
pub fn mark<P: ?Sized + NixPath>(
|
||||
pub fn mark<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
&self,
|
||||
flags: MarkFlags,
|
||||
mask: MaskFlags,
|
||||
dirfd: Option<RawFd>,
|
||||
dirfd: Fd,
|
||||
path: Option<&P>,
|
||||
) -> Result<()> {
|
||||
let res = crate::with_opt_nix_path(path, |p| unsafe {
|
||||
@@ -334,7 +333,7 @@ impl Fanotify {
|
||||
self.fd.as_raw_fd(),
|
||||
flags.bits(),
|
||||
mask.bits(),
|
||||
at_rawfd(dirfd),
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
p,
|
||||
)
|
||||
})?;
|
||||
@@ -362,7 +361,7 @@ impl Fanotify {
|
||||
let mut events = Vec::new();
|
||||
let mut offset = 0;
|
||||
|
||||
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
|
||||
let nread = read(&self.fd, &mut buffer)?;
|
||||
|
||||
while (nread - offset) >= metadata_size {
|
||||
let metadata = unsafe {
|
||||
@@ -419,3 +418,29 @@ impl AsFd for Fanotify {
|
||||
self.fd.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Fanotify {
|
||||
fn as_raw_fd(&self) -> RawFd
|
||||
{
|
||||
self.fd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Fanotify> for OwnedFd {
|
||||
fn from(value: Fanotify) -> Self {
|
||||
value.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl Fanotify {
|
||||
/// Constructs a `Fanotify` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid `Fanotify`.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self {
|
||||
fd
|
||||
}
|
||||
}
|
||||
}
|
||||
19
third_party/rust/nix/src/sys/inotify.rs
vendored
19
third_party/rust/nix/src/sys/inotify.rs
vendored
@@ -201,7 +201,7 @@ impl Inotify {
|
||||
let mut events = Vec::new();
|
||||
let mut offset = 0;
|
||||
|
||||
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
|
||||
let nread = read(&self.fd, &mut buffer)?;
|
||||
|
||||
while (nread - offset) >= header_size {
|
||||
let event = unsafe {
|
||||
@@ -239,6 +239,17 @@ impl Inotify {
|
||||
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
/// Constructs an `Inotify` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid `Inotify`.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self {
|
||||
fd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Inotify {
|
||||
@@ -254,3 +265,9 @@ impl AsFd for Inotify {
|
||||
self.fd.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Inotify> for OwnedFd {
|
||||
fn from(value: Inotify) -> Self {
|
||||
value.fd
|
||||
}
|
||||
}
|
||||
14
third_party/rust/nix/src/sys/ioctl/linux.rs
vendored
14
third_party/rust/nix/src/sys/ioctl/linux.rs
vendored
@@ -1,10 +1,20 @@
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
/// The datatype used for the ioctl number
|
||||
#[cfg(any(target_os = "android", target_env = "musl"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_env = "musl",
|
||||
target_env = "ohos"
|
||||
))]
|
||||
#[doc(hidden)]
|
||||
pub type ioctl_num_type = ::libc::c_int;
|
||||
#[cfg(not(any(target_os = "android", target_env = "musl")))]
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_env = "musl",
|
||||
target_env = "ohos"
|
||||
)))]
|
||||
#[doc(hidden)]
|
||||
pub type ioctl_num_type = ::libc::c_ulong;
|
||||
/// The datatype used for the 3rd argument
|
||||
|
||||
8
third_party/rust/nix/src/sys/ioctl/mod.rs
vendored
8
third_party/rust/nix/src/sys/ioctl/mod.rs
vendored
@@ -227,11 +227,11 @@
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
#[cfg(any(linux_android, target_os = "redox"))]
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", target_os = "redox"))]
|
||||
#[macro_use]
|
||||
mod linux;
|
||||
|
||||
#[cfg(any(linux_android, target_os = "redox"))]
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", target_os = "redox"))]
|
||||
pub use self::linux::*;
|
||||
|
||||
#[cfg(any(bsd, solarish, target_os = "haiku",))]
|
||||
@@ -655,8 +655,10 @@ macro_rules! ioctl_readwrite {
|
||||
pub unsafe fn $name(fd: $crate::libc::c_int,
|
||||
data: *mut $ty)
|
||||
-> $crate::Result<$crate::libc::c_int> {
|
||||
let ioty = $ioty;
|
||||
let nr = $nr;
|
||||
unsafe {
|
||||
convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::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::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
41
third_party/rust/nix/src/sys/memfd.rs
vendored
41
third_party/rust/nix/src/sys/memfd.rs
vendored
@@ -4,12 +4,11 @@ use cfg_if::cfg_if;
|
||||
use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
|
||||
|
||||
use crate::errno::Errno;
|
||||
use crate::Result;
|
||||
use std::ffi::CStr;
|
||||
use crate::{NixPath, Result};
|
||||
|
||||
libc_bitflags!(
|
||||
/// Options that change the behavior of [`memfd_create`].
|
||||
pub struct MemFdCreateFlag: libc::c_uint {
|
||||
pub struct MFdFlags: libc::c_uint {
|
||||
/// Set the close-on-exec ([`FD_CLOEXEC`]) flag on the new file descriptor.
|
||||
///
|
||||
/// By default, the new file descriptor is set to remain open across an [`execve`]
|
||||
@@ -38,6 +37,18 @@ libc_bitflags!(
|
||||
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
|
||||
#[cfg(linux_android)]
|
||||
MFD_HUGETLB;
|
||||
/// Shift to get the huge page size.
|
||||
#[cfg(target_env = "ohos")]
|
||||
MFD_HUGE_SHIFT;
|
||||
/// Mask to get the huge page size.
|
||||
#[cfg(target_env = "ohos")]
|
||||
MFD_HUGE_MASK;
|
||||
/// hugetlb size of 64KB.
|
||||
#[cfg(target_env = "ohos")]
|
||||
MFD_HUGE_64KB;
|
||||
/// hugetlb size of 512KB.
|
||||
#[cfg(target_env = "ohos")]
|
||||
MFD_HUGE_512KB;
|
||||
/// Following are to be used with [`MFD_HUGETLB`], indicating the desired hugetlb size.
|
||||
///
|
||||
/// See also the hugetlb filesystem in [`memfd_create(2)`].
|
||||
@@ -75,6 +86,10 @@ libc_bitflags!(
|
||||
}
|
||||
);
|
||||
|
||||
#[deprecated(since = "0.30.0", note = "Use `MFdFlags instead`")]
|
||||
/// The deprecated MemFdCreateFlag type alias
|
||||
pub type MemFdCreateFlag = MFdFlags;
|
||||
|
||||
/// Creates an anonymous file that lives in memory, and return a file-descriptor to it.
|
||||
///
|
||||
/// The file behaves like a regular file, and so can be modified, truncated, memory-mapped, and so on.
|
||||
@@ -84,25 +99,31 @@ libc_bitflags!(
|
||||
///
|
||||
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
|
||||
#[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! {
|
||||
pub fn memfd_create<P: NixPath + ?Sized>(
|
||||
name: &P,
|
||||
flags: MFdFlags,
|
||||
) -> Result<OwnedFd> {
|
||||
let res = name.with_nix_path(|cstr| {
|
||||
unsafe {
|
||||
cfg_if! {
|
||||
if #[cfg(all(
|
||||
// Android does not have a memfd_create symbol
|
||||
not(target_os = "android"),
|
||||
any(
|
||||
target_os = "freebsd",
|
||||
// If the OS is Linux, gnu and musl expose a memfd_create symbol but not uclibc
|
||||
// If the OS is Linux, gnu/musl/ohos expose a memfd_create symbol but not uclibc
|
||||
target_env = "gnu",
|
||||
target_env = "musl",
|
||||
target_env = "ohos"
|
||||
)))]
|
||||
{
|
||||
libc::memfd_create(name.as_ptr(), flags.bits())
|
||||
libc::memfd_create(cstr.as_ptr(), flags.bits())
|
||||
} else {
|
||||
libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
|
||||
libc::syscall(libc::SYS_memfd_create, cstr.as_ptr(), flags.bits())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
})?;
|
||||
|
||||
Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r as RawFd) })
|
||||
}
|
||||
|
||||
50
third_party/rust/nix/src/sys/mman.rs
vendored
50
third_party/rust/nix/src/sys/mman.rs
vendored
@@ -38,9 +38,13 @@ libc_bitflags! {
|
||||
/// Additional parameters for [`mmap`].
|
||||
pub struct MapFlags: c_int {
|
||||
/// Compatibility flag. Ignored.
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "redox")))]
|
||||
MAP_FILE;
|
||||
/// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
|
||||
MAP_SHARED;
|
||||
/// Force mmap to check and fail on unknown flags. This also enables `MAP_SYNC`.
|
||||
#[cfg(target_os = "linux")]
|
||||
MAP_SHARED_VALIDATE;
|
||||
/// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
|
||||
MAP_PRIVATE;
|
||||
/// Place the mapping at exactly the address specified in `addr`.
|
||||
@@ -60,6 +64,7 @@ libc_bitflags! {
|
||||
#[cfg(any(all(linux_android,
|
||||
any(target_arch = "x86", target_arch = "x86_64")),
|
||||
all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
|
||||
all(target_os = "linux", target_env = "ohos", target_arch = "x86_64"),
|
||||
all(target_os = "freebsd", target_pointer_width = "64")))]
|
||||
MAP_32BIT;
|
||||
/// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
|
||||
@@ -77,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(freebsdlike, target_os = "aix", target_os = "hurd")))]
|
||||
#[cfg(not(any(freebsdlike, target_os = "aix", target_os = "hurd", target_os = "redox")))]
|
||||
MAP_NORESERVE;
|
||||
/// Populate page tables for a mapping.
|
||||
#[cfg(linux_android)]
|
||||
@@ -140,8 +145,12 @@ libc_bitflags! {
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
MAP_HASSEMAPHORE;
|
||||
/// Region grows down, like a stack.
|
||||
#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
|
||||
#[cfg(any(linux_android, freebsdlike, netbsdlike))]
|
||||
MAP_STACK;
|
||||
/// Do not write through the page caches, write directly to the file. Used for Direct Access (DAX) enabled file systems.
|
||||
// Available on Linux glibc and musl, MIPS* target excluded.
|
||||
#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64", target_arch = "mips32r6", target_arch = "mips64r6")), not(target_env = "uclibc")))]
|
||||
MAP_SYNC;
|
||||
/// Pages in this mapping are not retained in the kernel's memory cache.
|
||||
#[cfg(apple_targets)]
|
||||
MAP_NOCACHE;
|
||||
@@ -197,6 +206,10 @@ libc_bitflags! {
|
||||
/// Place the mapping at exactly the address specified in `new_address`.
|
||||
#[cfg(target_os = "linux")]
|
||||
MREMAP_FIXED;
|
||||
/// Works in conjunction with `MREMAP_MAYMOVE` but does not unmap `old_address`.
|
||||
/// Note that, in this case, `old_size` and `new_size` must be the same.
|
||||
#[cfg(target_os = "linux")]
|
||||
MREMAP_DONTUNMAP;
|
||||
/// Place the mapping at exactly the address specified in `new_address`.
|
||||
#[cfg(target_os = "netbsd")]
|
||||
MAP_FIXED;
|
||||
@@ -268,7 +281,7 @@ libc_enum! {
|
||||
#[cfg(linux_android)]
|
||||
MADV_DODUMP,
|
||||
/// Specify that the application no longer needs the pages in the given range.
|
||||
#[cfg(not(any(target_os = "aix", target_os = "hurd")))]
|
||||
#[cfg(not(any(target_os = "aix", target_os = "hurd", target_os = "cygwin", target_os = "redox")))]
|
||||
MADV_FREE,
|
||||
/// Request that the system not flush the current range to disk unless it needs to.
|
||||
#[cfg(freebsdlike)]
|
||||
@@ -304,6 +317,25 @@ libc_enum! {
|
||||
#[cfg(apple_targets)]
|
||||
#[allow(missing_docs)]
|
||||
MADV_CAN_REUSE,
|
||||
/// Reclaim the address range when applicable.
|
||||
#[cfg(linux_android)]
|
||||
MADV_PAGEOUT,
|
||||
/// Deactivate the address range when applicable.
|
||||
#[cfg(linux_android)]
|
||||
MADV_COLD,
|
||||
/// After fork, the adress range is zero filled.
|
||||
#[cfg(linux_android)]
|
||||
MADV_WIPEONFORK,
|
||||
/// Undo `MADV_WIPEONFORK` when it applied.
|
||||
#[cfg(linux_android)]
|
||||
MADV_KEEPONFORK,
|
||||
/// Pre-load the address range for reading to reduce page-fault latency.
|
||||
#[cfg(linux_android)]
|
||||
MADV_POPULATE_READ,
|
||||
/// Pre-fault the address range for writing to reduce page-fault
|
||||
/// latency on subsequent writes.
|
||||
#[cfg(linux_android)]
|
||||
MADV_POPULATE_WRITE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +357,7 @@ libc_bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
|
||||
libc_bitflags! {
|
||||
/// Flags for [`mlockall`].
|
||||
pub struct MlockAllFlags: c_int {
|
||||
@@ -368,7 +400,7 @@ pub unsafe fn munlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
|
||||
/// Locked pages never move to the swap area. For more information, see [`mlockall(2)`].
|
||||
///
|
||||
/// [`mlockall(2)`]: https://man7.org/linux/man-pages/man2/mlockall.2.html
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
|
||||
pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
|
||||
unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
|
||||
}
|
||||
@@ -378,7 +410,7 @@ pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
|
||||
/// For more information, see [`munlockall(2)`].
|
||||
///
|
||||
/// [`munlockall(2)`]: https://man7.org/linux/man-pages/man2/munlockall.2.html
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
|
||||
pub fn munlockall() -> Result<()> {
|
||||
unsafe { Errno::result(libc::munlockall()) }.map(drop)
|
||||
}
|
||||
@@ -407,7 +439,7 @@ pub unsafe fn mmap<F: AsFd>(
|
||||
libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset)
|
||||
};
|
||||
|
||||
if ret == libc::MAP_FAILED {
|
||||
if std::ptr::eq(ret, libc::MAP_FAILED) {
|
||||
Err(Errno::last())
|
||||
} else {
|
||||
// SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
|
||||
@@ -439,7 +471,7 @@ pub unsafe fn mmap_anonymous(
|
||||
libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), -1, 0)
|
||||
};
|
||||
|
||||
if ret == libc::MAP_FAILED {
|
||||
if std::ptr::eq(ret, libc::MAP_FAILED) {
|
||||
Err(Errno::last())
|
||||
} else {
|
||||
// SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
|
||||
@@ -488,7 +520,7 @@ pub unsafe fn mremap(
|
||||
)
|
||||
};
|
||||
|
||||
if ret == libc::MAP_FAILED {
|
||||
if std::ptr::eq(ret, libc::MAP_FAILED) {
|
||||
Err(Errno::last())
|
||||
} else {
|
||||
// SAFETY: `libc::mremap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
|
||||
|
||||
24
third_party/rust/nix/src/sys/mod.rs
vendored
24
third_party/rust/nix/src/sys/mod.rs
vendored
@@ -1,7 +1,10 @@
|
||||
//! Mostly platform-specific functionality
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
all(
|
||||
target_os = "linux",
|
||||
not(any(target_env = "uclibc", target_env = "ohos"))
|
||||
),
|
||||
apple_targets,
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
@@ -20,8 +23,8 @@ feature! {
|
||||
#[cfg(bsd)]
|
||||
pub mod event;
|
||||
|
||||
/// Event file descriptor.
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[allow(missing_docs)]
|
||||
pub mod eventfd;
|
||||
}
|
||||
|
||||
@@ -31,7 +34,13 @@ feature! {
|
||||
pub mod fanotify;
|
||||
}
|
||||
|
||||
#[cfg(any(bsd, linux_android, target_os = "redox", solarish))]
|
||||
#[cfg(any(
|
||||
bsd,
|
||||
linux_android,
|
||||
solarish,
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
))]
|
||||
#[cfg(feature = "ioctl")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
|
||||
#[macro_use]
|
||||
@@ -43,7 +52,6 @@ feature! {
|
||||
pub mod memfd;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
feature! {
|
||||
#![feature = "mman"]
|
||||
pub mod mman;
|
||||
@@ -128,7 +136,13 @@ feature! {
|
||||
pub mod stat;
|
||||
}
|
||||
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))]
|
||||
#[cfg(any(
|
||||
linux_android,
|
||||
freebsdlike,
|
||||
apple_targets,
|
||||
target_os = "openbsd",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
feature! {
|
||||
#![feature = "fs"]
|
||||
pub mod statfs;
|
||||
|
||||
4
third_party/rust/nix/src/sys/personality.rs
vendored
4
third_party/rust/nix/src/sys/personality.rs
vendored
@@ -20,7 +20,7 @@ libc_bitflags! {
|
||||
/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
|
||||
ADDR_LIMIT_3GB;
|
||||
/// User-space function pointers to signal handlers point to descriptors.
|
||||
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "uclibc", target_env = "ohos")))]
|
||||
FDPIC_FUNCPTRS;
|
||||
/// Map page 0 as read-only.
|
||||
MMAP_PAGE_ZERO;
|
||||
@@ -41,7 +41,7 @@ libc_bitflags! {
|
||||
/// version number.
|
||||
///
|
||||
/// [`uname(2)`]: https://man7.org/linux/man-pages/man2/uname.2.html
|
||||
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "uclibc", target_env = "ohos")))]
|
||||
UNAME26;
|
||||
/// No effects.
|
||||
WHOLE_SECONDS;
|
||||
|
||||
2
third_party/rust/nix/src/sys/prctl.rs
vendored
2
third_party/rust/nix/src/sys/prctl.rs
vendored
@@ -166,7 +166,7 @@ pub fn get_name() -> Result<CString> {
|
||||
|
||||
/// 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<()> {
|
||||
pub fn set_timerslack(ns: c_ulong) -> Result<()> {
|
||||
let res = unsafe { libc::prctl(libc::PR_SET_TIMERSLACK, ns, 0, 0, 0) };
|
||||
|
||||
Errno::result(res).map(drop)
|
||||
|
||||
131
third_party/rust/nix/src/sys/ptrace/linux.rs
vendored
131
third_party/rust/nix/src/sys/ptrace/linux.rs
vendored
@@ -14,11 +14,10 @@ pub type AddressType = *mut ::libc::c_void;
|
||||
target_os = "linux",
|
||||
any(
|
||||
all(
|
||||
target_arch = "x86_64",
|
||||
any(target_arch = "x86_64", target_arch = "aarch64"),
|
||||
any(target_env = "gnu", target_env = "musl")
|
||||
),
|
||||
all(target_arch = "x86", target_env = "gnu"),
|
||||
all(target_arch = "aarch64", target_env = "gnu"),
|
||||
all(target_arch = "riscv64", target_env = "gnu"),
|
||||
),
|
||||
))]
|
||||
@@ -37,8 +36,8 @@ cfg_if! {
|
||||
}
|
||||
|
||||
libc_enum! {
|
||||
#[cfg_attr(not(any(target_env = "musl", target_env = "uclibc", target_os = "android")), repr(u32))]
|
||||
#[cfg_attr(any(target_env = "musl", target_env = "uclibc", target_os = "android"), repr(i32))]
|
||||
#[cfg_attr(not(any(target_env = "musl", target_env = "uclibc", target_os = "android", target_env = "ohos")), repr(u32))]
|
||||
#[cfg_attr(any(target_env = "musl", target_env = "uclibc", target_os = "android", target_env = "ohos"), repr(i32))]
|
||||
/// Ptrace Request enum defining the action to be taken.
|
||||
#[non_exhaustive]
|
||||
pub enum Request {
|
||||
@@ -54,6 +53,7 @@ libc_enum! {
|
||||
PTRACE_SINGLESTEP,
|
||||
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
|
||||
all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -63,6 +63,7 @@ libc_enum! {
|
||||
PTRACE_GETREGS,
|
||||
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
|
||||
all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -72,6 +73,7 @@ libc_enum! {
|
||||
PTRACE_SETREGS,
|
||||
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
|
||||
all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -81,6 +83,7 @@ libc_enum! {
|
||||
PTRACE_GETFPREGS,
|
||||
#[cfg(any(all(target_os = "android", target_pointer_width = "32"),
|
||||
all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -91,6 +94,7 @@ libc_enum! {
|
||||
PTRACE_ATTACH,
|
||||
PTRACE_DETACH,
|
||||
#[cfg(all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -99,6 +103,7 @@ libc_enum! {
|
||||
target_arch = "x86_64")))]
|
||||
PTRACE_GETFPXREGS,
|
||||
#[cfg(all(target_os = "linux", any(target_env = "musl",
|
||||
target_env = "ohos",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
@@ -141,6 +146,8 @@ libc_enum! {
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu",
|
||||
any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
PTRACE_SYSEMU_SINGLESTEP,
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
PTRACE_GET_SYSCALL_INFO,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,13 +181,21 @@ libc_enum! {
|
||||
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
),
|
||||
all(
|
||||
target_env = "musl",
|
||||
target_arch = "aarch64",
|
||||
)
|
||||
),
|
||||
))]
|
||||
libc_enum! {
|
||||
#[repr(i32)]
|
||||
@@ -197,13 +212,21 @@ libc_enum! {
|
||||
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
),
|
||||
all(
|
||||
target_env = "musl",
|
||||
target_arch = "aarch64",
|
||||
)
|
||||
),
|
||||
))]
|
||||
/// Represents register set areas, such as general-purpose registers or
|
||||
/// floating-point registers.
|
||||
@@ -220,15 +243,24 @@ pub unsafe trait RegisterSet {
|
||||
type Regs;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
)
|
||||
),
|
||||
all(
|
||||
target_env = "musl",
|
||||
target_arch = "aarch64",
|
||||
)
|
||||
),
|
||||
))]
|
||||
/// Register sets used in [`getregset`] and [`setregset`]
|
||||
pub mod regset {
|
||||
@@ -334,8 +366,13 @@ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
|
||||
/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(target_arch = "aarch64", target_arch = "riscv64")
|
||||
any(
|
||||
all(
|
||||
target_arch = "aarch64",
|
||||
any(target_env = "gnu", target_env = "musl")
|
||||
),
|
||||
all(target_arch = "riscv64", target_env = "gnu")
|
||||
)
|
||||
))]
|
||||
pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
|
||||
getregset::<regset::NT_PRSTATUS>(pid)
|
||||
@@ -344,12 +381,17 @@ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
|
||||
/// Get a particular set of user registers, as with `ptrace(PTRACE_GETREGSET, ...)`
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64"
|
||||
)
|
||||
),
|
||||
all(target_env = "musl", target_arch = "aarch64")
|
||||
)
|
||||
))]
|
||||
pub fn getregset<S: RegisterSet>(pid: Pid) -> Result<S::Regs> {
|
||||
@@ -408,8 +450,13 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
|
||||
/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(target_arch = "aarch64", target_arch = "riscv64")
|
||||
any(
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(target_arch = "aarch64", target_arch = "riscv64")
|
||||
),
|
||||
all(target_env = "musl", target_arch = "aarch64")
|
||||
)
|
||||
))]
|
||||
pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
|
||||
setregset::<regset::NT_PRSTATUS>(pid, regs)
|
||||
@@ -418,12 +465,17 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
|
||||
/// Set a particular set of user registers, as with `ptrace(PTRACE_SETREGSET, ...)`
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64"
|
||||
)
|
||||
),
|
||||
all(target_env = "musl", target_arch = "aarch64")
|
||||
)
|
||||
))]
|
||||
pub fn setregset<S: RegisterSet>(pid: Pid, mut regs: S::Regs) -> Result<()> {
|
||||
@@ -517,6 +569,13 @@ pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the informations of the syscall that caused the stop, as with
|
||||
/// `ptrace(PTRACE_GET_SYSCALL_INFO, ...`.
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub fn syscall_info(pid: Pid) -> Result<libc::ptrace_syscall_info> {
|
||||
ptrace_get_data::<libc::ptrace_syscall_info>(Request::PTRACE_GET_SYSCALL_INFO, pid)
|
||||
}
|
||||
|
||||
/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
|
||||
///
|
||||
/// Indicates that this process is to be traced by its parent.
|
||||
|
||||
6
third_party/rust/nix/src/sys/resource.rs
vendored
6
third_party/rust/nix/src/sys/resource.rs
vendored
@@ -19,7 +19,8 @@ cfg_if! {
|
||||
bsd,
|
||||
target_os = "android",
|
||||
target_os = "aix",
|
||||
all(target_os = "linux", not(target_env = "gnu"))
|
||||
all(target_os = "linux", not(target_env = "gnu")),
|
||||
target_os = "cygwin"
|
||||
))]{
|
||||
use libc::rlimit;
|
||||
}
|
||||
@@ -49,7 +50,8 @@ libc_enum! {
|
||||
bsd,
|
||||
target_os = "android",
|
||||
target_os = "aix",
|
||||
all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
|
||||
all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc"))),
|
||||
target_os = "cygwin"
|
||||
), repr(i32))]
|
||||
#[non_exhaustive]
|
||||
pub enum Resource {
|
||||
|
||||
8
third_party/rust/nix/src/sys/select.rs
vendored
8
third_party/rust/nix/src/sys/select.rs
vendored
@@ -115,7 +115,7 @@ impl<'fd> FdSet<'fd> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'fd> Default for FdSet<'fd> {
|
||||
impl Default for FdSet<'_> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
@@ -128,7 +128,7 @@ pub struct Fds<'a, 'fd> {
|
||||
range: Range<usize>,
|
||||
}
|
||||
|
||||
impl<'a, 'fd> Iterator for Fds<'a, 'fd> {
|
||||
impl<'fd> Iterator for Fds<'_, 'fd> {
|
||||
type Item = BorrowedFd<'fd>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@@ -148,7 +148,7 @@ impl<'a, 'fd> Iterator for Fds<'a, 'fd> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'fd> DoubleEndedIterator for Fds<'a, 'fd> {
|
||||
impl<'fd> DoubleEndedIterator for Fds<'_, 'fd> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<BorrowedFd<'fd>> {
|
||||
while let Some(i) = self.range.next_back() {
|
||||
@@ -161,7 +161,7 @@ impl<'a, 'fd> DoubleEndedIterator for Fds<'a, 'fd> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'fd> FusedIterator for Fds<'a, 'fd> {}
|
||||
impl FusedIterator for Fds<'_, '_> {}
|
||||
|
||||
/// Monitors file descriptors for readiness
|
||||
///
|
||||
|
||||
117
third_party/rust/nix/src/sys/signal.rs
vendored
117
third_party/rust/nix/src/sys/signal.rs
vendored
@@ -1,6 +1,3 @@
|
||||
// Portions of this file are Copyright 2014 The Rust Project Developers.
|
||||
// See https://www.rust-lang.org/policies/licenses.
|
||||
|
||||
//! Operating system signals.
|
||||
|
||||
use crate::errno::Errno;
|
||||
@@ -10,8 +7,6 @@ use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
use std::ops::BitOr;
|
||||
#[cfg(freebsdlike)]
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -72,6 +67,7 @@ libc_enum! {
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"))))]
|
||||
SIGSTKFLT,
|
||||
/// To parent on child stop or exit
|
||||
@@ -114,7 +110,8 @@ libc_enum! {
|
||||
SIGEMT,
|
||||
#[cfg(not(any(linux_android, target_os = "emscripten",
|
||||
target_os = "fuchsia", target_os = "redox",
|
||||
target_os = "haiku", target_os = "aix")))]
|
||||
target_os = "haiku", target_os = "aix",
|
||||
target_os = "solaris", target_os = "cygwin")))]
|
||||
/// Information request
|
||||
SIGINFO,
|
||||
}
|
||||
@@ -152,6 +149,7 @@ impl FromStr for Signal {
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
))
|
||||
))]
|
||||
@@ -191,7 +189,9 @@ impl FromStr for Signal {
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "aix",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "solaris",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
"SIGINFO" => Signal::SIGINFO,
|
||||
_ => return Err(Errno::EINVAL),
|
||||
@@ -234,6 +234,7 @@ impl Signal {
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
))
|
||||
))]
|
||||
@@ -274,7 +275,9 @@ impl Signal {
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "aix",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "solaris",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
Signal::SIGINFO => "SIGINFO",
|
||||
}
|
||||
@@ -321,6 +324,7 @@ const SIGNALS: [Signal; 28] = [
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
))
|
||||
))]
|
||||
@@ -338,6 +342,7 @@ const SIGNALS: [Signal; 31] = [
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
)
|
||||
))]
|
||||
@@ -356,13 +361,23 @@ const SIGNALS: [Signal; 30] = [
|
||||
SIGURG, SIGPOLL, SIGIO, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU,
|
||||
SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP,
|
||||
];
|
||||
#[cfg(any(target_os = "solaris", target_os = "cygwin"))]
|
||||
#[cfg(feature = "signal")]
|
||||
const SIGNALS: [Signal; 30] = [
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
|
||||
SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
|
||||
SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
|
||||
SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT,
|
||||
];
|
||||
#[cfg(not(any(
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "aix",
|
||||
target_os = "redox",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "solaris",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
#[cfg(feature = "signal")]
|
||||
const SIGNALS: [Signal; 31] = [
|
||||
@@ -745,11 +760,11 @@ pub enum SigHandler {
|
||||
/// Request that the signal be ignored.
|
||||
SigIgn,
|
||||
/// Use the given signal-catching function, which takes in the signal.
|
||||
Handler(extern fn(libc::c_int)),
|
||||
Handler(extern "C" fn(libc::c_int)),
|
||||
/// Use the given signal-catching function, which takes in the signal, information about how
|
||||
/// the signal was generated, and a pointer to the threads `ucontext_t`.
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
|
||||
SigAction(extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
|
||||
}
|
||||
|
||||
/// Action to take on receipt of a signal. Corresponds to `sigaction`.
|
||||
@@ -772,27 +787,14 @@ 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) {
|
||||
unsafe {
|
||||
(*p).sa_sigaction = match handler {
|
||||
SigHandler::SigDfl => libc::SIG_DFL,
|
||||
SigHandler::SigIgn => libc::SIG_IGN,
|
||||
SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
|
||||
SigHandler::Handler(f) => f as *const extern "C" fn(libc::c_int) as usize,
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
|
||||
unsafe {
|
||||
(*p).sa_union.__su_sigaction = match handler {
|
||||
SigHandler::SigDfl => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL) },
|
||||
SigHandler::SigIgn => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN) },
|
||||
SigHandler::Handler(f) => unsafe { mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f) },
|
||||
SigHandler::SigAction(f) => f,
|
||||
SigHandler::SigAction(f) => f as *const extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -824,7 +826,6 @@ 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,
|
||||
@@ -840,9 +841,9 @@ impl SigAction {
|
||||
// ensured that it is correctly initialized.
|
||||
unsafe{
|
||||
*(&p as *const usize
|
||||
as *const extern fn(_, _, _))
|
||||
as *const extern "C" fn(_, _, _))
|
||||
}
|
||||
as extern fn(_, _, _)),
|
||||
as extern "C" fn(_, _, _)),
|
||||
p => SigHandler::Handler(
|
||||
// Safe for one of two reasons:
|
||||
// * The SigHandler was created by SigHandler::new, in which
|
||||
@@ -852,29 +853,9 @@ impl SigAction {
|
||||
// ensured that it is correctly initialized.
|
||||
unsafe{
|
||||
*(&p as *const usize
|
||||
as *const extern fn(libc::c_int))
|
||||
as *const extern "C" fn(libc::c_int))
|
||||
}
|
||||
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)),
|
||||
}
|
||||
as extern "C" fn(libc::c_int)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -935,7 +916,7 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
|
||||
/// # use nix::sys::signal::{self, Signal, SigHandler};
|
||||
/// static SIGNALED: AtomicBool = AtomicBool::new(false);
|
||||
///
|
||||
/// extern fn handle_sigint(signal: libc::c_int) {
|
||||
/// extern "C" fn handle_sigint(signal: libc::c_int) {
|
||||
/// let signal = Signal::try_from(signal).unwrap();
|
||||
/// SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
|
||||
/// }
|
||||
@@ -972,7 +953,7 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
|
||||
libc::SIG_DFL => SigHandler::SigDfl,
|
||||
libc::SIG_IGN => SigHandler::SigIgn,
|
||||
p => SigHandler::Handler(
|
||||
unsafe { *(&p as *const usize as *const extern fn(libc::c_int)) } as extern fn(libc::c_int)),
|
||||
unsafe { *(&p as *const usize as *const extern "C" fn(libc::c_int)) } as extern "C" fn(libc::c_int)),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1114,8 +1095,8 @@ pub type type_of_thread_id = libc::pid_t;
|
||||
// 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 = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum SigevNotify {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum SigevNotify<'fd> {
|
||||
/// No notification will be delivered
|
||||
SigevNone,
|
||||
/// Notify by delivering a signal to the process.
|
||||
@@ -1131,7 +1112,7 @@ pub enum SigevNotify {
|
||||
#[cfg(freebsdlike)]
|
||||
SigevKevent {
|
||||
/// File descriptor of the kqueue to notify.
|
||||
kq: RawFd,
|
||||
kq: std::os::fd::BorrowedFd<'fd>,
|
||||
/// Will be contained in the kevent's `udata` field.
|
||||
udata: libc::intptr_t
|
||||
},
|
||||
@@ -1140,11 +1121,11 @@ pub enum SigevNotify {
|
||||
#[cfg(feature = "event")]
|
||||
SigevKeventFlags {
|
||||
/// File descriptor of the kqueue to notify.
|
||||
kq: RawFd,
|
||||
kq: std::os::fd::BorrowedFd<'fd>,
|
||||
/// 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
|
||||
flags: crate::sys::event::EvFlags
|
||||
},
|
||||
/// Notify by delivering a signal to a thread.
|
||||
#[cfg(any(
|
||||
@@ -1161,6 +1142,14 @@ pub enum SigevNotify {
|
||||
/// structure of the queued signal.
|
||||
si_value: libc::intptr_t
|
||||
},
|
||||
/// A helper variant to resolve the unused parameter (`'fd`) problem on
|
||||
/// platforms other than FreeBSD and DragonFlyBSD.
|
||||
///
|
||||
/// This variant can never be constructed due to the usage of an enum with 0
|
||||
/// variants.
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(freebsdlike))]
|
||||
_Unreachable(&'fd std::convert::Infallible),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,15 +1326,19 @@ mod sigevent {
|
||||
},
|
||||
#[cfg(freebsdlike)]
|
||||
SigevNotify::SigevKevent{kq, udata} => {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
sev.sigev_notify = libc::SIGEV_KEVENT;
|
||||
sev.sigev_signo = kq;
|
||||
sev.sigev_signo = kq.as_raw_fd();
|
||||
sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
|
||||
},
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "event")]
|
||||
SigevNotify::SigevKeventFlags{kq, udata, flags} => {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
sev.sigev_notify = libc::SIGEV_KEVENT;
|
||||
sev.sigev_signo = kq;
|
||||
sev.sigev_signo = kq.as_raw_fd();
|
||||
sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
|
||||
sev._sigev_un._kevent_flags = flags.bits();
|
||||
},
|
||||
@@ -1363,6 +1356,8 @@ mod sigevent {
|
||||
sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
|
||||
sev.sigev_notify_thread_id = thread_id;
|
||||
}
|
||||
#[cfg(not(freebsdlike))]
|
||||
SigevNotify::_Unreachable(_) => unreachable!("This variant could never be constructed")
|
||||
}
|
||||
SigEvent{sigevent: sev}
|
||||
}
|
||||
@@ -1398,7 +1393,7 @@ mod sigevent {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a libc::sigevent> for SigEvent {
|
||||
impl From<&'_ libc::sigevent> for SigEvent {
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn from(sigevent: &libc::sigevent) -> Self {
|
||||
// Safe because they're really the same structure. See
|
||||
|
||||
17
third_party/rust/nix/src/sys/signalfd.rs
vendored
17
third_party/rust/nix/src/sys/signalfd.rs
vendored
@@ -18,6 +18,8 @@
|
||||
use crate::errno::Errno;
|
||||
pub use crate::sys::signal::{self, SigSet};
|
||||
use crate::Result;
|
||||
|
||||
/// Information of a received signal, the return type of [`SignalFd::read_signal()`].
|
||||
pub use libc::signalfd_siginfo as siginfo;
|
||||
|
||||
use std::mem;
|
||||
@@ -125,6 +127,15 @@ impl SignalFd {
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a `SignalFd` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid `SignalFd`.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
|
||||
fn update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()> {
|
||||
let raw_fd = self.0.as_raw_fd();
|
||||
unsafe {
|
||||
@@ -145,6 +156,12 @@ impl AsRawFd for SignalFd {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SignalFd> for OwnedFd {
|
||||
fn from(value: SignalFd) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for SignalFd {
|
||||
type Item = siginfo;
|
||||
|
||||
|
||||
57
third_party/rust/nix/src/sys/socket/addr.rs
vendored
57
third_party/rust/nix/src/sys/socket/addr.rs
vendored
@@ -66,7 +66,7 @@ pub enum AddressFamily {
|
||||
#[cfg(linux_android)]
|
||||
Netlink = libc::AF_NETLINK,
|
||||
/// Kernel interface for interacting with the routing table
|
||||
#[cfg(not(any(linux_android, target_os = "redox")))]
|
||||
#[cfg(not(any(linux_android, target_os = "redox", target_os = "cygwin")))]
|
||||
Route = libc::PF_ROUTE,
|
||||
/// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
|
||||
#[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
|
||||
@@ -78,7 +78,7 @@ pub enum AddressFamily {
|
||||
#[cfg(linux_android)]
|
||||
Ax25 = libc::AF_AX25,
|
||||
/// IPX - Novell protocols
|
||||
#[cfg(not(any(target_os = "aix", target_os = "redox")))]
|
||||
#[cfg(not(any(target_os = "aix", target_os = "redox", target_os = "cygwin")))]
|
||||
Ipx = libc::AF_IPX,
|
||||
/// AppleTalk
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -164,6 +164,7 @@ pub enum AddressFamily {
|
||||
apple_targets,
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
)))]
|
||||
Bluetooth = libc::AF_BLUETOOTH,
|
||||
/// IUCV (inter-user communication vehicle) z/VM protocol for
|
||||
@@ -180,6 +181,7 @@ pub enum AddressFamily {
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
)))]
|
||||
Isdn = libc::AF_ISDN,
|
||||
/// Nokia cellular modem IPC/RPC interface
|
||||
@@ -263,7 +265,7 @@ impl AddressFamily {
|
||||
libc::AF_NETLINK => Some(AddressFamily::Netlink),
|
||||
#[cfg(apple_targets)]
|
||||
libc::AF_SYSTEM => Some(AddressFamily::System),
|
||||
#[cfg(not(any(linux_android, target_os = "redox")))]
|
||||
#[cfg(not(any(linux_android, target_os = "redox", target_os = "cygwin")))]
|
||||
libc::PF_ROUTE => Some(AddressFamily::Route),
|
||||
#[cfg(linux_android)]
|
||||
libc::AF_PACKET => Some(AddressFamily::Packet),
|
||||
@@ -446,6 +448,7 @@ impl UnixAddr {
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
{
|
||||
UnixAddr { sun, sun_len }
|
||||
@@ -510,6 +513,7 @@ impl UnixAddr {
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
{
|
||||
self.sun_len
|
||||
@@ -526,7 +530,8 @@ impl SockaddrLike for UnixAddr {
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
fn len(&self) -> libc::socklen_t {
|
||||
self.sun_len.into()
|
||||
@@ -556,6 +561,7 @@ impl SockaddrLike for UnixAddr {
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
))] {
|
||||
let su_len = len.unwrap_or(
|
||||
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
|
||||
@@ -655,15 +661,13 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `addr`: raw pointer to something that can be cast to a
|
||||
/// `libc::sockaddr`. For example, `libc::sockaddr_in`,
|
||||
/// `libc::sockaddr_in6`, etc.
|
||||
/// - `len`: For fixed-width types like `sockaddr_in`, it will be
|
||||
/// validated if present and ignored if not. For variable-width
|
||||
/// types it is required and must be the total length of valid
|
||||
/// data. For example, if `addr` points to a
|
||||
/// named `sockaddr_un`, then `len` must be the length of the
|
||||
/// structure up to but not including the trailing NUL.
|
||||
/// - `addr`: raw pointer to something that can be cast to a `libc::sockaddr`.
|
||||
/// For example, `libc::sockaddr_in`, `libc::sockaddr_in6`, etc.
|
||||
/// - `len`: For fixed-width types like `sockaddr_in`, it will be validated
|
||||
/// if present and ignored if not. For variable-width types it is required
|
||||
/// and must be the total length of valid data. For example, if `addr`
|
||||
/// points to a named `sockaddr_un`, then `len` must be the length of the
|
||||
/// structure up to but not including the trailing NUL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
@@ -919,6 +923,13 @@ impl From<SockaddrIn> for net::SocketAddrV4 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl From<SockaddrIn> for net::SocketAddr {
|
||||
fn from(addr: SockaddrIn) -> Self {
|
||||
net::SocketAddr::from(net::SocketAddrV4::from(addr))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl From<SockaddrIn> for libc::sockaddr_in {
|
||||
fn from(sin: SockaddrIn) -> libc::sockaddr_in {
|
||||
@@ -1075,6 +1086,13 @@ impl From<SockaddrIn6> for net::SocketAddrV6 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl From<SockaddrIn6> for net::SocketAddr {
|
||||
fn from(addr: SockaddrIn6) -> Self {
|
||||
net::SocketAddr::from(net::SocketAddrV6::from(addr))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl std::str::FromStr for SockaddrIn6 {
|
||||
type Err = net::AddrParseError;
|
||||
@@ -1110,7 +1128,7 @@ pub union SockaddrStorage {
|
||||
alg: AlgAddr,
|
||||
#[cfg(all(
|
||||
feature = "net",
|
||||
not(any(target_os = "hurd", target_os = "redox"))
|
||||
not(any(target_os = "hurd", target_os = "redox", target_os = "cygwin"))
|
||||
))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
dl: LinkAddr,
|
||||
@@ -1154,6 +1172,7 @@ impl SockaddrLike for SockaddrStorage {
|
||||
linux_android,
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
if i32::from(ss.ss_family) == libc::AF_UNIX {
|
||||
// Safe because we UnixAddr is strictly smaller than
|
||||
@@ -1210,7 +1229,7 @@ impl SockaddrLike for SockaddrStorage {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", solarish))]
|
||||
#[cfg(any(linux_android, target_os = "fuchsia", solarish, target_os = "cygwin"))]
|
||||
fn len(&self) -> libc::socklen_t {
|
||||
match self.as_unix_addr() {
|
||||
// The UnixAddr type knows its own length
|
||||
@@ -1272,6 +1291,7 @@ impl SockaddrStorage {
|
||||
if #[cfg(any(linux_android,
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
{
|
||||
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
|
||||
@@ -1301,6 +1321,7 @@ impl SockaddrStorage {
|
||||
if #[cfg(any(linux_android,
|
||||
target_os = "fuchsia",
|
||||
solarish,
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
{
|
||||
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
|
||||
@@ -2176,7 +2197,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "hurd", target_os = "redox")))]
|
||||
#[cfg(not(any(target_os = "hurd", target_os = "redox", target_os = "cygwin")))]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
mod link {
|
||||
#[cfg(any(apple_targets, solarish))]
|
||||
@@ -2200,7 +2221,7 @@ mod tests {
|
||||
sdl_slen: 0,
|
||||
..unsafe { mem::zeroed() }
|
||||
});
|
||||
format!("{la}");
|
||||
let _ = format!("{la}");
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
@@ -2407,7 +2428,7 @@ mod tests {
|
||||
let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
|
||||
|
||||
let sun_path1 =
|
||||
unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
|
||||
unsafe { &(&(*addr.as_ptr()).sun_path)[..addr.path_len()] };
|
||||
let sun_path2 = [
|
||||
0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
|
||||
116, 101, 115, 116,
|
||||
|
||||
310
third_party/rust/nix/src/sys/socket/mod.rs
vendored
310
third_party/rust/nix/src/sys/socket/mod.rs
vendored
@@ -39,10 +39,22 @@ pub use self::addr::{SockaddrLike, SockaddrStorage};
|
||||
pub use self::addr::{AddressFamily, UnixAddr};
|
||||
#[cfg(not(solarish))]
|
||||
pub use self::addr::{AddressFamily, UnixAddr};
|
||||
#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))]
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
)))]
|
||||
#[cfg(feature = "net")]
|
||||
pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6};
|
||||
#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))]
|
||||
#[cfg(any(
|
||||
solarish,
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
#[cfg(feature = "net")]
|
||||
pub use self::addr::{SockaddrIn, SockaddrIn6};
|
||||
|
||||
@@ -199,10 +211,28 @@ pub enum SockProtocol {
|
||||
// The protocol number is fed into the socket syscall in network byte order.
|
||||
#[cfg(linux_android)]
|
||||
EthAll = (libc::ETH_P_ALL as u16).to_be() as i32,
|
||||
#[cfg(linux_android)]
|
||||
/// Packet filter on loopback traffic
|
||||
EthLoop = (libc::ETH_P_LOOP as u16).to_be() as i32,
|
||||
/// Packet filter on IPv4 traffic
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(target_endian = "big")]
|
||||
EthIp = libc::ETH_P_IP,
|
||||
/// Packet filter on IPv6 traffic
|
||||
#[cfg(linux_android)]
|
||||
EthIpv6 = (libc::ETH_P_IPV6 as u16).to_be() as i32,
|
||||
/// ICMP protocol ([icmp(7)](https://man7.org/linux/man-pages/man7/icmp.7.html))
|
||||
Icmp = libc::IPPROTO_ICMP,
|
||||
/// ICMPv6 protocol (ICMP over IPv6)
|
||||
IcmpV6 = libc::IPPROTO_ICMPV6,
|
||||
/// SCTP ([sctp(7)](https://man7.org/linux/man-pages/man7/sctp.7.html))
|
||||
#[cfg(any(
|
||||
apple_targets,
|
||||
linux_android,
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
Sctp = libc::IPPROTO_SCTP,
|
||||
}
|
||||
|
||||
impl SockProtocol {
|
||||
@@ -223,6 +253,14 @@ impl SockProtocol {
|
||||
#[cfg(apple_targets)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const KextEvent: SockProtocol = SockProtocol::Icmp; // Matches libc::SYSPROTO_EVENT
|
||||
|
||||
/// Packet filter on IPv4 traffic
|
||||
// NOTE: placed here due to conflict (little endian arch) with SockProtocol::NetLinkISCI
|
||||
#[cfg(linux_android)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[cfg(target_endian = "little")]
|
||||
pub const EthIp: SockProtocol = unsafe { std::mem::transmute::<i32, SockProtocol>((libc::ETH_P_IP as u16).to_be() as i32) };
|
||||
|
||||
}
|
||||
#[cfg(linux_android)]
|
||||
libc_bitflags! {
|
||||
@@ -346,6 +384,9 @@ libc_bitflags! {
|
||||
target_os = "fuchsia",
|
||||
target_os = "freebsd"))]
|
||||
MSG_WAITFORONE;
|
||||
/// Indicates that this message is not a user message but an SCTP notification.
|
||||
#[cfg(target_os = "linux")]
|
||||
MSG_NOTIFICATION;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,6 +540,63 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(apple_targets)] {
|
||||
use std::fmt;
|
||||
|
||||
/// Return type of [`LocalPeerToken`].
|
||||
///
|
||||
/// The audit token is an opaque token which identifies Mach tasks and
|
||||
/// senders of Mach messages as subjects to the BSM audit system. Only
|
||||
/// the appropriate BSM library routines should be used to interpret
|
||||
/// the contents of the audit token as the representation of the
|
||||
/// subject identity within the token may change over time.
|
||||
///
|
||||
/// Starting with macOS 11, almost all audit functions have been
|
||||
/// deprecated (see the system header `bsm/libbsm.h`), do not use them
|
||||
/// if your program target more recent versions of macOS.
|
||||
///
|
||||
/// [`LocalPeerToken`]: crate::sys::socket::sockopt::LocalPeerToken
|
||||
#[repr(C)]
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct audit_token_t {
|
||||
/// Value of the token.
|
||||
///
|
||||
/// This is considered an opaque value, do not rely on its format.
|
||||
pub val: [libc::c_uint; 8],
|
||||
}
|
||||
|
||||
// Make the debug representation a hex string to make it shorter and clearer.
|
||||
impl fmt::Debug for audit_token_t {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("audit_token_t")
|
||||
.field(&format!("0x{:08X}", self))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for audit_token_t {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for v in self.val {
|
||||
fmt::LowerHex::fmt(&v, f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for audit_token_t {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for v in self.val {
|
||||
fmt::UpperHex::fmt(&v, f)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
feature! {
|
||||
#![feature = "net"]
|
||||
/// Request for multicast socket operations
|
||||
@@ -573,7 +671,7 @@ macro_rules! cmsg_space {
|
||||
( $( $x:ty ),* ) => {
|
||||
{
|
||||
let space = 0 $(+ $crate::sys::socket::cmsg_space::<$x>())*;
|
||||
Vec::<u8>::with_capacity(space)
|
||||
vec![0u8; space]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,7 +697,7 @@ pub struct RecvMsg<'a, 's, S> {
|
||||
mhdr: msghdr,
|
||||
}
|
||||
|
||||
impl<'a, S> RecvMsg<'a, '_, S> {
|
||||
impl<S> RecvMsg<'_, '_, S> {
|
||||
/// Iterate over the valid control messages pointed to by this msghdr. If
|
||||
/// allocated space for CMSGs was too small it is not safe to iterate,
|
||||
/// instead return an `Error::ENOBUFS` error.
|
||||
@@ -623,7 +721,7 @@ pub struct CmsgIterator<'a> {
|
||||
mhdr: &'a msghdr
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CmsgIterator<'a> {
|
||||
impl Iterator for CmsgIterator<'_> {
|
||||
type Item = ControlMessageOwned;
|
||||
|
||||
fn next(&mut self) -> Option<ControlMessageOwned> {
|
||||
@@ -769,6 +867,43 @@ pub enum ControlMessageOwned {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv6OrigDstAddr(libc::sockaddr_in6),
|
||||
|
||||
/// Time-to-Live (TTL) header field of the incoming IPv4 packet.
|
||||
///
|
||||
/// [Further reading](https://www.man7.org/linux/man-pages/man7/ip.7.html)
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Ttl(i32),
|
||||
|
||||
/// Time-to-Live (TTL) header field of the incoming IPv4 packet.
|
||||
///
|
||||
/// [Further reading](https://datatracker.ietf.org/doc/html/rfc3542.html)
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Ttl(u8),
|
||||
|
||||
/// Hop Limit header field of the incoming IPv6 packet.
|
||||
///
|
||||
/// [Further reading for Linux](https://www.man7.org/linux/man-pages/man7/ip.7.html)
|
||||
/// [Further reading for FreeBSD](https://datatracker.ietf.org/doc/html/rfc3542.html)
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv6HopLimit(i32),
|
||||
|
||||
/// Retrieve the DSCP (ToS) header field of the incoming IPv4 packet.
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Tos(u8),
|
||||
|
||||
/// Retrieve the DSCP (Traffic Class) header field of the incoming IPv6 packet.
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv6TClass(i32),
|
||||
|
||||
/// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
|
||||
/// packets from a single sender.
|
||||
/// Fixed-size payloads are following one by one in a receive buffer.
|
||||
@@ -809,7 +944,6 @@ pub enum ControlMessageOwned {
|
||||
TlsGetRecordType(TlsGetRecordType),
|
||||
|
||||
/// Catch-all variant for unimplemented cmsg types.
|
||||
#[doc(hidden)]
|
||||
Unknown(UnknownCmsg),
|
||||
}
|
||||
|
||||
@@ -891,7 +1025,7 @@ impl ControlMessageOwned {
|
||||
let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) };
|
||||
ControlMessageOwned::ScmCreds(cred.into())
|
||||
}
|
||||
#[cfg(not(any(target_os = "aix", target_os = "haiku")))]
|
||||
#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "cygwin")))]
|
||||
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
|
||||
let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) };
|
||||
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
|
||||
@@ -987,9 +1121,48 @@ impl ControlMessageOwned {
|
||||
let content_type = unsafe { ptr::read_unaligned(p as *const u8) };
|
||||
ControlMessageOwned::TlsGetRecordType(content_type.into())
|
||||
},
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IP, libc::IP_TTL) => {
|
||||
let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
|
||||
ControlMessageOwned::Ipv4Ttl(ttl)
|
||||
},
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IP, libc::IP_RECVTTL) => {
|
||||
let ttl: u8 = unsafe { ptr::read_unaligned(p as *const u8) };
|
||||
ControlMessageOwned::Ipv4Ttl(ttl)
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IPV6, libc::IPV6_HOPLIMIT) => {
|
||||
let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
|
||||
ControlMessageOwned::Ipv6HopLimit(ttl)
|
||||
},
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IP, libc::IP_TOS) => {
|
||||
let tos = unsafe { ptr::read_unaligned(p as *const u8) };
|
||||
ControlMessageOwned::Ipv4Tos(tos)
|
||||
},
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IP, libc::IP_RECVTOS) => {
|
||||
let tos = unsafe { ptr::read_unaligned(p as *const u8) };
|
||||
ControlMessageOwned::Ipv4Tos(tos)
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
(libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => {
|
||||
let tc = unsafe { ptr::read_unaligned(p as *const i32) };
|
||||
ControlMessageOwned::Ipv6TClass(tc)
|
||||
},
|
||||
(_, _) => {
|
||||
let sl = unsafe { std::slice::from_raw_parts(p, len) };
|
||||
let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
|
||||
let ucmsg = UnknownCmsg {
|
||||
cmsg_header: *header,
|
||||
data_bytes: Vec::<u8>::from(sl),
|
||||
};
|
||||
ControlMessageOwned::Unknown(ucmsg)
|
||||
}
|
||||
}
|
||||
@@ -1124,6 +1297,18 @@ pub enum ControlMessage<'a> {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4SendSrcAddr(&'a libc::in_addr),
|
||||
|
||||
/// Configure the Time-to-Live for v4 traffic.
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Ttl(&'a libc::c_int),
|
||||
|
||||
/// Configure the Time-to-Live for v4 traffic.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Ttl(&'a libc::c_uchar),
|
||||
|
||||
/// Configure the hop limit for v6 multicast traffic.
|
||||
///
|
||||
/// Set the IPv6 hop limit for this message. The argument is an integer
|
||||
@@ -1138,9 +1323,9 @@ pub enum ControlMessage<'a> {
|
||||
Ipv6HopLimit(&'a libc::c_int),
|
||||
|
||||
/// SO_RXQ_OVFL indicates that an unsigned 32 bit value
|
||||
/// ancilliary msg (cmsg) should be attached to recieved
|
||||
/// ancillary msg (cmsg) should be attached to received
|
||||
/// skbs indicating the number of packets dropped by the
|
||||
/// socket between the last recieved packet and this
|
||||
/// socket between the last received packet and this
|
||||
/// received packet.
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
RxqOvfl(&'a u32),
|
||||
@@ -1152,14 +1337,34 @@ pub enum ControlMessage<'a> {
|
||||
/// page.
|
||||
#[cfg(target_os = "linux")]
|
||||
TxTime(&'a u64),
|
||||
|
||||
/// Configure DSCP / IP TOS for outgoing v4 packets.
|
||||
///
|
||||
/// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv4Tos(&'a u8),
|
||||
|
||||
/// Configure DSCP / IPv6 TCLASS for outgoing v6 packets.
|
||||
///
|
||||
/// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
Ipv6TClass(&'a i32),
|
||||
}
|
||||
|
||||
// An opaque structure used to prevent cmsghdr from being a public type
|
||||
#[doc(hidden)]
|
||||
/// Control messages that are currently not supported by Nix.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct UnknownCmsg(cmsghdr, Vec<u8>);
|
||||
pub struct UnknownCmsg {
|
||||
/// Control message header.
|
||||
pub cmsg_header: cmsghdr,
|
||||
/// Bytes of the control message data.
|
||||
pub data_bytes: Vec<u8>
|
||||
}
|
||||
|
||||
impl<'a> ControlMessage<'a> {
|
||||
impl ControlMessage<'_> {
|
||||
/// The value of CMSG_SPACE on this message.
|
||||
/// Safe because CMSG_SPACE is always safe
|
||||
fn space(&self) -> usize {
|
||||
@@ -1169,13 +1374,15 @@ impl<'a> ControlMessage<'a> {
|
||||
/// The value of CMSG_LEN on this message.
|
||||
/// Safe because CMSG_LEN is always safe
|
||||
#[cfg(any(target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "musl"))))]
|
||||
all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
|
||||
target_os = "cygwin"))]
|
||||
fn cmsg_len(&self) -> usize {
|
||||
unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "musl")))))]
|
||||
all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
|
||||
target_os = "cygwin")))]
|
||||
fn cmsg_len(&self) -> libc::c_uint {
|
||||
unsafe{CMSG_LEN(self.len() as libc::c_uint)}
|
||||
}
|
||||
@@ -1245,6 +1452,12 @@ impl<'a> ControlMessage<'a> {
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
|
||||
#[cfg(linux_android)]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Ttl(ttl) => ttl as *const i32 as *const u8,
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Ttl(ttl) => ttl as *const u8,
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8,
|
||||
@@ -1256,6 +1469,16 @@ impl<'a> ControlMessage<'a> {
|
||||
ControlMessage::TxTime(tx_time) => {
|
||||
tx_time as *const _ as *const u8
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Tos(tos) => {
|
||||
tos as *const _
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6TClass(tclass) => {
|
||||
tclass as *const _ as *const u8
|
||||
},
|
||||
};
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
@@ -1307,6 +1530,11 @@ impl<'a> ControlMessage<'a> {
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Ttl(ttl) => {
|
||||
mem::size_of_val(ttl)
|
||||
},
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6HopLimit(limit) => {
|
||||
@@ -1320,6 +1548,16 @@ impl<'a> ControlMessage<'a> {
|
||||
ControlMessage::TxTime(tx_time) => {
|
||||
mem::size_of_val(tx_time)
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Tos(tos) => {
|
||||
mem::size_of_val(tos)
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6TClass(tclass) => {
|
||||
mem::size_of_val(tclass)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1347,6 +1585,9 @@ impl<'a> ControlMessage<'a> {
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Ttl(_) => libc::IPPROTO_IP,
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6,
|
||||
@@ -1354,6 +1595,12 @@ impl<'a> ControlMessage<'a> {
|
||||
ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
|
||||
#[cfg(target_os = "linux")]
|
||||
ControlMessage::TxTime(_) => libc::SOL_SOCKET,
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Tos(_) => libc::IPPROTO_IP,
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6TClass(_) => libc::IPPROTO_IPV6,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1392,6 +1639,9 @@ impl<'a> ControlMessage<'a> {
|
||||
#[cfg(any(freebsdlike, netbsdlike))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Ttl(_) => libc::IP_TTL,
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT,
|
||||
@@ -1403,6 +1653,16 @@ impl<'a> ControlMessage<'a> {
|
||||
ControlMessage::TxTime(_) => {
|
||||
libc::SCM_TXTIME
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv4Tos(_) => {
|
||||
libc::IP_TOS
|
||||
},
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
ControlMessage::Ipv6TClass(_) => {
|
||||
libc::IPV6_TCLASS
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,6 +1703,7 @@ impl<'a> ControlMessage<'a> {
|
||||
/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
|
||||
/// ```
|
||||
/// When directing to a specific address, the generic type will be inferred.
|
||||
/// Note that SCM_RIGHTS ancillary data are valid only for AF_UNIX sockets on Solaris.
|
||||
/// ```
|
||||
/// # use nix::sys::socket::*;
|
||||
/// # use nix::unistd::pipe;
|
||||
@@ -1457,6 +1718,7 @@ impl<'a> ControlMessage<'a> {
|
||||
/// let iov = [IoSlice::new(b"hello")];
|
||||
/// let fds = [r.as_raw_fd()];
|
||||
/// let cmsg = ControlMessage::ScmRights(&fds);
|
||||
/// #[cfg(not(target_os = "solaris"))]
|
||||
/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
|
||||
/// ```
|
||||
pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
|
||||
@@ -1643,11 +1905,9 @@ impl<S> MultiHeaders<S> {
|
||||
/// call to recvmmsg(). In the current implementation, however, the error code can be
|
||||
/// overwritten in the meantime by an unrelated network event on a socket, for example an
|
||||
/// incoming ICMP packet.
|
||||
|
||||
// On aarch64 linux using recvmmsg and trying to get hardware/kernel timestamps might not
|
||||
// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
|
||||
// details
|
||||
|
||||
#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
|
||||
pub fn recvmmsg<'a, XS, S, I>(
|
||||
fd: RawFd,
|
||||
@@ -1844,7 +2104,10 @@ unsafe fn pack_mhdr_to_receive<S>(
|
||||
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
|
||||
let p = mhdr.as_mut_ptr();
|
||||
unsafe {
|
||||
(*p).msg_name = address as *mut c_void;
|
||||
// it is important to use as_mut_ptr() here since S can be
|
||||
// a zero sized type representing by a dangling pointer.
|
||||
// as_mut_ptr() handles this case and uses a null pointer instead
|
||||
(*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
|
||||
(*p).msg_namelen = S::size();
|
||||
(*p).msg_iov = iov_buffer as *mut iovec;
|
||||
(*p).msg_iovlen = iov_buffer_len as _;
|
||||
@@ -1923,7 +2186,7 @@ fn pack_mhdr_to_send<'a, I, C, S>(
|
||||
/// # References
|
||||
/// [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>>,
|
||||
mut cmsg_buffer: Option<&'a mut [u8]>,
|
||||
flags: MsgFlags) -> Result<RecvMsg<'a, 'outer, S>>
|
||||
where S: SockaddrLike + 'a,
|
||||
'inner: 'outer
|
||||
@@ -1931,7 +2194,7 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i
|
||||
let mut address = mem::MaybeUninit::uninit();
|
||||
|
||||
let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
|
||||
.map(|v| (v.as_mut_ptr(), v.capacity()))
|
||||
.map(|v| (v.as_mut_ptr(), v.len()))
|
||||
.unwrap_or((ptr::null_mut(), 0));
|
||||
let mut mhdr = unsafe {
|
||||
pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
|
||||
@@ -2036,7 +2299,7 @@ impl Backlog {
|
||||
|
||||
let val = val.into();
|
||||
|
||||
if !(MIN..Self::MAXCONN.0).contains(&val) {
|
||||
if !(MIN..=Self::MAXCONN.0).contains(&val) {
|
||||
return Err(Errno::EINVAL);
|
||||
}
|
||||
|
||||
@@ -2207,7 +2470,7 @@ pub trait GetSockOpt: Copy {
|
||||
|
||||
/// Represents a socket option that can be set.
|
||||
pub trait SetSockOpt: Clone {
|
||||
type Val;
|
||||
type Val: ?Sized;
|
||||
|
||||
/// Set the value of this socket option on the given socket.
|
||||
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()>;
|
||||
@@ -2302,4 +2565,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
|
||||
Errno::result(shutdown(df, how)).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
569
third_party/rust/nix/src/sys/socket/sockopt.rs
vendored
569
third_party/rust/nix/src/sys/socket/sockopt.rs
vendored
@@ -1,13 +1,18 @@
|
||||
//! Socket options as used by `setsockopt` and `getsockopt`.
|
||||
use super::{GetSockOpt, SetSockOpt};
|
||||
use crate::errno::Errno;
|
||||
#[cfg(any(linux_android, target_os = "illumos"))]
|
||||
use super::SetSockOpt;
|
||||
use crate::sys::time::TimeVal;
|
||||
use crate::Result;
|
||||
#[cfg(any(linux_android, target_os = "illumos"))]
|
||||
use crate::{errno::Errno, Result};
|
||||
use cfg_if::cfg_if;
|
||||
use libc::{self, c_int, c_void, socklen_t};
|
||||
use std::ffi::{CStr, CString, OsStr, OsString};
|
||||
#[cfg(apple_targets)]
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CStr, OsStr, OsString};
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(any(linux_android, target_os = "illumos"))]
|
||||
use std::os::unix::io::{AsFd, AsRawFd};
|
||||
|
||||
// Constants
|
||||
@@ -22,40 +27,49 @@ const TCP_CA_NAME_MAX: usize = 16;
|
||||
/// This macro aims to help implementing `SetSockOpt` for different socket options that accept
|
||||
/// different kinds of data to be used with `setsockopt`.
|
||||
///
|
||||
/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
|
||||
/// you are implementing represents a simple type.
|
||||
/// Instead of using this macro directly consider using [`sockopt_impl!`](crate::sockopt_impl),
|
||||
/// especially if the option you are implementing represents a simple type.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
|
||||
/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
|
||||
/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
|
||||
/// and more. Please refer to your system manual for more options. Will be passed as the second
|
||||
/// argument (`level`) to the `setsockopt` call.
|
||||
/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
|
||||
/// and more. Please refer to your system manual for more options. Will be passed as the second
|
||||
/// argument (`level`) to the `setsockopt` call.
|
||||
/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
|
||||
/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
|
||||
/// to the `setsockopt` call.
|
||||
/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
|
||||
/// to the `setsockopt` call.
|
||||
/// * Type of the value that you are going to set.
|
||||
/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
|
||||
/// `bool`, `SetUsize` for `usize`, etc.).
|
||||
/// * Type that implements the `Set` trait for the type from the previous item
|
||||
/// (like `SetBool` for `bool`, `SetUsize` for `usize`, etc.).
|
||||
#[macro_export]
|
||||
macro_rules! setsockopt_impl {
|
||||
($name:ident, $level:expr, $flag:path, $ty:ty, $setter:ty) => {
|
||||
impl SetSockOpt for $name {
|
||||
#[allow(deprecated)] // to allow we have deprecated socket option
|
||||
impl $crate::sys::socket::SetSockOpt for $name {
|
||||
type Val = $ty;
|
||||
|
||||
fn set<F: AsFd>(&self, fd: &F, val: &$ty) -> Result<()> {
|
||||
unsafe {
|
||||
let setter: $setter = Set::new(val);
|
||||
|
||||
let res = libc::setsockopt(
|
||||
fn set<F: std::os::unix::io::AsFd>(
|
||||
&self,
|
||||
fd: &F,
|
||||
val: &$ty,
|
||||
) -> $crate::Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
use $crate::sys::socket::sockopt::Set;
|
||||
let setter: $setter = Set::new(val);
|
||||
let level = $level;
|
||||
let flag = $flag;
|
||||
let res = unsafe {
|
||||
libc::setsockopt(
|
||||
fd.as_fd().as_raw_fd(),
|
||||
$level,
|
||||
$flag,
|
||||
level,
|
||||
flag,
|
||||
setter.ffi_ptr(),
|
||||
setter.ffi_len(),
|
||||
);
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
)
|
||||
};
|
||||
$crate::errno::Errno::result(res).map(drop)
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -67,44 +81,68 @@ macro_rules! setsockopt_impl {
|
||||
/// This macro aims to help implementing `GetSockOpt` for different socket options that accept
|
||||
/// different kinds of data to be use with `getsockopt`.
|
||||
///
|
||||
/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
|
||||
/// you are implementing represents a simple type.
|
||||
/// Instead of using this macro directly consider using [`sockopt_impl!`](crate::sockopt_impl),
|
||||
/// especially if the option you are implementing represents a simple type.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * Name of the type you want to implement `GetSockOpt` for.
|
||||
/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`), *ip
|
||||
/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer
|
||||
/// to your system manual for more options. Will be passed as the second argument (`level`) to
|
||||
/// the `getsockopt` call.
|
||||
/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer
|
||||
/// to your system manual for more options. Will be passed as the second argument (`level`) to
|
||||
/// the `getsockopt` call.
|
||||
/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
|
||||
/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
|
||||
/// the `getsockopt` call.
|
||||
/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
|
||||
/// the `getsockopt` call.
|
||||
/// * Type of the value that you are going to get.
|
||||
/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
|
||||
/// `bool`, `GetUsize` for `usize`, etc.).
|
||||
/// `bool`, `GetUsize` for `usize`, etc.).
|
||||
#[macro_export]
|
||||
macro_rules! getsockopt_impl {
|
||||
($name:ident, $level:expr, $flag:path, $ty:ty, $getter:ty) => {
|
||||
impl GetSockOpt for $name {
|
||||
#[allow(deprecated)] // to allow we have deprecated socket option
|
||||
impl $crate::sys::socket::GetSockOpt for $name {
|
||||
type Val = $ty;
|
||||
|
||||
fn get<F: AsFd>(&self, fd: &F) -> Result<$ty> {
|
||||
unsafe {
|
||||
let mut getter: $getter = Get::uninit();
|
||||
|
||||
let res = libc::getsockopt(
|
||||
fn get<F: std::os::unix::io::AsFd>(
|
||||
&self,
|
||||
fd: &F,
|
||||
) -> $crate::Result<$ty> {
|
||||
use std::os::fd::AsRawFd;
|
||||
use $crate::sys::socket::sockopt::Get;
|
||||
let mut getter: $getter = Get::uninit();
|
||||
let level = $level;
|
||||
let flag = $flag;
|
||||
let res = unsafe {
|
||||
libc::getsockopt(
|
||||
fd.as_fd().as_raw_fd(),
|
||||
$level,
|
||||
$flag,
|
||||
level,
|
||||
flag,
|
||||
getter.ffi_ptr(),
|
||||
getter.ffi_len(),
|
||||
);
|
||||
Errno::result(res)?;
|
||||
)
|
||||
};
|
||||
$crate::errno::Errno::result(res)?;
|
||||
|
||||
match <$ty>::try_from(getter.assume_init()) {
|
||||
Err(_) => Err(Errno::EINVAL),
|
||||
Ok(r) => Ok(r),
|
||||
}
|
||||
// getter is definitely initialized now
|
||||
let gotten = unsafe { getter.assume_init() };
|
||||
match <$ty>::try_from(gotten) {
|
||||
// In most `getsockopt_impl!` implementations, `assume_init()`
|
||||
// returns `$ty`, so calling `$ty`::try_from($ty) will always
|
||||
// succeed. which makes the following `Err(_)` branch
|
||||
// unreachable.
|
||||
//
|
||||
// However, there is indeed one exception, `sockopt::SockType`,
|
||||
// `assume_init()` returns an `i32`, but `$ty` is `super::SockType`,
|
||||
// this exception necessitates the use of that `try_from()`,
|
||||
// and we have to allow the unreachable pattern wraning.
|
||||
//
|
||||
// For the reason why we are using `i32` as the underlying
|
||||
// buffer type for this socket option, see issue:
|
||||
// https://github.com/nix-rust/nix/issues/1819
|
||||
#[allow(unreachable_patterns)]
|
||||
Err(_) => Err($crate::errno::Errno::EINVAL),
|
||||
Ok(r) => Ok(r),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,72 +162,90 @@ macro_rules! getsockopt_impl {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
|
||||
/// both of them.
|
||||
/// both of them.
|
||||
/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
|
||||
/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
|
||||
/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
|
||||
/// and more. Please refer to your system manual for more options. Will be passed as the second
|
||||
/// argument (`level`) to the `getsockopt`/`setsockopt` call.
|
||||
/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
|
||||
/// and more. Please refer to your system manual for more options. Will be passed as the second
|
||||
/// argument (`level`) to the `getsockopt`/`setsockopt` call.
|
||||
/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
|
||||
/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
|
||||
/// to the `setsockopt`/`getsockopt` call.
|
||||
/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
|
||||
/// to the `setsockopt`/`getsockopt` call.
|
||||
/// * `$ty:ty`: type of the value that will be get/set.
|
||||
/// * `$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(unused_macro_rules)]
|
||||
#[macro_export]
|
||||
macro_rules! sockopt_impl {
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, GetOnly, $level, $flag, bool, GetBool);
|
||||
$name, GetOnly, $level, $flag, bool, $crate::sys::socket::sockopt::GetBool);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, u8) => {
|
||||
sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, GetU8);
|
||||
sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, $crate::sys::socket::sockopt::GetU8);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, usize) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, GetOnly, $level, $flag, usize, GetUsize);
|
||||
$name, GetOnly, $level, $flag, usize, $crate::sys::socket::sockopt::GetUsize);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, OwnedFd) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, GetOnly, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::GetOwnedFd);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, bool) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, SetOnly, $level, $flag, bool, SetBool);
|
||||
$name, SetOnly, $level, $flag, bool, $crate::sys::socket::sockopt::SetBool);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, u8) => {
|
||||
sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, SetU8);
|
||||
sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, $crate::sys::socket::sockopt::SetU8);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, usize) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, SetOnly, $level, $flag, usize, SetUsize);
|
||||
$name, SetOnly, $level, $flag, usize, $crate::sys::socket::sockopt::SetUsize);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, OwnedFd) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, SetOnly, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::SetOwnedFd);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, bool) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, bool, GetBool, SetBool);
|
||||
$name, Both, $level, $flag, bool, $crate::sys::socket::sockopt::GetBool, $crate::sys::socket::sockopt::SetBool);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, u8) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, u8, GetU8, SetU8);
|
||||
$name, Both, $level, $flag, u8, $crate::sys::socket::sockopt::GetU8, $crate::sys::socket::sockopt::SetU8);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, usize) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, usize, GetUsize, SetUsize);
|
||||
$name, Both, $level, $flag, usize, $crate::sys::socket::sockopt::GetUsize, $crate::sys::socket::sockopt::SetUsize);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, OwnedFd) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, OwnedFd, $crate::sys::socket::sockopt::GetOwnedFd, $crate::sys::socket::sockopt::SetOwnedFd);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path,
|
||||
OsString<$array:ty>) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, OsString, GetOsString<$array>,
|
||||
SetOsString);
|
||||
$name, Both, $level, $flag, std::ffi::OsString, $crate::sys::socket::sockopt::GetOsString<$array>,
|
||||
$crate::sys::socket::sockopt::SetOsString);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -199,7 +255,7 @@ macro_rules! sockopt_impl {
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, GetOnly, $level, $flag, $ty, GetStruct<$ty>);
|
||||
$name, GetOnly, $level, $flag, $ty, $crate::sys::socket::sockopt::GetStruct<$ty>);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty,
|
||||
@@ -215,7 +271,7 @@ macro_rules! sockopt_impl {
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty) =>
|
||||
{
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, SetOnly, $level, $flag, $ty, SetStruct<$ty>);
|
||||
$name, SetOnly, $level, $flag, $ty, $crate::sys::socket::sockopt::SetStruct<$ty>);
|
||||
};
|
||||
|
||||
($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty,
|
||||
@@ -241,8 +297,8 @@ macro_rules! sockopt_impl {
|
||||
|
||||
($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty) => {
|
||||
sockopt_impl!($(#[$attr])*
|
||||
$name, Both, $level, $flag, $ty, GetStruct<$ty>,
|
||||
SetStruct<$ty>);
|
||||
$name, Both, $level, $flag, $ty, $crate::sys::socket::sockopt::GetStruct<$ty>,
|
||||
$crate::sys::socket::sockopt::SetStruct<$ty>);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -260,7 +316,7 @@ sockopt_impl!(
|
||||
libc::SO_REUSEADDR,
|
||||
bool
|
||||
);
|
||||
#[cfg(not(solarish))]
|
||||
#[cfg(not(any(solarish, target_os = "cygwin")))]
|
||||
sockopt_impl!(
|
||||
/// Permits multiple AF_INET or AF_INET6 sockets to be bound to an
|
||||
/// identical socket address.
|
||||
@@ -280,16 +336,44 @@ sockopt_impl!(
|
||||
libc::SO_REUSEPORT_LB,
|
||||
bool
|
||||
);
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Select or query the set of functions that TCP will use for this connection. This allows a
|
||||
/// user to select an alternate TCP stack.
|
||||
TcpFunctionBlk,
|
||||
Both,
|
||||
libc::IPPROTO_TCP,
|
||||
libc::TCP_FUNCTION_BLK,
|
||||
libc::tcp_function_set
|
||||
);
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Query the alias name of the set of function of the socket's TCP stack.
|
||||
/// Uses the same field for the main name when getting from TCP_FUNCTION_BLK.
|
||||
/// Empty if no alias.
|
||||
TcpFunctionAlias,
|
||||
GetOnly,
|
||||
libc::IPPROTO_TCP,
|
||||
libc::TCP_FUNCTION_ALIAS,
|
||||
libc::tcp_function_set
|
||||
);
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Used to disable Nagle's algorithm.
|
||||
///
|
||||
/// Nagle's algorithm:
|
||||
///
|
||||
/// Under most circumstances, TCP sends data when it is presented; when
|
||||
/// outstanding data has not yet been acknowledged, it gathers small amounts
|
||||
/// of output to be sent in a single packet once an acknowledgement is
|
||||
/// received. For a small number of clients, such as window systems that
|
||||
/// send a stream of mouse events which receive no replies, this
|
||||
/// packetization may cause significant delays. The boolean option
|
||||
/// TCP_NODELAY defeats this algorithm.
|
||||
/// packetization may cause significant delays. The boolean option, when
|
||||
/// enabled, defeats this algorithm.
|
||||
TcpNoDelay,
|
||||
Both,
|
||||
libc::IPPROTO_TCP,
|
||||
@@ -297,7 +381,7 @@ sockopt_impl!(
|
||||
bool
|
||||
);
|
||||
sockopt_impl!(
|
||||
/// When enabled, a close(2) or shutdown(2) will not return until all
|
||||
/// When enabled, a close(2) or shutdown(2) will not return until all
|
||||
/// queued messages for the socket have been successfully sent or the
|
||||
/// linger timeout has been reached.
|
||||
Linger,
|
||||
@@ -306,6 +390,15 @@ sockopt_impl!(
|
||||
libc::SO_LINGER,
|
||||
libc::linger
|
||||
);
|
||||
#[cfg(apple_targets)]
|
||||
sockopt_impl!(
|
||||
/// Same as `SO_LINGER`, but the duration is in seconds rather than kernel ticks.
|
||||
LingerSec,
|
||||
Both,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_LINGER_SEC,
|
||||
libc::linger
|
||||
);
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
@@ -398,9 +491,10 @@ sockopt_impl!(
|
||||
libc::SO_PRIORITY,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[deprecated(since = "0.30.0", note = "Use Ipv4Tos instead")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Set or receive the Type-Of-Service (TOS) field that is
|
||||
/// sent with every IP packet originating from this socket
|
||||
@@ -410,17 +504,51 @@ sockopt_impl!(
|
||||
libc::IP_TOS,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Traffic class associated with outgoing packets
|
||||
/// Set or receive the Type-Of-Service (TOS) field that is
|
||||
/// sent with every IP packet originating from this socket
|
||||
Ipv4Tos,
|
||||
Both,
|
||||
libc::IPPROTO_IP,
|
||||
libc::IP_TOS,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// If enabled, the IP_TOS ancillary message is passed with incoming packets.
|
||||
IpRecvTos,
|
||||
Both,
|
||||
libc::IPPROTO_IP,
|
||||
libc::IP_RECVTOS,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Set the traffic class associated with outgoing packets.
|
||||
Ipv6TClass,
|
||||
Both,
|
||||
libc::IPPROTO_IPV6,
|
||||
libc::IPV6_TCLASS,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// If enabled, the IPV6_TCLASS ancillary message is passed with incoming packets.
|
||||
Ipv6RecvTClass,
|
||||
Both,
|
||||
libc::IPPROTO_IPV6,
|
||||
libc::IPV6_RECVTCLASS,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "fuchsia"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
@@ -504,7 +632,7 @@ sockopt_impl!(
|
||||
libc::SO_KEEPALIVE,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(freebsdlike, apple_targets))]
|
||||
#[cfg(freebsdlike)]
|
||||
sockopt_impl!(
|
||||
/// Get the credentials of the peer process of a connected unix domain
|
||||
/// socket.
|
||||
@@ -515,14 +643,34 @@ sockopt_impl!(
|
||||
super::XuCred
|
||||
);
|
||||
#[cfg(apple_targets)]
|
||||
sockopt_impl!(
|
||||
/// Get the credentials of the peer process of a connected unix domain
|
||||
/// socket.
|
||||
LocalPeerCred,
|
||||
GetOnly,
|
||||
libc::SOL_LOCAL,
|
||||
libc::LOCAL_PEERCRED,
|
||||
super::XuCred
|
||||
);
|
||||
#[cfg(apple_targets)]
|
||||
sockopt_impl!(
|
||||
/// Get the PID of the peer process of a connected unix domain socket.
|
||||
LocalPeerPid,
|
||||
GetOnly,
|
||||
0,
|
||||
libc::SOL_LOCAL,
|
||||
libc::LOCAL_PEERPID,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(apple_targets)]
|
||||
sockopt_impl!(
|
||||
/// Get the audit token of the peer process of a connected unix domain
|
||||
/// socket.
|
||||
LocalPeerToken,
|
||||
GetOnly,
|
||||
libc::SOL_LOCAL,
|
||||
libc::LOCAL_PEERTOKEN,
|
||||
super::audit_token_t
|
||||
);
|
||||
#[cfg(linux_android)]
|
||||
sockopt_impl!(
|
||||
/// Return the credentials of the foreign process connected to this socket.
|
||||
@@ -532,6 +680,15 @@ sockopt_impl!(
|
||||
libc::SO_PEERCRED,
|
||||
super::UnixCredentials
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
sockopt_impl!(
|
||||
/// Return the pidfd of the foreign process connected to this socket.
|
||||
PeerPidfd,
|
||||
GetOnly,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_PEERPIDFD,
|
||||
OwnedFd
|
||||
);
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
@@ -568,7 +725,7 @@ sockopt_impl!(
|
||||
u32
|
||||
);
|
||||
cfg_if! {
|
||||
if #[cfg(linux_android)] {
|
||||
if #[cfg(any(linux_android, apple_targets))] {
|
||||
sockopt_impl!(
|
||||
/// The maximum segment size for outgoing TCP packets.
|
||||
TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
|
||||
@@ -749,7 +906,13 @@ sockopt_impl!(
|
||||
libc::SO_TIMESTAMPING,
|
||||
super::TimestampingFlag
|
||||
);
|
||||
#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "hurd", target_os = "redox")))]
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "redox",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
sockopt_impl!(
|
||||
/// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
|
||||
ReceiveTimestamp,
|
||||
@@ -896,7 +1059,7 @@ sockopt_impl!(
|
||||
libc::IP_PKTINFO,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))]
|
||||
#[cfg(any(linux_android, bsd))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
@@ -908,6 +1071,19 @@ sockopt_impl!(
|
||||
libc::IPV6_RECVPKTINFO,
|
||||
bool
|
||||
);
|
||||
|
||||
#[cfg(any(linux_android, bsd))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// Pass an `IPV6_PKTINFO` ancillary message that contains a in6_pktinfo
|
||||
/// structure that supplies some information about the incoming packet.
|
||||
Ipv6PacketInfo,
|
||||
Both,
|
||||
libc::IPPROTO_IPV6,
|
||||
libc::IPV6_PKTINFO,
|
||||
bool
|
||||
);
|
||||
#[cfg(bsd)]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
@@ -1036,6 +1212,17 @@ sockopt_impl!(
|
||||
libc::IP_TTL,
|
||||
libc::c_int
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
/// Enables a receiving socket to retrieve the Time-to-Live (TTL) field
|
||||
/// from incoming IPv4 packets.
|
||||
Ipv4RecvTtl,
|
||||
Both,
|
||||
libc::IPPROTO_IP,
|
||||
libc::IP_RECVTTL,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(apple_targets, linux_android, target_os = "freebsd"))]
|
||||
sockopt_impl!(
|
||||
/// Set the unicast hop limit for the socket.
|
||||
@@ -1047,6 +1234,17 @@ sockopt_impl!(
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
/// Enables a receiving socket to retrieve the Hop Limit field
|
||||
/// (similar to TTL in IPv4) from incoming IPv6 packets.
|
||||
Ipv6RecvHopLimit,
|
||||
Both,
|
||||
libc::IPPROTO_IPV6,
|
||||
libc::IPV6_RECVHOPLIMIT,
|
||||
bool
|
||||
);
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
sockopt_impl!(
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
|
||||
/// The `recvmsg(2)` call will return the destination IP address for a UDP
|
||||
@@ -1087,6 +1285,30 @@ sockopt_impl!(
|
||||
GetCString<[u8; libc::IFNAMSIZ]>
|
||||
);
|
||||
|
||||
#[cfg(solarish)]
|
||||
sockopt_impl!(
|
||||
/// Enable/disable exclusive binding.
|
||||
/// Prevent multiple sockets to bind to the same
|
||||
/// address:port, neutralizing `SO_REUSEADDR` effect.
|
||||
ExclBind,
|
||||
Both,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_EXCLBIND,
|
||||
bool
|
||||
);
|
||||
#[cfg(target_os = "linux")]
|
||||
sockopt_impl!(
|
||||
/// To be used with `ReusePort`,
|
||||
/// we can then attach a BPF (classic)
|
||||
/// to set how the packets are assigned
|
||||
/// to the socket (e.g. cpu distribution).
|
||||
AttachReusePortCbpf,
|
||||
SetOnly,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_ATTACH_REUSEPORT_CBPF,
|
||||
libc::sock_fprog
|
||||
);
|
||||
|
||||
#[allow(missing_docs)]
|
||||
// Not documented by Linux!
|
||||
#[cfg(linux_android)]
|
||||
@@ -1300,7 +1522,58 @@ impl SetSockOpt for TcpTlsRx {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// Attach a named filter to this socket to be able to
|
||||
/// defer when anough byte had been buffered by the kernel
|
||||
pub struct FilterAttach;
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
impl SetSockOpt for FilterAttach {
|
||||
type Val = OsStr;
|
||||
|
||||
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
|
||||
if val.len() > libc::FILNAME_MAX as usize {
|
||||
return Err(Errno::EINVAL);
|
||||
}
|
||||
unsafe {
|
||||
let res = libc::setsockopt(
|
||||
fd.as_fd().as_raw_fd(),
|
||||
libc::SOL_FILTER,
|
||||
libc::FIL_ATTACH,
|
||||
val.as_bytes().as_ptr().cast(),
|
||||
val.len() as libc::socklen_t,
|
||||
);
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// Detach a socket filter previously attached with FIL_ATTACH
|
||||
pub struct FilterDetach;
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
impl SetSockOpt for FilterDetach {
|
||||
type Val = OsStr;
|
||||
|
||||
fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> {
|
||||
if val.len() > libc::FILNAME_MAX as usize {
|
||||
return Err(Errno::EINVAL);
|
||||
}
|
||||
unsafe {
|
||||
let res = libc::setsockopt(
|
||||
fd.as_fd().as_raw_fd(),
|
||||
libc::SOL_FILTER,
|
||||
libc::FIL_DETACH,
|
||||
val.as_bytes().as_ptr().cast(),
|
||||
val.len() as libc::socklen_t,
|
||||
);
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
* ===== Accessor helpers =====
|
||||
@@ -1308,7 +1581,9 @@ impl SetSockOpt for TcpTlsRx {
|
||||
*/
|
||||
|
||||
/// Helper trait that describes what is expected from a `GetSockOpt` getter.
|
||||
trait Get<T> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
pub trait Get<T> {
|
||||
/// Returns an uninitialized value.
|
||||
fn uninit() -> Self;
|
||||
/// Returns a pointer to the stored value. This pointer will be passed to the system's
|
||||
@@ -1322,7 +1597,9 @@ trait Get<T> {
|
||||
}
|
||||
|
||||
/// Helper trait that describes what is expected from a `SetSockOpt` setter.
|
||||
trait Set<'a, T> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
pub trait Set<'a, T> {
|
||||
/// Initialize the setter with a given value.
|
||||
fn new(val: &'a T) -> Self;
|
||||
/// Returns a pointer to the stored value. This pointer will be passed to the system's
|
||||
@@ -1334,7 +1611,10 @@ trait Set<'a, T> {
|
||||
}
|
||||
|
||||
/// Getter for an arbitrary `struct`.
|
||||
struct GetStruct<T> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
pub struct GetStruct<T> {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<T>,
|
||||
}
|
||||
@@ -1366,7 +1646,10 @@ impl<T> Get<T> for GetStruct<T> {
|
||||
}
|
||||
|
||||
/// Setter for an arbitrary `struct`.
|
||||
struct SetStruct<'a, T: 'static> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
pub struct SetStruct<'a, T: 'static> {
|
||||
ptr: &'a T,
|
||||
}
|
||||
|
||||
@@ -1385,7 +1668,10 @@ impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
|
||||
}
|
||||
|
||||
/// Getter for a boolean value.
|
||||
struct GetBool {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct GetBool {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<c_int>,
|
||||
}
|
||||
@@ -1417,7 +1703,10 @@ impl Get<bool> for GetBool {
|
||||
}
|
||||
|
||||
/// Setter for a boolean value.
|
||||
struct SetBool {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct SetBool {
|
||||
val: c_int,
|
||||
}
|
||||
|
||||
@@ -1438,11 +1727,16 @@ impl<'a> Set<'a, bool> for SetBool {
|
||||
}
|
||||
|
||||
/// Getter for an `u8` value.
|
||||
struct GetU8 {
|
||||
#[cfg(feature = "net")]
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct GetU8 {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<u8>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl Get<u8> for GetU8 {
|
||||
fn uninit() -> Self {
|
||||
GetU8 {
|
||||
@@ -1470,10 +1764,14 @@ impl Get<u8> for GetU8 {
|
||||
}
|
||||
|
||||
/// Setter for an `u8` value.
|
||||
struct SetU8 {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct SetU8 {
|
||||
val: u8,
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a> Set<'a, u8> for SetU8 {
|
||||
fn new(val: &'a u8) -> SetU8 {
|
||||
SetU8 { val: *val }
|
||||
@@ -1489,7 +1787,10 @@ impl<'a> Set<'a, u8> for SetU8 {
|
||||
}
|
||||
|
||||
/// Getter for an `usize` value.
|
||||
struct GetUsize {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct GetUsize {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<c_int>,
|
||||
}
|
||||
@@ -1521,7 +1822,10 @@ impl Get<usize> for GetUsize {
|
||||
}
|
||||
|
||||
/// Setter for an `usize` value.
|
||||
struct SetUsize {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct SetUsize {
|
||||
val: c_int,
|
||||
}
|
||||
|
||||
@@ -1539,8 +1843,73 @@ impl<'a> Set<'a, usize> for SetUsize {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Getter for a `OwnedFd` value.
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct GetOwnedFd {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<c_int>,
|
||||
}
|
||||
|
||||
impl Get<OwnedFd> for GetOwnedFd {
|
||||
fn uninit() -> Self {
|
||||
GetOwnedFd {
|
||||
len: mem::size_of::<c_int>() as socklen_t,
|
||||
val: MaybeUninit::uninit(),
|
||||
}
|
||||
}
|
||||
|
||||
fn ffi_ptr(&mut self) -> *mut c_void {
|
||||
self.val.as_mut_ptr().cast()
|
||||
}
|
||||
|
||||
fn ffi_len(&mut self) -> *mut socklen_t {
|
||||
&mut self.len
|
||||
}
|
||||
|
||||
unsafe fn assume_init(self) -> OwnedFd {
|
||||
use std::os::fd::{FromRawFd, RawFd};
|
||||
|
||||
assert_eq!(
|
||||
self.len as usize,
|
||||
mem::size_of::<c_int>(),
|
||||
"invalid getsockopt implementation"
|
||||
);
|
||||
unsafe { OwnedFd::from_raw_fd(self.val.assume_init() as RawFd) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Setter for an `OwnedFd` value.
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct SetOwnedFd {
|
||||
val: c_int,
|
||||
}
|
||||
|
||||
impl<'a> Set<'a, OwnedFd> for SetOwnedFd {
|
||||
fn new(val: &'a OwnedFd) -> SetOwnedFd {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
SetOwnedFd { val: val.as_raw_fd() as c_int }
|
||||
}
|
||||
|
||||
fn ffi_ptr(&self) -> *const c_void {
|
||||
&self.val as *const c_int as *const c_void
|
||||
}
|
||||
|
||||
fn ffi_len(&self) -> socklen_t {
|
||||
mem::size_of_val(&self.val) as socklen_t
|
||||
}
|
||||
}
|
||||
|
||||
/// Getter for a `OsString` value.
|
||||
struct GetOsString<T: AsMut<[u8]>> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
pub struct GetOsString<T: AsMut<[u8]>> {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<T>,
|
||||
}
|
||||
@@ -1564,17 +1933,29 @@ impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
|
||||
unsafe fn assume_init(self) -> OsString {
|
||||
let len = self.len as usize;
|
||||
let mut v = unsafe { self.val.assume_init() };
|
||||
OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
|
||||
if let Ok(cs) = CStr::from_bytes_until_nul(&v.as_mut()[0..len]) {
|
||||
// It's legal for the kernel to return any number of NULs at the
|
||||
// end of the string. C applications don't care, after all.
|
||||
OsStr::from_bytes(cs.to_bytes())
|
||||
} else {
|
||||
// Even zero NULs is possible.
|
||||
OsStr::from_bytes(&v.as_mut()[0..len])
|
||||
}
|
||||
.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
/// Setter for a `OsString` value.
|
||||
struct SetOsString<'a> {
|
||||
// Hide the docs, because it's an implementation detail of `sockopt_impl!`
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct SetOsString<'a> {
|
||||
val: &'a OsStr,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd", linux_android, target_os = "illumos"))]
|
||||
impl<'a> Set<'a, OsString> for SetOsString<'a> {
|
||||
fn new(val: &'a OsString) -> SetOsString {
|
||||
fn new(val: &OsString) -> SetOsString {
|
||||
SetOsString {
|
||||
val: val.as_os_str(),
|
||||
}
|
||||
@@ -1590,11 +1971,13 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> {
|
||||
}
|
||||
|
||||
/// Getter for a `CString` value.
|
||||
#[cfg(apple_targets)]
|
||||
struct GetCString<T: AsMut<[u8]>> {
|
||||
len: socklen_t,
|
||||
val: MaybeUninit<T>,
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
impl<T: AsMut<[u8]>> Get<CString> for GetCString<T> {
|
||||
fn uninit() -> Self {
|
||||
GetCString {
|
||||
|
||||
89
third_party/rust/nix/src/sys/stat.rs
vendored
89
third_party/rust/nix/src/sys/stat.rs
vendored
@@ -6,11 +6,10 @@ pub use libc::stat as FileStat;
|
||||
pub use libc::{dev_t, mode_t};
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use crate::fcntl::{at_rawfd, AtFlags};
|
||||
use crate::fcntl::AtFlags;
|
||||
use crate::sys::time::{TimeSpec, TimeVal};
|
||||
use crate::{errno::Errno, NixPath, Result};
|
||||
use std::mem;
|
||||
use std::os::unix::io::RawFd;
|
||||
|
||||
libc_bitflags!(
|
||||
/// "File type" flags for `mknod` and related functions.
|
||||
@@ -168,17 +167,18 @@ pub fn mknod<P: ?Sized + NixPath>(
|
||||
|
||||
/// Create a special or ordinary file, relative to a given directory.
|
||||
#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
|
||||
pub fn mknodat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn mknodat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
kind: SFlag,
|
||||
perm: Mode,
|
||||
dev: dev_t,
|
||||
) -> Result<()> {
|
||||
let dirfd = at_rawfd(dirfd);
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = path.with_nix_path(|cstr| unsafe {
|
||||
libc::mknodat(
|
||||
dirfd,
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
kind.bits() | perm.bits() as mode_t,
|
||||
dev,
|
||||
@@ -233,9 +233,11 @@ pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
|
||||
Ok(unsafe { dst.assume_init() })
|
||||
}
|
||||
|
||||
pub fn fstat(fd: RawFd) -> Result<FileStat> {
|
||||
pub fn fstat<Fd: std::os::fd::AsFd>(fd: Fd) -> Result<FileStat> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let mut dst = mem::MaybeUninit::uninit();
|
||||
let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) };
|
||||
let res = unsafe { libc::fstat(fd.as_fd().as_raw_fd(), dst.as_mut_ptr()) };
|
||||
|
||||
Errno::result(res)?;
|
||||
|
||||
@@ -243,16 +245,17 @@ pub fn fstat(fd: RawFd) -> Result<FileStat> {
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn fstatat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn fstatat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
pathname: &P,
|
||||
f: AtFlags,
|
||||
) -> Result<FileStat> {
|
||||
let dirfd = at_rawfd(dirfd);
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let mut dst = mem::MaybeUninit::uninit();
|
||||
let res = pathname.with_nix_path(|cstr| unsafe {
|
||||
libc::fstatat(
|
||||
dirfd,
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
dst.as_mut_ptr(),
|
||||
f.bits() as libc::c_int,
|
||||
@@ -269,8 +272,11 @@ pub fn fstatat<P: ?Sized + NixPath>(
|
||||
/// # References
|
||||
///
|
||||
/// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
|
||||
pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
|
||||
let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
|
||||
pub fn fchmod<Fd: std::os::fd::AsFd>(fd: Fd, mode: Mode) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res =
|
||||
unsafe { libc::fchmod(fd.as_fd().as_raw_fd(), mode.bits() as mode_t) };
|
||||
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
@@ -286,12 +292,12 @@ pub enum FchmodatFlags {
|
||||
///
|
||||
/// The file to be changed is determined relative to the directory associated
|
||||
/// with the file descriptor `dirfd` or the current working directory
|
||||
/// if `dirfd` is `None`.
|
||||
/// if `dirfd` is [`AT_FDCWD`](crate::fcntl::AT_FDCWD).
|
||||
///
|
||||
/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
|
||||
/// then the mode of the symbolic link is changed.
|
||||
///
|
||||
/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
|
||||
/// `fchmodat(AT_FDCWD, path, mode, FchmodatFlags::FollowSymlink)` is identical to
|
||||
/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
|
||||
/// in the `nix` crate.
|
||||
///
|
||||
@@ -299,19 +305,21 @@ pub enum FchmodatFlags {
|
||||
///
|
||||
/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn fchmodat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn fchmodat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
mode: Mode,
|
||||
flag: FchmodatFlags,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let atflag = match flag {
|
||||
FchmodatFlags::FollowSymlink => AtFlags::empty(),
|
||||
FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||
};
|
||||
let res = path.with_nix_path(|cstr| unsafe {
|
||||
libc::fchmodat(
|
||||
at_rawfd(dirfd),
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
mode.bits() as mode_t,
|
||||
atflag.bits() as libc::c_int,
|
||||
@@ -383,9 +391,15 @@ pub fn lutimes<P: ?Sized + NixPath>(
|
||||
///
|
||||
/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
|
||||
#[inline]
|
||||
pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
|
||||
pub fn futimens<Fd: std::os::fd::AsFd>(
|
||||
fd: Fd,
|
||||
atime: &TimeSpec,
|
||||
mtime: &TimeSpec,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
|
||||
let res = unsafe { libc::futimens(fd, ×[0]) };
|
||||
let res = unsafe { libc::futimens(fd.as_fd().as_raw_fd(), ×[0]) };
|
||||
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
@@ -402,12 +416,12 @@ pub enum UtimensatFlags {
|
||||
///
|
||||
/// The file to be changed is determined relative to the directory associated
|
||||
/// with the file descriptor `dirfd` or the current working directory
|
||||
/// if `dirfd` is `None`.
|
||||
/// if `dirfd` is [`AT_FDCWD`](crate::fcntl::AT_FDCWD).
|
||||
///
|
||||
/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link,
|
||||
/// then the mode of the symbolic link is changed.
|
||||
///
|
||||
/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
|
||||
/// `utimensat(AT_FDCWD, path, times, UtimensatFlags::FollowSymlink)` is identical to
|
||||
/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
|
||||
/// former if the platforms you care about support it.
|
||||
///
|
||||
@@ -418,13 +432,15 @@ pub enum UtimensatFlags {
|
||||
///
|
||||
/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn utimensat<P: ?Sized + NixPath>(
|
||||
dirfd: Option<RawFd>,
|
||||
pub fn utimensat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
atime: &TimeSpec,
|
||||
mtime: &TimeSpec,
|
||||
flag: UtimensatFlags,
|
||||
) -> Result<()> {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let atflag = match flag {
|
||||
UtimensatFlags::FollowSymlink => AtFlags::empty(),
|
||||
UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||
@@ -432,7 +448,7 @@ pub fn utimensat<P: ?Sized + NixPath>(
|
||||
let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
|
||||
let res = path.with_nix_path(|cstr| unsafe {
|
||||
libc::utimensat(
|
||||
at_rawfd(dirfd),
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
×[0],
|
||||
atflag.bits() as libc::c_int,
|
||||
@@ -442,15 +458,28 @@ pub fn utimensat<P: ?Sized + NixPath>(
|
||||
Errno::result(res).map(drop)
|
||||
}
|
||||
|
||||
/// Create a directory at the path specified by `dirfd` and `path`.
|
||||
///
|
||||
/// If `path` is a relative path, then it is interpreted relative to the directory
|
||||
/// referred to by the file descriptor `dirfd`. (One can use [`AT_FDCWD`][link] to
|
||||
/// specify the current working directory in `dirfd`). If `path` is absolute,
|
||||
/// then `dirfd` is ignored.
|
||||
///
|
||||
/// [link]: crate::fcntl::AT_FDCWD
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn mkdirat<P: ?Sized + NixPath>(
|
||||
fd: Option<RawFd>,
|
||||
pub fn mkdirat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
|
||||
dirfd: Fd,
|
||||
path: &P,
|
||||
mode: Mode,
|
||||
) -> Result<()> {
|
||||
let fd = at_rawfd(fd);
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let res = path.with_nix_path(|cstr| unsafe {
|
||||
libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t)
|
||||
libc::mkdirat(
|
||||
dirfd.as_fd().as_raw_fd(),
|
||||
cstr.as_ptr(),
|
||||
mode.bits() as mode_t,
|
||||
)
|
||||
})?;
|
||||
|
||||
Errno::result(res).map(drop)
|
||||
|
||||
61
third_party/rust/nix/src/sys/statfs.rs
vendored
61
third_party/rust/nix/src/sys/statfs.rs
vendored
@@ -1,7 +1,7 @@
|
||||
//! Get filesystem statistics, non-portably
|
||||
//!
|
||||
//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
|
||||
#[cfg(not(linux_android))]
|
||||
#[cfg(not(any(linux_android, target_os = "cygwin")))]
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::mem;
|
||||
@@ -19,24 +19,27 @@ use crate::{errno::Errno, NixPath, Result};
|
||||
#[cfg(target_os = "android")]
|
||||
pub type fsid_t = libc::__fsid_t;
|
||||
/// Identifies a mounted file system
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "cygwin")))]
|
||||
pub type fsid_t = libc::fsid_t;
|
||||
/// Identifies a mounted file system
|
||||
#[cfg(target_os = "cygwin")]
|
||||
pub type fsid_t = libc::c_long;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(linux_android, target_os = "fuchsia"))] {
|
||||
type type_of_statfs = libc::statfs64;
|
||||
const LIBC_FSTATFS: unsafe extern fn
|
||||
const LIBC_FSTATFS: unsafe extern "C" fn
|
||||
(fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
|
||||
= libc::fstatfs64;
|
||||
const LIBC_STATFS: unsafe extern fn
|
||||
const LIBC_STATFS: unsafe extern "C" fn
|
||||
(path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
|
||||
= libc::statfs64;
|
||||
} else {
|
||||
type type_of_statfs = libc::statfs;
|
||||
const LIBC_FSTATFS: unsafe extern fn
|
||||
const LIBC_FSTATFS: unsafe extern "C" fn
|
||||
(fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
|
||||
= libc::fstatfs;
|
||||
const LIBC_STATFS: unsafe extern fn
|
||||
const LIBC_STATFS: unsafe extern "C" fn
|
||||
(path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
|
||||
= libc::statfs;
|
||||
}
|
||||
@@ -51,11 +54,13 @@ pub struct Statfs(type_of_statfs);
|
||||
type fs_type_t = u32;
|
||||
#[cfg(target_os = "android")]
|
||||
type fs_type_t = libc::c_ulong;
|
||||
#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_arch = "s390x",
|
||||
not(target_env = "musl")
|
||||
))]
|
||||
type fs_type_t = libc::c_uint;
|
||||
#[cfg(all(target_os = "linux", target_env = "musl"))]
|
||||
type fs_type_t = libc::c_ulong;
|
||||
#[cfg(all(target_os = "linux", target_env = "ohos"))]
|
||||
#[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))]
|
||||
type fs_type_t = libc::c_ulong;
|
||||
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
|
||||
type fs_type_t = libc::c_int;
|
||||
@@ -69,6 +74,8 @@ type fs_type_t = libc::c_int;
|
||||
))
|
||||
))]
|
||||
type fs_type_t = libc::__fsword_t;
|
||||
#[cfg(target_os = "cygwin")]
|
||||
type fs_type_t = libc::c_long;
|
||||
|
||||
/// Describes the file system type as known by the operating system.
|
||||
#[cfg(any(
|
||||
@@ -81,6 +88,7 @@ type fs_type_t = libc::__fsword_t;
|
||||
target_os = "linux",
|
||||
not(any(target_arch = "s390x", target_env = "musl"))
|
||||
),
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
#[derive(Eq, Copy, Clone, PartialEq, Debug)]
|
||||
pub struct FsType(pub fs_type_t);
|
||||
@@ -299,7 +307,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Magic code defining system type
|
||||
#[cfg(not(linux_android))]
|
||||
#[cfg(not(any(linux_android, target_os = "cygwin")))]
|
||||
pub fn filesystem_type_name(&self) -> &str {
|
||||
let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
|
||||
c_str.to_str().unwrap()
|
||||
@@ -318,7 +326,11 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Optimal transfer block size
|
||||
#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_arch = "s390x",
|
||||
not(target_env = "musl")
|
||||
))]
|
||||
pub fn optimal_transfer_size(&self) -> u32 {
|
||||
self.0.f_bsize
|
||||
}
|
||||
@@ -373,7 +385,11 @@ impl Statfs {
|
||||
|
||||
/// Size of a block
|
||||
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
|
||||
#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_arch = "s390x",
|
||||
not(target_env = "musl")
|
||||
))]
|
||||
pub fn block_size(&self) -> u32 {
|
||||
self.0.f_bsize
|
||||
}
|
||||
@@ -427,7 +443,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Size of a block
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn block_size(&self) -> libc::c_long {
|
||||
self.0.f_bsize
|
||||
}
|
||||
@@ -454,7 +470,11 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Maximum length of filenames
|
||||
#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))]
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_arch = "s390x",
|
||||
not(target_env = "musl")
|
||||
))]
|
||||
pub fn maximum_name_length(&self) -> u32 {
|
||||
self.0.f_namelen
|
||||
}
|
||||
@@ -504,7 +524,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Total data blocks in filesystem
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn blocks(&self) -> libc::c_long {
|
||||
self.0.f_blocks
|
||||
}
|
||||
@@ -528,7 +548,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Free blocks in filesystem
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn blocks_free(&self) -> libc::c_long {
|
||||
self.0.f_bfree
|
||||
}
|
||||
@@ -546,7 +566,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Free blocks available to unprivileged user
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn blocks_available(&self) -> libc::c_long {
|
||||
self.0.f_bavail
|
||||
}
|
||||
@@ -576,7 +596,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Total file nodes in filesystem
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn files(&self) -> libc::c_long {
|
||||
self.0.f_files
|
||||
}
|
||||
@@ -599,7 +619,7 @@ impl Statfs {
|
||||
}
|
||||
|
||||
/// Free file nodes in filesystem
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "cygwin"))]
|
||||
pub fn files_free(&self) -> libc::c_long {
|
||||
self.0.f_ffree
|
||||
}
|
||||
@@ -625,6 +645,7 @@ impl Statfs {
|
||||
impl Debug for Statfs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut ds = f.debug_struct("Statfs");
|
||||
#[cfg(not(target_os = "cygwin"))]
|
||||
ds.field("optimal_transfer_size", &self.optimal_transfer_size());
|
||||
ds.field("block_size", &self.block_size());
|
||||
ds.field("blocks", &self.blocks());
|
||||
|
||||
12
third_party/rust/nix/src/sys/termios.rs
vendored
12
third_party/rust/nix/src/sys/termios.rs
vendored
@@ -418,7 +418,7 @@ libc_enum! {
|
||||
VEOL,
|
||||
VEOL2,
|
||||
VERASE,
|
||||
#[cfg(any(freebsdlike, solarish))]
|
||||
#[cfg(any(freebsdlike, target_os = "illumos"))]
|
||||
VERASE2,
|
||||
VINTR,
|
||||
VKILL,
|
||||
@@ -431,7 +431,7 @@ libc_enum! {
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
VREPRINT,
|
||||
VSTART,
|
||||
#[cfg(any(bsd, solarish))]
|
||||
#[cfg(any(bsd, target_os = "illumos"))]
|
||||
VSTATUS,
|
||||
VSTOP,
|
||||
VSUSP,
|
||||
@@ -461,7 +461,7 @@ impl SpecialCharacterIndices {
|
||||
}
|
||||
|
||||
pub use libc::NCCS;
|
||||
#[cfg(any(linux_android, target_os = "aix", bsd))]
|
||||
#[cfg(any(bsd, linux_android, target_os = "aix", target_os = "solaris"))]
|
||||
pub use libc::_POSIX_VDISABLE;
|
||||
|
||||
libc_bitflags! {
|
||||
@@ -667,7 +667,7 @@ libc_bitflags! {
|
||||
ECHOK;
|
||||
ECHO;
|
||||
ECHONL;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "cygwin")))]
|
||||
ECHOPRT;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
ECHOCTL;
|
||||
@@ -676,14 +676,14 @@ libc_bitflags! {
|
||||
#[cfg(bsd)]
|
||||
ALTWERASE;
|
||||
IEXTEN;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "aix")))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "aix", target_os = "cygwin")))]
|
||||
EXTPROC;
|
||||
TOSTOP;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
FLUSHO;
|
||||
#[cfg(bsd)]
|
||||
NOKERNINFO;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "cygwin")))]
|
||||
PENDIN;
|
||||
NOFLSH;
|
||||
}
|
||||
|
||||
55
third_party/rust/nix/src/sys/time.rs
vendored
55
third_party/rust/nix/src/sys/time.rs
vendored
@@ -1,4 +1,7 @@
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
pub use libc::{suseconds_t, time_t};
|
||||
use libc::{timespec, timeval};
|
||||
@@ -253,7 +256,10 @@ impl PartialOrd for TimeSpec {
|
||||
|
||||
impl TimeValLike for TimeSpec {
|
||||
#[inline]
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
fn seconds(seconds: i64) -> TimeSpec {
|
||||
assert!(
|
||||
@@ -286,7 +292,10 @@ impl TimeValLike for TimeSpec {
|
||||
|
||||
/// Makes a new `TimeSpec` with given number of nanoseconds.
|
||||
#[inline]
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
fn nanoseconds(nanoseconds: i64) -> TimeSpec {
|
||||
let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
|
||||
@@ -340,7 +349,10 @@ impl TimeSpec {
|
||||
TimeSpec::new(0, libc::UTIME_NOW as timespec_tv_nsec_t);
|
||||
|
||||
/// Construct a new `TimeSpec` from its components
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)] // https://github.com/rust-lang/libc/issues/1848
|
||||
pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self {
|
||||
let mut ts = zero_init_timespec();
|
||||
ts.tv_sec = seconds;
|
||||
@@ -356,7 +368,10 @@ impl TimeSpec {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)] // https://github.com/rust-lang/libc/issues/1848
|
||||
pub const fn tv_sec(&self) -> time_t {
|
||||
self.0.tv_sec
|
||||
}
|
||||
@@ -365,7 +380,10 @@ impl TimeSpec {
|
||||
self.0.tv_nsec
|
||||
}
|
||||
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
pub const fn from_duration(duration: Duration) -> Self {
|
||||
let mut ts = zero_init_timespec();
|
||||
@@ -506,7 +524,10 @@ impl TimeValLike for TimeVal {
|
||||
(TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&seconds),
|
||||
"TimeVal out of bounds; seconds={seconds}"
|
||||
);
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
TimeVal(timeval {
|
||||
tv_sec: seconds as time_t,
|
||||
@@ -531,7 +552,10 @@ impl TimeValLike for TimeVal {
|
||||
(TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs),
|
||||
"TimeVal out of bounds"
|
||||
);
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
TimeVal(timeval {
|
||||
tv_sec: secs as time_t,
|
||||
@@ -549,7 +573,10 @@ impl TimeValLike for TimeVal {
|
||||
(TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs),
|
||||
"TimeVal out of bounds"
|
||||
);
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))]
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)]
|
||||
// https://github.com/rust-lang/libc/issues/1848
|
||||
TimeVal(timeval {
|
||||
tv_sec: secs as time_t,
|
||||
@@ -586,7 +613,10 @@ impl TimeValLike for TimeVal {
|
||||
|
||||
impl TimeVal {
|
||||
/// Construct a new `TimeVal` from its components
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)] // https://github.com/rust-lang/libc/issues/1848
|
||||
pub const fn new(seconds: time_t, microseconds: suseconds_t) -> Self {
|
||||
Self(timeval {
|
||||
tv_sec: seconds,
|
||||
@@ -602,7 +632,10 @@ impl TimeVal {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
|
||||
#[cfg_attr(
|
||||
any(target_env = "musl", target_env = "ohos"),
|
||||
allow(deprecated)
|
||||
)] // https://github.com/rust-lang/libc/issues/1848
|
||||
pub const fn tv_sec(&self) -> time_t {
|
||||
self.0.tv_sec
|
||||
}
|
||||
|
||||
2
third_party/rust/nix/src/sys/timer.rs
vendored
2
third_party/rust/nix/src/sys/timer.rs
vendored
@@ -95,7 +95,7 @@ impl Timer {
|
||||
/// There are 3 types of alarms you can set:
|
||||
///
|
||||
/// - one shot: the alarm will trigger once after the specified amount of
|
||||
/// time.
|
||||
/// time.
|
||||
/// Example: I want an alarm to go off in 60s and then disable itself.
|
||||
///
|
||||
/// - interval: the alarm will trigger every specified interval of time.
|
||||
|
||||
22
third_party/rust/nix/src/sys/timerfd.rs
vendored
22
third_party/rust/nix/src/sys/timerfd.rs
vendored
@@ -58,6 +58,12 @@ impl FromRawFd for TimerFd {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TimerFd> for OwnedFd {
|
||||
fn from(value: TimerFd) -> Self {
|
||||
value.fd
|
||||
}
|
||||
}
|
||||
|
||||
libc_enum! {
|
||||
/// The type of the clock used to mark the progress of the timer. For more
|
||||
/// details on each kind of clock, please refer to [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
|
||||
@@ -113,7 +119,7 @@ impl TimerFd {
|
||||
/// There are 3 types of alarms you can set:
|
||||
///
|
||||
/// - one shot: the alarm will trigger once after the specified amount of
|
||||
/// time.
|
||||
/// time.
|
||||
/// Example: I want an alarm to go off in 60s and then disable itself.
|
||||
///
|
||||
/// - interval: the alarm will trigger every specified interval of time.
|
||||
@@ -208,7 +214,7 @@ 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.as_fd().as_raw_fd(), &mut [0u8; 8]) {
|
||||
while let Err(e) = read(&self.fd, &mut [0u8; 8]) {
|
||||
if e == Errno::ECANCELED {
|
||||
break;
|
||||
}
|
||||
@@ -219,4 +225,16 @@ impl TimerFd {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/// Constructs a `TimerFd` wrapping an existing `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `OwnedFd` is a valid `TimerFd`.
|
||||
pub unsafe fn from_owned_fd(fd: OwnedFd) -> Self {
|
||||
Self {
|
||||
fd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
third_party/rust/nix/src/sys/uio.rs
vendored
4
third_party/rust/nix/src/sys/uio.rs
vendored
@@ -53,7 +53,7 @@ pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
|
||||
/// or an error occurs. The file offset is not changed.
|
||||
///
|
||||
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris", target_os = "cygwin")))]
|
||||
pub fn pwritev<Fd: AsFd>(
|
||||
fd: Fd,
|
||||
iov: &[IoSlice<'_>],
|
||||
@@ -82,7 +82,7 @@ pub fn pwritev<Fd: AsFd>(
|
||||
/// changed.
|
||||
///
|
||||
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris", target_os = "cygwin")))]
|
||||
// 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)]
|
||||
|
||||
293
third_party/rust/nix/src/syslog.rs
vendored
Normal file
293
third_party/rust/nix/src/syslog.rs
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
//! Interfaces for controlling system log.
|
||||
|
||||
use crate::{NixPath, Result};
|
||||
use std::ffi::OsStr;
|
||||
use std::ptr;
|
||||
|
||||
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`].
|
||||
///
|
||||
/// The parameter `ident` is a string that will be prepended to every message. The `logopt`
|
||||
/// argument specifies logging options. The `facility` parameter encodes a default facility to be
|
||||
/// assigned to all messages that do not have an explicit facility encoded.
|
||||
//
|
||||
// On Linux, the `ident` argument needs to have static lifetime according to the
|
||||
// man page:
|
||||
//
|
||||
// The argument ident in the call of openlog() is probably stored as-is. Thus,
|
||||
// if the string it points to is changed, syslog() may start prepending the changed
|
||||
// string, and if the string it points to ceases to exist, the results are
|
||||
// undefined. Most portable is to use a string constant.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn openlog(
|
||||
ident: Option<&'static std::ffi::CStr>,
|
||||
logopt: LogFlags,
|
||||
facility: Facility,
|
||||
) -> Result<()> {
|
||||
let logopt = logopt.bits();
|
||||
let facility = facility as libc::c_int;
|
||||
match ident {
|
||||
None => unsafe {
|
||||
libc::openlog(ptr::null(), logopt, facility);
|
||||
},
|
||||
Some(ident) => ident.with_nix_path(|ident| unsafe {
|
||||
libc::openlog(ident.as_ptr(), logopt, facility);
|
||||
})?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`].
|
||||
///
|
||||
/// The parameter `ident` is a string that will be prepended to every message. The `logopt`
|
||||
/// argument specifies logging options. The `facility` parameter encodes a default facility to be
|
||||
/// assigned to all messages that do not have an explicit facility encoded.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn openlog<S: AsRef<OsStr> + ?Sized>(
|
||||
ident: Option<&S>,
|
||||
logopt: LogFlags,
|
||||
facility: Facility,
|
||||
) -> Result<()> {
|
||||
let logopt = logopt.bits();
|
||||
let facility = facility as libc::c_int;
|
||||
match ident.map(OsStr::new) {
|
||||
None => unsafe {
|
||||
libc::openlog(ptr::null(), logopt, facility);
|
||||
},
|
||||
Some(ident) => ident.with_nix_path(|ident| unsafe {
|
||||
libc::openlog(ident.as_ptr(), logopt, facility);
|
||||
})?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes message to the system message logger.
|
||||
///
|
||||
/// The message is then written to the system console, log files, logged-in users, or forwarded
|
||||
/// to other machines as appropriate.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity, Priority};
|
||||
///
|
||||
/// let priority = Priority::new(Severity::LOG_EMERG, Facility::LOG_USER);
|
||||
/// syslog(priority, "Hello, nix!").unwrap();
|
||||
///
|
||||
/// // use `format!` to format the message
|
||||
/// let name = "syslog";
|
||||
/// syslog(priority, &format!("Hello, {name}!")).unwrap();
|
||||
/// ```
|
||||
pub fn syslog<P, S>(priority: P, message: &S) -> Result<()>
|
||||
where
|
||||
P: Into<Priority>,
|
||||
S: AsRef<OsStr> + ?Sized,
|
||||
{
|
||||
let priority = priority.into();
|
||||
let formatter = OsStr::new("%s");
|
||||
let message = OsStr::new(message);
|
||||
formatter.with_nix_path(|formatter| {
|
||||
message.with_nix_path(|message| unsafe {
|
||||
libc::syslog(priority.0, formatter.as_ptr(), message.as_ptr())
|
||||
})
|
||||
})??;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the process-wide priority mask to `mask` and return the previous mask
|
||||
/// value.
|
||||
///
|
||||
/// Calls to `syslog()` with a priority level not set in `mask` are ignored. The
|
||||
/// default is to log all priorities.
|
||||
///
|
||||
/// If the `mask` argument is `None`, the current logmask is not modified, this
|
||||
/// can be used to query the current log mask.
|
||||
pub fn setlogmask(mask: Option<LogMask>) -> LogMask {
|
||||
let mask = match mask {
|
||||
Some(mask) => mask.0,
|
||||
None => 0,
|
||||
};
|
||||
let prev_mask = unsafe { libc::setlogmask(mask) };
|
||||
LogMask(prev_mask)
|
||||
}
|
||||
|
||||
/// Closes the log file.
|
||||
pub fn closelog() {
|
||||
unsafe { libc::closelog() }
|
||||
}
|
||||
|
||||
/// System log priority mask.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct LogMask(libc::c_int);
|
||||
|
||||
impl LogMask {
|
||||
/// Creates a mask of all priorities up to and including `priority`.
|
||||
#[doc(alias("LOG_UPTO"))]
|
||||
pub fn up_to(priority: Severity) -> Self {
|
||||
let pri = priority as libc::c_int;
|
||||
Self((1 << (pri + 1)) - 1)
|
||||
}
|
||||
|
||||
/// Creates a mask for the specified priority.
|
||||
#[doc(alias("LOG_MASK"))]
|
||||
pub fn of_priority(priority: Severity) -> Self {
|
||||
let pri = priority as libc::c_int;
|
||||
Self(1 << pri)
|
||||
}
|
||||
|
||||
/// Returns if the mask for the specified `priority` is set.
|
||||
pub fn contains(&self, priority: Severity) -> bool {
|
||||
let priority = Self::of_priority(priority);
|
||||
let and_result = *self & priority;
|
||||
and_result.0 != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOr for LogMask {
|
||||
type Output = Self;
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAnd for LogMask {
|
||||
type Output = Self;
|
||||
fn bitand(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 & rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOrAssign for LogMask {
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAndAssign for LogMask {
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Not for LogMask {
|
||||
type Output = Self;
|
||||
fn not(self) -> Self::Output {
|
||||
Self(!self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// The priority for a log message.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Priority(libc::c_int);
|
||||
|
||||
impl Priority {
|
||||
/// Create a new priority from a facility and severity level.
|
||||
pub fn new(severity: Severity, facility: Facility) -> Self {
|
||||
let priority = (facility as libc::c_int) | (severity as libc::c_int);
|
||||
Priority(priority)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Severity> for Priority {
|
||||
fn from(severity: Severity) -> Self {
|
||||
let priority = severity as libc::c_int;
|
||||
Priority(priority)
|
||||
}
|
||||
}
|
||||
|
||||
libc_bitflags! {
|
||||
/// Options for system logging.
|
||||
pub struct LogFlags: libc::c_int {
|
||||
/// Log the process id with each message: useful for identifying instantiations of
|
||||
/// daemons.
|
||||
LOG_PID;
|
||||
/// If syslog() cannot pass the message to syslogd(8) it will attempt to write the
|
||||
/// message to the console ("/dev/console").
|
||||
LOG_CONS;
|
||||
/// The converse of [`LOG_NDELAY`][LogFlags::LOG_NDELAY]; opening of the connection is
|
||||
/// delayed until `syslog` is called.
|
||||
///
|
||||
/// This is the default, and need not be specified.
|
||||
LOG_ODELAY;
|
||||
/// Open the connection to syslogd(8) immediately. Normally the open is delayed until
|
||||
/// the first message is logged. Useful for programs that need to manage the order in
|
||||
/// which file descriptors are allocated.
|
||||
LOG_NDELAY;
|
||||
/// Write the message to standard error output as well to the system log.
|
||||
#[cfg(not(any(solarish, target_os = "redox", target_os = "cygwin")))]
|
||||
LOG_PERROR;
|
||||
}
|
||||
}
|
||||
|
||||
libc_enum! {
|
||||
/// Severity levels for log messages.
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
pub enum Severity {
|
||||
/// A panic condition.
|
||||
///
|
||||
/// This is normally broadcast to all users.
|
||||
LOG_EMERG,
|
||||
/// A condition that should be corrected immediately, such as a corrupted system database.
|
||||
LOG_ALERT,
|
||||
/// Critical conditions, e.g., hard device errors.
|
||||
LOG_CRIT,
|
||||
/// Errors.
|
||||
LOG_ERR,
|
||||
/// Warning messages.
|
||||
LOG_WARNING,
|
||||
/// Conditions that are not error conditions, but should possibly be handled specially.
|
||||
LOG_NOTICE,
|
||||
/// Informational messages.
|
||||
LOG_INFO,
|
||||
/// Messages that contain information normally of use only when debugging a program.
|
||||
LOG_DEBUG,
|
||||
}
|
||||
}
|
||||
|
||||
libc_enum! {
|
||||
/// Facilities for log messages.
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
pub enum Facility {
|
||||
/// Messages generated by the kernel.
|
||||
///
|
||||
/// These cannot be generated by any user processes.
|
||||
LOG_KERN,
|
||||
/// Messages generated by random user processes.
|
||||
///
|
||||
/// This is the default facility identifier if none is specified.
|
||||
LOG_USER,
|
||||
/// The mail system.
|
||||
LOG_MAIL,
|
||||
/// System daemons, such as routed(8), that are not provided for explicitly by other facilities.
|
||||
LOG_DAEMON,
|
||||
/// The authorization system: login(1), su(1), getty(8), etc.
|
||||
LOG_AUTH,
|
||||
/// Messages generated internally by syslogd(8).
|
||||
LOG_SYSLOG,
|
||||
/// The line printer spooling system: cups-lpd(8), cupsd(8), etc.
|
||||
LOG_LPR,
|
||||
/// The network news system.
|
||||
LOG_NEWS,
|
||||
/// The uucp system.
|
||||
LOG_UUCP,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL0,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL1,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL2,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL3,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL4,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL5,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL6,
|
||||
/// Reserved for local use.
|
||||
LOG_LOCAL7,
|
||||
}
|
||||
}
|
||||
5
third_party/rust/nix/src/time.rs
vendored
5
third_party/rust/nix/src/time.rs
vendored
@@ -122,7 +122,10 @@ impl ClockId {
|
||||
#[cfg(any(
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
all(target_os = "linux", target_env = "musl")
|
||||
all(
|
||||
target_os = "linux",
|
||||
any(target_env = "musl", target_env = "ohos")
|
||||
)
|
||||
))]
|
||||
pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
|
||||
/// International Atomic Time.
|
||||
|
||||
10
third_party/rust/nix/src/ucontext.rs
vendored
10
third_party/rust/nix/src/ucontext.rs
vendored
@@ -1,9 +1,9 @@
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "ohos")))]
|
||||
use crate::errno::Errno;
|
||||
use crate::sys::signal::SigSet;
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "ohos")))]
|
||||
use crate::Result;
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "ohos")))]
|
||||
use std::mem;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
@@ -12,7 +12,7 @@ pub struct UContext {
|
||||
}
|
||||
|
||||
impl UContext {
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "ohos")))]
|
||||
pub fn get() -> Result<UContext> {
|
||||
let mut context = mem::MaybeUninit::<libc::ucontext_t>::uninit();
|
||||
let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
|
||||
@@ -23,7 +23,7 @@ impl UContext {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
#[cfg(not(any(target_env = "musl", target_env = "ohos")))]
|
||||
pub fn set(&self) -> Result<()> {
|
||||
let res = unsafe {
|
||||
libc::setcontext(&self.context as *const libc::ucontext_t)
|
||||
|
||||
671
third_party/rust/nix/src/unistd.rs
vendored
671
third_party/rust/nix/src/unistd.rs
vendored
File diff suppressed because it is too large
Load Diff
18
third_party/rust/nix/test/sys/mod.rs
vendored
18
third_party/rust/nix/test/sys/mod.rs
vendored
@@ -8,7 +8,10 @@ mod test_signal;
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
apple_targets,
|
||||
all(target_os = "linux", not(target_env = "uclibc")),
|
||||
all(
|
||||
target_os = "linux",
|
||||
not(any(target_env = "uclibc", target_env = "ohos"))
|
||||
),
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
mod test_aio;
|
||||
@@ -16,7 +19,8 @@ mod test_aio;
|
||||
target_os = "redox",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
mod test_ioctl;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -82,3 +86,13 @@ mod test_statfs;
|
||||
target_os = "haiku"
|
||||
)))]
|
||||
mod test_resource;
|
||||
|
||||
// This test module should be enabled for both linux_android and freebsd, but
|
||||
// the `memfd_create(2)` symbol is not available under Linux QEMU,
|
||||
//
|
||||
// https://github.com/nix-rust/nix/actions/runs/9427112650/job/25970870477
|
||||
//
|
||||
// and I haven't found a way to stop the linker from linking that symbol, so
|
||||
// only enable this for FreeBSD for now.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
mod test_memfd;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#[cfg(all(
|
||||
not(target_env = "musl"),
|
||||
not(target_env = "uclibc"),
|
||||
not(target_env = "ohos"),
|
||||
any(
|
||||
target_os = "linux",
|
||||
apple_targets,
|
||||
|
||||
6
third_party/rust/nix/test/sys/test_event.rs
vendored
6
third_party/rust/nix/test/sys/test_event.rs
vendored
@@ -1,5 +1,5 @@
|
||||
use libc::intptr_t;
|
||||
use nix::sys::event::{EventFilter, EventFlag, FilterFlag, KEvent};
|
||||
use nix::sys::event::{EvFlags, EventFilter, FilterFlag, KEvent};
|
||||
|
||||
#[test]
|
||||
fn test_struct_kevent() {
|
||||
@@ -11,7 +11,7 @@ fn test_struct_kevent() {
|
||||
let actual = KEvent::new(
|
||||
0xdead_beef,
|
||||
EventFilter::EVFILT_READ,
|
||||
EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
|
||||
EvFlags::EV_ONESHOT | EvFlags::EV_ADD,
|
||||
FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
|
||||
data,
|
||||
udata,
|
||||
@@ -32,7 +32,7 @@ fn test_kevent_filter() {
|
||||
let actual = KEvent::new(
|
||||
0xdead_beef,
|
||||
EventFilter::EVFILT_READ,
|
||||
EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
|
||||
EvFlags::EV_ONESHOT | EvFlags::EV_ADD,
|
||||
FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
|
||||
0x1337,
|
||||
udata,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::*;
|
||||
use nix::errno::Errno;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
use nix::sys::fanotify::{
|
||||
EventFFlags, Fanotify, FanotifyResponse, InitFlags, MarkFlags, MaskFlags,
|
||||
Response,
|
||||
@@ -36,7 +37,7 @@ fn test_fanotify_notifications() {
|
||||
.mark(
|
||||
MarkFlags::FAN_MARK_ADD,
|
||||
MaskFlags::FAN_OPEN | MaskFlags::FAN_MODIFY | MaskFlags::FAN_CLOSE,
|
||||
None,
|
||||
AT_FDCWD,
|
||||
Some(&tempfile),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -99,7 +100,7 @@ fn test_fanotify_responses() {
|
||||
.mark(
|
||||
MarkFlags::FAN_MARK_ADD,
|
||||
MaskFlags::FAN_OPEN_PERM,
|
||||
None,
|
||||
AT_FDCWD,
|
||||
Some(&tempfile),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -182,7 +183,7 @@ fn test_fanotify_overflow() {
|
||||
.mark(
|
||||
MarkFlags::FAN_MARK_ADD,
|
||||
MaskFlags::FAN_OPEN,
|
||||
None,
|
||||
AT_FDCWD,
|
||||
Some(&tempfile),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
20
third_party/rust/nix/test/sys/test_memfd.rs
vendored
Normal file
20
third_party/rust/nix/test/sys/test_memfd.rs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#[test]
|
||||
fn test_memfd_create() {
|
||||
use nix::sys::memfd::memfd_create;
|
||||
use nix::sys::memfd::MFdFlags;
|
||||
use nix::unistd::lseek;
|
||||
use nix::unistd::read;
|
||||
use nix::unistd::{write, Whence};
|
||||
|
||||
let fd =
|
||||
memfd_create("test_memfd_create_name", MFdFlags::MFD_CLOEXEC).unwrap();
|
||||
let contents = b"hello";
|
||||
assert_eq!(write(&fd, contents).unwrap(), 5);
|
||||
|
||||
lseek(&fd, 0, Whence::SeekSet).unwrap();
|
||||
|
||||
let mut buf = vec![0_u8; contents.len()];
|
||||
assert_eq!(read(&fd, &mut buf).unwrap(), 5);
|
||||
|
||||
assert_eq!(contents, buf.as_slice());
|
||||
}
|
||||
79
third_party/rust/nix/test/sys/test_mman.rs
vendored
79
third_party/rust/nix/test/sys/test_mman.rs
vendored
@@ -119,3 +119,82 @@ fn test_mremap_shrink() {
|
||||
// The first KB should still be accessible and have the old data in it.
|
||||
assert_eq!(slice[ONE_K - 1], 0xFF);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_mremap_dontunmap() {
|
||||
use nix::libc::size_t;
|
||||
use nix::sys::mman::{mremap, MRemapFlags};
|
||||
use std::num::NonZeroUsize;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
const ONE_K: size_t = 1024;
|
||||
let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
|
||||
|
||||
let slice: &mut [u8] = unsafe {
|
||||
let mem = mmap_anonymous(
|
||||
None,
|
||||
one_k_non_zero,
|
||||
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
|
||||
MapFlags::MAP_PRIVATE,
|
||||
)
|
||||
.unwrap();
|
||||
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
|
||||
};
|
||||
|
||||
// because we do not unmap `slice`, `old_size` and `new_size`
|
||||
// need to be equal or `EINVAL` is set.
|
||||
let _new_slice: &mut [u8] = unsafe {
|
||||
let mem = mremap(
|
||||
NonNull::from(&mut slice[..]).cast(),
|
||||
ONE_K,
|
||||
ONE_K,
|
||||
MRemapFlags::MREMAP_MAYMOVE | MRemapFlags::MREMAP_DONTUNMAP,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_madv_wipeonfork() {
|
||||
use nix::libc::size_t;
|
||||
use nix::sys::mman::{madvise, MmapAdvise};
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
const ONE_K: size_t = 1024;
|
||||
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
|
||||
let slice: &mut [u8] = unsafe {
|
||||
let mem = mmap_anonymous(
|
||||
None,
|
||||
ten_one_k,
|
||||
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
|
||||
MapFlags::MAP_PRIVATE,
|
||||
)
|
||||
.unwrap();
|
||||
madvise(mem, ONE_K, MmapAdvise::MADV_WIPEONFORK)
|
||||
.expect("madvise failed");
|
||||
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
|
||||
};
|
||||
slice[ONE_K - 1] = 0xFF;
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
|
||||
unsafe {
|
||||
let res = fork().expect("fork failed");
|
||||
match res {
|
||||
ForkResult::Child => {
|
||||
// that s the whole point of MADV_WIPEONFORK
|
||||
assert_eq!(slice[ONE_K - 1], 0x00);
|
||||
libc::_exit(0);
|
||||
}
|
||||
ForkResult::Parent { child } => {
|
||||
nix::sys::signal::kill(child, nix::sys::signal::SIGTERM)
|
||||
.unwrap();
|
||||
let _ = nix::sys::wait::wait().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
third_party/rust/nix/test/sys/test_prctl.rs
vendored
21
third_party/rust/nix/test/sys/test_prctl.rs
vendored
@@ -89,16 +89,20 @@ mod test_prctl {
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
#[test]
|
||||
fn test_get_set_timerslack() {
|
||||
let original = prctl::get_timerslack().unwrap();
|
||||
let original = prctl::get_timerslack().unwrap() as libc::c_ulong;
|
||||
|
||||
let slack = 60_000;
|
||||
prctl::set_timerslack(slack).unwrap();
|
||||
let res = prctl::get_timerslack().unwrap();
|
||||
assert_eq!(slack, res as u64);
|
||||
let res = prctl::get_timerslack().unwrap() as libc::c_ulong;
|
||||
assert_eq!(slack, res);
|
||||
|
||||
prctl::set_timerslack(original as u64).unwrap();
|
||||
prctl::set_timerslack(original).unwrap();
|
||||
}
|
||||
|
||||
// Loongarch need to use a newer QEMU that disabled these PRCTL subcodes/methods.
|
||||
// https://github.com/qemu/qemu/commit/220717a6f46a99031a5b1af964bbf4dec1310440
|
||||
// So we should ignore them when testing in QEMU environments.
|
||||
#[cfg_attr(all(qemu, target_arch = "loongarch64"), ignore)]
|
||||
#[test]
|
||||
fn test_disable_enable_perf_events() {
|
||||
prctl::task_perf_events_disable().unwrap();
|
||||
@@ -112,6 +116,10 @@ mod test_prctl {
|
||||
assert!(no_new_privs);
|
||||
}
|
||||
|
||||
// Loongarch need to use a newer QEMU that disabled these PRCTL subcodes/methods
|
||||
// https://github.com/qemu/qemu/commit/220717a6f46a99031a5b1af964bbf4dec1310440
|
||||
// So we should ignore them when testing in QEMU environments.
|
||||
#[cfg_attr(all(qemu, target_arch = "loongarch64"), ignore)]
|
||||
#[test]
|
||||
fn test_get_set_thp_disable() {
|
||||
let original = prctl::get_thp_disable().unwrap();
|
||||
@@ -123,7 +131,12 @@ mod test_prctl {
|
||||
prctl::set_thp_disable(original).unwrap();
|
||||
}
|
||||
|
||||
// Ignore this test under QEMU, as it started failing after updating the Linux CI
|
||||
// runner image, for reasons unknown.
|
||||
//
|
||||
// See: https://github.com/nix-rust/nix/issues/2418
|
||||
#[test]
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
fn test_set_vma_anon_name() {
|
||||
use nix::errno::Errno;
|
||||
use nix::sys::mman;
|
||||
|
||||
14
third_party/rust/nix/test/sys/test_pthread.rs
vendored
14
third_party/rust/nix/test/sys/test_pthread.rs
vendored
@@ -1,13 +1,23 @@
|
||||
use nix::sys::pthread::*;
|
||||
|
||||
#[cfg(any(target_env = "musl", target_os = "redox"))]
|
||||
#[cfg(any(
|
||||
target_env = "musl",
|
||||
target_os = "redox",
|
||||
target_env = "ohos",
|
||||
target_os = "cygwin"
|
||||
))]
|
||||
#[test]
|
||||
fn test_pthread_self() {
|
||||
let tid = pthread_self();
|
||||
assert!(!tid.is_null());
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_env = "musl", target_os = "redox")))]
|
||||
#[cfg(not(any(
|
||||
target_env = "musl",
|
||||
target_os = "redox",
|
||||
target_env = "ohos",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
#[test]
|
||||
fn test_pthread_self() {
|
||||
let tid = pthread_self();
|
||||
|
||||
59
third_party/rust/nix/test/sys/test_ptrace.rs
vendored
59
third_party/rust/nix/test/sys/test_ptrace.rs
vendored
@@ -179,12 +179,17 @@ fn test_ptrace_interrupt() {
|
||||
// ptrace::{setoptions, getregs} are only available in these platforms
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64"
|
||||
)
|
||||
),
|
||||
all(target_env = "musl", target_arch = "aarch64")
|
||||
)
|
||||
))]
|
||||
#[test]
|
||||
@@ -292,12 +297,17 @@ fn test_ptrace_syscall() {
|
||||
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64",
|
||||
all(
|
||||
target_env = "gnu",
|
||||
any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv64"
|
||||
)
|
||||
),
|
||||
all(target_env = "musl", target_arch = "aarch64")
|
||||
)
|
||||
))]
|
||||
#[test]
|
||||
@@ -371,3 +381,32 @@ fn test_ptrace_regsets() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
#[test]
|
||||
fn test_ptrace_syscall_info() {
|
||||
use nix::sys::ptrace;
|
||||
use nix::sys::wait::{waitpid, WaitStatus};
|
||||
use nix::unistd::fork;
|
||||
use nix::unistd::ForkResult::*;
|
||||
|
||||
require_capability!("test_ptrace_syscall_info", CAP_SYS_PTRACE);
|
||||
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
match unsafe { fork() }.expect("Error: Fork Failed") {
|
||||
Child => {
|
||||
ptrace::traceme().unwrap();
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
unsafe {
|
||||
::libc::_exit(0);
|
||||
}
|
||||
}
|
||||
Parent { child } => loop {
|
||||
if let Ok(WaitStatus::Exited(_, 0)) = waitpid(child, None) {
|
||||
break;
|
||||
}
|
||||
let si = ptrace::syscall_info(child).unwrap();
|
||||
assert!(si.op >= libc::PTRACE_SYSCALL_INFO_ENTRY);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use nix::sys::resource::{getrusage, UsageWho};
|
||||
/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have
|
||||
/// been updated.
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
pub fn test_resource_limits_nofile() {
|
||||
let (mut soft_limit, hard_limit) =
|
||||
getrlimit(Resource::RLIMIT_NOFILE).unwrap();
|
||||
|
||||
271
third_party/rust/nix/test/sys/test_socket.rs
vendored
271
third_party/rust/nix/test/sys/test_socket.rs
vendored
@@ -200,7 +200,7 @@ pub fn test_path_to_sock_addr() {
|
||||
|
||||
let expect: &[c_char] =
|
||||
unsafe { slice::from_raw_parts(path.as_ptr().cast(), path.len()) };
|
||||
assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect);
|
||||
assert_eq!(unsafe { &(&(*addr.as_ptr()).sun_path)[..8] }, expect);
|
||||
|
||||
assert_eq!(addr.path(), Some(actual));
|
||||
}
|
||||
@@ -321,12 +321,13 @@ pub fn test_socketpair() {
|
||||
.unwrap();
|
||||
write(&fd1, b"hello").unwrap();
|
||||
let mut buf = [0; 5];
|
||||
read(fd2.as_raw_fd(), &mut buf).unwrap();
|
||||
read(&fd2, &mut buf).unwrap();
|
||||
|
||||
assert_eq!(&buf[..], b"hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
pub fn test_recvmsg_sockaddr_un() {
|
||||
use nix::sys::socket::{
|
||||
self, bind, socket, AddressFamily, MsgFlags, SockFlag, SockType,
|
||||
@@ -841,6 +842,7 @@ pub fn test_recvmsg_ebadf() {
|
||||
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
pub fn test_scm_rights() {
|
||||
use nix::sys::socket::{
|
||||
recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage,
|
||||
@@ -908,14 +910,24 @@ pub fn test_scm_rights() {
|
||||
// Ensure that the received file descriptor works
|
||||
write(&w, b"world").unwrap();
|
||||
let mut buf = [0u8; 5];
|
||||
read(received_r.as_raw_fd(), &mut buf).unwrap();
|
||||
// SAFETY:
|
||||
// should be safe since we don't use it after close
|
||||
let borrowed_received_r =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(received_r) };
|
||||
read(borrowed_received_r, &mut buf).unwrap();
|
||||
assert_eq!(&buf[..], b"world");
|
||||
close(received_r).unwrap();
|
||||
}
|
||||
|
||||
// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
|
||||
// 1. Disable the test on emulated platforms due to not enabled support of
|
||||
// AF_ALG in QEMU from rust cross
|
||||
// 2. Disable the test on aarch64/Linux CI because bind() fails with ENOENT
|
||||
// https://github.com/nix-rust/nix/issues/1352
|
||||
#[cfg(linux_android)]
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
#[cfg_attr(
|
||||
any(qemu, all(target_os = "linux", target_arch = "aarch64")),
|
||||
ignore
|
||||
)]
|
||||
#[test]
|
||||
pub fn test_af_alg_cipher() {
|
||||
use nix::sys::socket::sockopt::AlgSetKey;
|
||||
@@ -926,11 +938,6 @@ pub fn test_af_alg_cipher() {
|
||||
use nix::unistd::read;
|
||||
use std::io::IoSlice;
|
||||
|
||||
skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352");
|
||||
// Travis's seccomp profile blocks AF_ALG
|
||||
// https://docs.docker.com/engine/security/seccomp/
|
||||
skip_if_seccomp!(test_af_alg_cipher);
|
||||
|
||||
let alg_type = "skcipher";
|
||||
let alg_name = "ctr-aes-aesni";
|
||||
// 256-bits secret key
|
||||
@@ -975,8 +982,12 @@ pub fn test_af_alg_cipher() {
|
||||
|
||||
// allocate buffer for encrypted data
|
||||
let mut encrypted = vec![0u8; payload_len];
|
||||
// SAFETY:
|
||||
// should be safe since session_socket won't be closed before the use of this borrowed one
|
||||
let borrowed_session_socket =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(session_socket) };
|
||||
let num_bytes =
|
||||
read(session_socket.as_raw_fd(), &mut encrypted).expect("read encrypt");
|
||||
read(borrowed_session_socket, &mut encrypted).expect("read encrypt");
|
||||
assert_eq!(num_bytes, payload_len);
|
||||
|
||||
let iov = IoSlice::new(&encrypted);
|
||||
@@ -998,8 +1009,12 @@ pub fn test_af_alg_cipher() {
|
||||
|
||||
// allocate buffer for decrypted data
|
||||
let mut decrypted = vec![0u8; payload_len];
|
||||
// SAFETY:
|
||||
// should be safe since session_socket won't be closed before the use of this borrowed one
|
||||
let borrowed_session_socket =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(session_socket) };
|
||||
let num_bytes =
|
||||
read(session_socket.as_raw_fd(), &mut decrypted).expect("read decrypt");
|
||||
read(borrowed_session_socket, &mut decrypted).expect("read decrypt");
|
||||
|
||||
assert_eq!(num_bytes, payload_len);
|
||||
assert_eq!(decrypted, payload);
|
||||
@@ -1087,8 +1102,12 @@ pub fn test_af_alg_aead() {
|
||||
// allocate buffer for encrypted data
|
||||
let mut encrypted =
|
||||
vec![0u8; (assoc_size as usize) + payload_len + auth_size];
|
||||
// SAFETY:
|
||||
// should be safe since session_socket won't be closed before the use of this borrowed one
|
||||
let borrowed_session_socket =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(session_socket) };
|
||||
let num_bytes =
|
||||
read(session_socket.as_raw_fd(), &mut encrypted).expect("read encrypt");
|
||||
read(borrowed_session_socket, &mut encrypted).expect("read encrypt");
|
||||
assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize));
|
||||
|
||||
for i in 0..assoc_size {
|
||||
@@ -1122,10 +1141,16 @@ pub fn test_af_alg_aead() {
|
||||
// authentication tag memory is only needed in the output buffer for encryption
|
||||
// and in the input buffer for decryption.
|
||||
// Do not block on read, as we may have fewer bytes than buffer size
|
||||
fcntl(session_socket, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// `session_socket` will be valid for the lifetime of this test
|
||||
// TODO: remove this workaround when accept(2) becomes I/O-safe.
|
||||
let borrowed_fd =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(session_socket) };
|
||||
fcntl(borrowed_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))
|
||||
.expect("fcntl non_blocking");
|
||||
let num_bytes =
|
||||
read(session_socket.as_raw_fd(), &mut decrypted).expect("read decrypt");
|
||||
let num_bytes = read(borrowed_fd, &mut decrypted).expect("read decrypt");
|
||||
|
||||
assert!(num_bytes >= payload_len + (assoc_size as usize));
|
||||
assert_eq!(
|
||||
@@ -1304,6 +1329,7 @@ pub fn test_sendmsg_ipv4sendsrcaddr() {
|
||||
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
fn test_scm_rights_single_cmsg_multiple_fds() {
|
||||
use nix::sys::socket::{
|
||||
recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags,
|
||||
@@ -1615,7 +1641,11 @@ fn test_impl_scm_credentials_and_rights(
|
||||
// Ensure that the received file descriptor works
|
||||
write(&w, b"world").unwrap();
|
||||
let mut buf = [0u8; 5];
|
||||
read(received_r.as_raw_fd(), &mut buf).unwrap();
|
||||
// SAFETY:
|
||||
// It should be safe if we don't use this BorrowedFd after close.
|
||||
let received_r_borrowed =
|
||||
unsafe { std::os::fd::BorrowedFd::borrow_raw(received_r) };
|
||||
read(received_r_borrowed, &mut buf).unwrap();
|
||||
assert_eq!(&buf[..], b"world");
|
||||
close(received_r).unwrap();
|
||||
|
||||
@@ -1659,17 +1689,28 @@ pub fn test_named_unixdomain() {
|
||||
|
||||
let s3 = accept(s1.as_raw_fd()).expect("accept failed");
|
||||
|
||||
// SAFETY:
|
||||
// It should be safe considering that s3 will be open within this test
|
||||
let s3 = unsafe { std::os::fd::BorrowedFd::borrow_raw(s3) };
|
||||
let mut buf = [0; 5];
|
||||
read(s3.as_raw_fd(), &mut buf).unwrap();
|
||||
read(s3, &mut buf).unwrap();
|
||||
thr.join().unwrap();
|
||||
|
||||
assert_eq!(&buf[..], b"hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_listen_maxbacklog() {
|
||||
use nix::sys::socket::Backlog;
|
||||
|
||||
assert!(Backlog::new(libc::SOMAXCONN).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_listen_wrongbacklog() {
|
||||
use nix::sys::socket::Backlog;
|
||||
|
||||
#[cfg(not(target_os = "cygwin"))]
|
||||
assert!(Backlog::new(libc::SOMAXCONN + 1).is_err());
|
||||
assert!(Backlog::new(-2).is_err());
|
||||
}
|
||||
@@ -2544,6 +2585,191 @@ fn test_recvmsg_rxq_ovfl() {
|
||||
assert_eq!(drop_counter, 1);
|
||||
}
|
||||
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
#[cfg(feature = "net")]
|
||||
// qemu doesn't seem to be emulating this correctly in these architectures
|
||||
#[cfg_attr(
|
||||
all(
|
||||
qemu,
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
)
|
||||
),
|
||||
ignore
|
||||
)]
|
||||
#[test]
|
||||
pub fn test_ip_tos_udp() {
|
||||
use nix::sys::socket::ControlMessageOwned;
|
||||
use nix::sys::socket::{
|
||||
bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
|
||||
MsgFlags, SockFlag, SockType, SockaddrIn,
|
||||
};
|
||||
|
||||
let sock_addr = SockaddrIn::from_str("127.0.0.1:6909").unwrap();
|
||||
let rsock = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&rsock, sockopt::IpRecvTos, &true).unwrap();
|
||||
bind(rsock.as_raw_fd(), &sock_addr).unwrap();
|
||||
|
||||
let sbuf = [0u8; 2048];
|
||||
let iov1 = [std::io::IoSlice::new(&sbuf)];
|
||||
|
||||
let mut rbuf = [0u8; 2048];
|
||||
let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)];
|
||||
let mut rcmsg = cmsg_space!(libc::c_int);
|
||||
|
||||
let ssock = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.expect("send socket failed");
|
||||
setsockopt(&ssock, sockopt::Ipv4Tos, &20).unwrap();
|
||||
|
||||
// Test the sendmsg control message and check the received packet has the same TOS.
|
||||
let scmsg = ControlMessage::Ipv4Tos(&20);
|
||||
sendmsg(
|
||||
ssock.as_raw_fd(),
|
||||
&iov1,
|
||||
&[scmsg],
|
||||
MsgFlags::empty(),
|
||||
Some(&sock_addr),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// TODO: this test is weak, but testing for the actual ToS value results in sporadic
|
||||
// failures in CI where the ToS in the message header is not the one set by the
|
||||
// sender, so for now the test only checks for the presence of the ToS in the message
|
||||
// header.
|
||||
let mut tc = None;
|
||||
let recv = recvmsg::<()>(
|
||||
rsock.as_raw_fd(),
|
||||
&mut iov2,
|
||||
Some(&mut rcmsg),
|
||||
MsgFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
for c in recv.cmsgs().unwrap() {
|
||||
if let ControlMessageOwned::Ipv4Tos(t) = c {
|
||||
tc = Some(t);
|
||||
}
|
||||
}
|
||||
assert!(tc.is_some());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
// qemu doesn't seem to be emulating this correctly in these architectures
|
||||
#[cfg_attr(
|
||||
all(
|
||||
qemu,
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips32r6",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
)
|
||||
),
|
||||
ignore
|
||||
)]
|
||||
#[cfg(feature = "net")]
|
||||
#[test]
|
||||
pub fn test_ipv6_tclass_udp() {
|
||||
use nix::sys::socket::ControlMessageOwned;
|
||||
use nix::sys::socket::{
|
||||
bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
|
||||
MsgFlags, SockFlag, SockType, SockaddrIn6,
|
||||
};
|
||||
|
||||
let std_sa = SocketAddrV6::from_str("[::1]:6902").unwrap();
|
||||
let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa);
|
||||
let rsock = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&rsock, sockopt::Ipv6RecvTClass, &true).unwrap();
|
||||
// This bind call with IPV6_RECVTCLASS fails on the Linux aarch64 target with EADDRNOTAVAIL,
|
||||
// so the test will only run if `bind` does not return an error..
|
||||
if bind(rsock.as_raw_fd(), &sock_addr).is_ok() {
|
||||
let sbuf = [0u8; 2048];
|
||||
let iov1 = [std::io::IoSlice::new(&sbuf)];
|
||||
|
||||
let mut rbuf = [0u8; 2048];
|
||||
let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)];
|
||||
let mut rcmsg = cmsg_space!(libc::c_int);
|
||||
|
||||
let ssock = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.expect("send socket failed");
|
||||
setsockopt(&ssock, sockopt::Ipv6TClass, &10).unwrap();
|
||||
|
||||
sendmsg(
|
||||
ssock.as_raw_fd(),
|
||||
&iov1,
|
||||
&[],
|
||||
MsgFlags::empty(),
|
||||
Some(&sock_addr),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut tc = None;
|
||||
let recv = recvmsg::<()>(
|
||||
rsock.as_raw_fd(),
|
||||
&mut iov2,
|
||||
Some(&mut rcmsg),
|
||||
MsgFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
for c in recv.cmsgs().unwrap() {
|
||||
if let ControlMessageOwned::Ipv6TClass(t) = c {
|
||||
tc = Some(t);
|
||||
}
|
||||
}
|
||||
assert_eq!(tc, Some(10));
|
||||
|
||||
let scmsg = ControlMessage::Ipv6TClass(&20);
|
||||
sendmsg(
|
||||
ssock.as_raw_fd(),
|
||||
&iov1,
|
||||
&[scmsg],
|
||||
MsgFlags::empty(),
|
||||
Some(&sock_addr),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut tc = None;
|
||||
let recv = recvmsg::<()>(
|
||||
rsock.as_raw_fd(),
|
||||
&mut iov2,
|
||||
Some(&mut rcmsg),
|
||||
MsgFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
for c in recv.cmsgs().unwrap() {
|
||||
if let ControlMessageOwned::Ipv6TClass(t) = c {
|
||||
tc = Some(t);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(tc, Some(20));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(linux_android)]
|
||||
mod linux_errqueue {
|
||||
use super::FromStr;
|
||||
@@ -2693,7 +2919,7 @@ mod linux_errqueue {
|
||||
)
|
||||
.unwrap();
|
||||
// The sent message / destination associated with the error is returned:
|
||||
assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len());
|
||||
assert_eq!(msg.bytes, MESSAGE_CONTENTS.len());
|
||||
// recvmsg(2): "The original destination address of the datagram that caused the error is
|
||||
// supplied via msg_name;" however, this is not literally true. E.g., an earlier version
|
||||
// of this test used 0.0.0.0 (::0) as the destination address, which was mutated into
|
||||
@@ -2930,7 +3156,12 @@ fn can_use_cmsg_space() {
|
||||
let _ = cmsg_space!(u8);
|
||||
}
|
||||
|
||||
#[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))]
|
||||
#[cfg(not(any(
|
||||
linux_android,
|
||||
target_os = "redox",
|
||||
target_os = "haiku",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
#[test]
|
||||
fn can_open_routing_socket() {
|
||||
use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
|
||||
|
||||
447
third_party/rust/nix/test/sys/test_sockopt.rs
vendored
447
third_party/rust/nix/test/sys/test_sockopt.rs
vendored
@@ -4,7 +4,7 @@ use nix::sys::socket::{
|
||||
getsockopt, setsockopt, socket, sockopt, AddressFamily, SockFlag,
|
||||
SockProtocol, SockType,
|
||||
};
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand::{rng, Rng};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
|
||||
|
||||
// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
|
||||
@@ -66,6 +66,36 @@ pub fn test_local_peer_pid() {
|
||||
assert_eq!(pid, std::process::id() as _);
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
pub fn test_local_peer_token() {
|
||||
use nix::sys::socket::{audit_token_t, socketpair};
|
||||
|
||||
#[link(name = "bsm", kind = "dylib")]
|
||||
extern "C" {
|
||||
/// Extract the process ID from an `audit_token_t`, used to identify
|
||||
/// Mach tasks and senders of Mach messages as subjects of the audit
|
||||
/// system.
|
||||
///
|
||||
/// - `atoken`: The Mach audit token.
|
||||
/// - Returns: The process ID extracted from the Mach audit token.
|
||||
fn audit_token_to_pid(atoken: audit_token_t) -> libc::pid_t;
|
||||
}
|
||||
|
||||
let (fd1, _fd2) = socketpair(
|
||||
AddressFamily::Unix,
|
||||
SockType::Stream,
|
||||
None,
|
||||
SockFlag::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
let audit_token = getsockopt(&fd1, sockopt::LocalPeerToken).unwrap();
|
||||
assert_eq!(
|
||||
unsafe { audit_token_to_pid(audit_token) },
|
||||
std::process::id() as _
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn is_so_mark_functional() {
|
||||
@@ -94,7 +124,7 @@ fn test_so_buf() {
|
||||
SockProtocol::Udp,
|
||||
)
|
||||
.unwrap();
|
||||
let bufsize: usize = thread_rng().gen_range(4096..131_072);
|
||||
let bufsize: usize = rng().random_range(4096..131_072);
|
||||
setsockopt(&fd, sockopt::SndBuf, &bufsize).unwrap();
|
||||
let actual = getsockopt(&fd, sockopt::SndBuf).unwrap();
|
||||
assert!(actual >= bufsize);
|
||||
@@ -129,11 +159,11 @@ fn test_so_listen_q_limit() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
fn test_so_tcp_maxseg() {
|
||||
use nix::sys::socket::{
|
||||
accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
|
||||
};
|
||||
use nix::unistd::write;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::str::FromStr;
|
||||
|
||||
@@ -153,14 +183,12 @@ fn test_so_tcp_maxseg() {
|
||||
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
|
||||
// than `segsize`
|
||||
let segsize: u32 = 873;
|
||||
assert!(initial < segsize);
|
||||
cfg_if! {
|
||||
if #[cfg(linux_android)] {
|
||||
let segsize: u32 = 873;
|
||||
assert!(initial < segsize);
|
||||
setsockopt(&rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
|
||||
} else {
|
||||
assert!(initial < 700);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,20 +200,38 @@ fn test_so_tcp_maxseg() {
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
connect(ssock.as_raw_fd(), &sock_addr).unwrap();
|
||||
|
||||
let rsess = accept(rsock.as_raw_fd()).unwrap();
|
||||
let rsess = unsafe { OwnedFd::from_raw_fd(rsess) };
|
||||
write(&rsess, b"hello").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! {
|
||||
if #[cfg(linux_android)] {
|
||||
assert!((segsize - 100) <= actual);
|
||||
assert!(actual <= segsize);
|
||||
if #[cfg(apple_targets)] {
|
||||
// on apple targets (and unlike linux), we can only set the MSS on a *connected*
|
||||
// socket. Also, the same MSS can't be read using getsockopt from the other end.
|
||||
|
||||
assert_ne!(segsize, getsockopt(&rsess, sockopt::TcpMaxSeg).unwrap());
|
||||
setsockopt(&rsess, sockopt::TcpMaxSeg, &segsize).unwrap();
|
||||
assert_eq!(segsize, getsockopt(&rsess, sockopt::TcpMaxSeg).unwrap());
|
||||
|
||||
assert_ne!(segsize, getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap());
|
||||
setsockopt(&ssock, sockopt::TcpMaxSeg, &segsize).unwrap();
|
||||
assert_eq!(segsize, getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap());
|
||||
} else {
|
||||
assert!(initial < actual);
|
||||
assert!(536 < actual);
|
||||
use nix::unistd::write;
|
||||
|
||||
write(&rsess, b"hello").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.
|
||||
if cfg!(linux_android) {
|
||||
assert!((segsize - 100) <= actual);
|
||||
assert!(actual <= segsize);
|
||||
} else {
|
||||
assert!(initial < actual);
|
||||
assert!(536 < actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,6 +257,8 @@ fn test_so_type_unknown() {
|
||||
use nix::errno::Errno;
|
||||
|
||||
require_capability!("test_so_type", CAP_NET_RAW);
|
||||
// SOCK_PACKET is deprecated, but since it is used for testing here, we allow it
|
||||
#[allow(deprecated)]
|
||||
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) };
|
||||
@@ -219,16 +267,16 @@ fn test_so_type_unknown() {
|
||||
}
|
||||
|
||||
// The CI doesn't supported getsockopt and setsockopt on emulated processors.
|
||||
// It's believed that a QEMU issue, the tests run ok on a fully emulated system.
|
||||
// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
|
||||
// It's believed to be a QEMU issue; the tests run ok on a fully emulated
|
||||
// system. Current CI just runs the binary with QEMU but the kernel remains the
|
||||
// same as the host.
|
||||
// So the syscall doesn't work properly unless the kernel is also emulated.
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
any(target_arch = "x86", target_arch = "x86_64"),
|
||||
any(target_os = "freebsd", target_os = "linux")
|
||||
))]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
fn test_tcp_congestion() {
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
@@ -239,6 +287,10 @@ fn test_tcp_congestion() {
|
||||
.unwrap();
|
||||
|
||||
let val = getsockopt(&fd, sockopt::TcpCongestion).unwrap();
|
||||
let bytes = val.as_os_str().as_bytes();
|
||||
for b in bytes.iter() {
|
||||
assert_ne!(*b, 0, "OsString should contain no embedded NULs: {val:?}");
|
||||
}
|
||||
setsockopt(&fd, sockopt::TcpCongestion, &val).unwrap();
|
||||
|
||||
setsockopt(
|
||||
@@ -251,6 +303,35 @@ fn test_tcp_congestion() {
|
||||
assert_eq!(getsockopt(&fd, sockopt::TcpCongestion).unwrap(), val);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn test_tcp_function_blk_alias() {
|
||||
use std::ffi::CStr;
|
||||
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tfs = getsockopt(&fd, sockopt::TcpFunctionBlk).unwrap();
|
||||
let name = unsafe { CStr::from_ptr(tfs.function_set_name.as_ptr()) };
|
||||
assert!(!name.to_bytes().is_empty());
|
||||
|
||||
let aliastfs = getsockopt(&fd, sockopt::TcpFunctionAlias).unwrap();
|
||||
let aliasname =
|
||||
unsafe { CStr::from_ptr(aliastfs.function_set_name.as_ptr()) };
|
||||
// freebsd default tcp stack has no alias.
|
||||
assert!(aliasname.to_bytes().is_empty());
|
||||
|
||||
// We can't know at compile time what options are available. So just test the setter by a
|
||||
// no-op set.
|
||||
// TODO: test if we can load for example BBR tcp stack kernel module.
|
||||
setsockopt(&fd, sockopt::TcpFunctionBlk, &tfs).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(linux_android)]
|
||||
fn test_bindtodevice() {
|
||||
@@ -469,7 +550,7 @@ fn test_so_priority() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
fn test_ip_tos() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
@@ -479,12 +560,12 @@ 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::Ipv4Tos, &tos).unwrap();
|
||||
assert_eq!(getsockopt(&fd, sockopt::Ipv4Tos).unwrap(), tos);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
// Disable the test under emulation because it fails in Cirrus-CI. Lack
|
||||
// of QEMU support is suspected.
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
@@ -683,6 +764,46 @@ fn can_get_peercred_on_unix_socket() {
|
||||
assert_ne!(a_cred.pid(), 0);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn pid_from_pidfd(pidfd: OwnedFd) -> u32 {
|
||||
use std::fs::read_to_string;
|
||||
|
||||
let fd = pidfd.as_raw_fd();
|
||||
let fdinfo = read_to_string(format!("/proc/self/fdinfo/{fd}")).unwrap();
|
||||
let pidline = fdinfo.split('\n').find(|s| s.starts_with("Pid:")).unwrap();
|
||||
pidline.split('\t').next_back().unwrap().parse().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn can_get_peerpidfd_on_unix_socket() {
|
||||
use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
|
||||
|
||||
let (a, b) = socketpair(
|
||||
AddressFamily::Unix,
|
||||
SockType::Stream,
|
||||
None,
|
||||
SockFlag::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match (
|
||||
getsockopt(&a, sockopt::PeerPidfd),
|
||||
getsockopt(&b, sockopt::PeerPidfd),
|
||||
) {
|
||||
(Ok(a_pidfd), Ok(b_pidfd)) => {
|
||||
let a_pid = pid_from_pidfd(a_pidfd);
|
||||
let b_pid = pid_from_pidfd(b_pidfd);
|
||||
assert_eq!(a_pid, b_pid);
|
||||
assert_ne!(a_pid, 0);
|
||||
}
|
||||
(Err(nix::Error::ENOPROTOOPT), Err(nix::Error::ENOPROTOOPT)) => {
|
||||
// Pidfd can still be unsupported on some CI runners
|
||||
}
|
||||
(Err(err), _) | (_, Err(err)) => panic!("{err:?}"),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_socket_type_unix() {
|
||||
use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
|
||||
@@ -877,3 +998,275 @@ fn test_reuseport_lb() {
|
||||
setsockopt(&fd, sockopt::ReusePortLb, &true).unwrap();
|
||||
assert!(getsockopt(&fd, sockopt::ReusePortLb).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
fn test_ipv4_recv_ttl_opts() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, sockopt::Ipv4RecvTtl, &true)
|
||||
.expect("setting IP_RECVTTL on an inet stream socket should succeed");
|
||||
setsockopt(&fd, sockopt::Ipv4RecvTtl, &false)
|
||||
.expect("unsetting IP_RECVTTL on an inet stream socket should succeed");
|
||||
let fdd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fdd, sockopt::Ipv4RecvTtl, &true)
|
||||
.expect("setting IP_RECVTTL on an inet datagram socket should succeed");
|
||||
setsockopt(&fdd, sockopt::Ipv4RecvTtl, &false).expect(
|
||||
"unsetting IP_RECVTTL on an inet datagram socket should succeed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
fn test_ipv6_recv_hop_limit_opts() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, sockopt::Ipv6RecvHopLimit, &true).expect(
|
||||
"setting IPV6_RECVHOPLIMIT on an inet6 stream socket should succeed",
|
||||
);
|
||||
setsockopt(&fd, sockopt::Ipv6RecvHopLimit, &false).expect(
|
||||
"unsetting IPV6_RECVHOPLIMIT on an inet6 stream socket should succeed",
|
||||
);
|
||||
let fdd = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fdd, sockopt::Ipv6RecvHopLimit, &true).expect(
|
||||
"setting IPV6_RECVHOPLIMIT on an inet6 datagram socket should succeed",
|
||||
);
|
||||
setsockopt(&fdd, sockopt::Ipv6RecvHopLimit, &false).expect(
|
||||
"unsetting IPV6_RECVHOPLIMIT on an inet6 datagram socket should succeed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
fn test_ipv4_recv_tos_opts() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, sockopt::IpRecvTos, &true)
|
||||
.expect("setting IP_RECVTOS on an inet stream socket should succeed");
|
||||
setsockopt(&fd, sockopt::IpRecvTos, &false)
|
||||
.expect("unsetting IP_RECVTOS on an inet stream socket should succeed");
|
||||
let fdd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fdd, sockopt::IpRecvTos, &true)
|
||||
.expect("setting IP_RECVTOS on an inet datagram socket should succeed");
|
||||
setsockopt(&fdd, sockopt::IpRecvTos, &false).expect(
|
||||
"unsetting IP_RECVTOS on an inet datagram socket should succeed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(linux_android, target_os = "freebsd"))]
|
||||
fn test_ipv6_recv_traffic_class_opts() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, sockopt::Ipv6RecvTClass, &true).expect(
|
||||
"setting IPV6_RECVTCLASS on an inet6 stream socket should succeed",
|
||||
);
|
||||
setsockopt(&fd, sockopt::Ipv6RecvTClass, &false).expect(
|
||||
"unsetting IPV6_RECVTCLASS on an inet6 stream socket should succeed",
|
||||
);
|
||||
let fdd = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fdd, sockopt::Ipv6RecvTClass, &true).expect(
|
||||
"setting IPV6_RECVTCLASS on an inet6 datagram socket should succeed",
|
||||
);
|
||||
setsockopt(&fdd, sockopt::Ipv6RecvTClass, &false).expect(
|
||||
"unsetting IPV6_RECVTCLASS on an inet6 datagram socket should succeed",
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_linger_sec() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let set_linger = libc::linger {
|
||||
l_onoff: 1,
|
||||
l_linger: 1,
|
||||
};
|
||||
setsockopt(&fd, sockopt::LingerSec, &set_linger).unwrap();
|
||||
|
||||
let get_linger = getsockopt(&fd, sockopt::Linger).unwrap();
|
||||
assert_eq!(get_linger.l_linger, set_linger.l_linger * 100);
|
||||
}
|
||||
|
||||
/// Users should be able to define their own sockopts.
|
||||
mod sockopt_impl {
|
||||
use nix::sys::socket::{
|
||||
getsockopt, setsockopt, socket, AddressFamily, SockFlag, SockProtocol,
|
||||
SockType,
|
||||
};
|
||||
|
||||
sockopt_impl!(KeepAlive, Both, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
|
||||
|
||||
#[test]
|
||||
fn test_so_tcp_keepalive() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, KeepAlive, &true).unwrap();
|
||||
assert!(getsockopt(&fd, KeepAlive).unwrap());
|
||||
}
|
||||
|
||||
sockopt_impl!(
|
||||
Linger,
|
||||
Both,
|
||||
libc::SOL_SOCKET,
|
||||
libc::SO_LINGER,
|
||||
libc::linger
|
||||
);
|
||||
#[test]
|
||||
fn test_linger() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let set_linger = libc::linger {
|
||||
l_onoff: 1,
|
||||
l_linger: 42,
|
||||
};
|
||||
setsockopt(&fd, Linger, &set_linger).unwrap();
|
||||
|
||||
let get_linger = getsockopt(&fd, Linger).unwrap();
|
||||
assert_eq!(get_linger.l_linger, set_linger.l_linger);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(solarish)]
|
||||
#[test]
|
||||
fn test_exclbind() {
|
||||
use nix::errno::Errno;
|
||||
use nix::sys::socket::{
|
||||
bind, socket, AddressFamily, SockFlag, SockType, SockaddrIn,
|
||||
};
|
||||
use std::net::SocketAddrV4;
|
||||
use std::str::FromStr;
|
||||
let fd1 = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let addr = SocketAddrV4::from_str("127.0.0.1:8081").unwrap();
|
||||
let excl = true;
|
||||
|
||||
setsockopt(&fd1, sockopt::ExclBind, &excl).unwrap();
|
||||
bind(fd1.as_raw_fd(), &SockaddrIn::from(addr)).unwrap();
|
||||
assert_eq!(getsockopt(&fd1, sockopt::ExclBind), Ok(true));
|
||||
let fd2 = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
bind(fd2.as_raw_fd(), &SockaddrIn::from(addr)),
|
||||
Err(Errno::EADDRINUSE)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
#[test]
|
||||
fn test_solfilter() {
|
||||
use nix::errno::Errno;
|
||||
let s = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Stream,
|
||||
SockFlag::empty(),
|
||||
SockProtocol::Tcp,
|
||||
)
|
||||
.unwrap();
|
||||
let data = std::ffi::OsStr::new("httpf");
|
||||
let attach = sockopt::FilterAttach;
|
||||
let detach = sockopt::FilterDetach;
|
||||
|
||||
// These 2 options won't work unless the needed kernel module is installed:
|
||||
// https://github.com/nix-rust/nix/pull/2611#issuecomment-2750237782
|
||||
//
|
||||
// So we only test the binding here
|
||||
assert_eq!(Err(Errno::ENOENT), setsockopt(&s, attach, data));
|
||||
assert_eq!(Err(Errno::ENOENT), setsockopt(&s, detach, data));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
pub fn test_so_attach_reuseport_cbpf() {
|
||||
let fd = socket(
|
||||
AddressFamily::Inet6,
|
||||
SockType::Datagram,
|
||||
SockFlag::empty(),
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
setsockopt(&fd, sockopt::ReusePort, &true).unwrap();
|
||||
setsockopt(&fd, sockopt::ReuseAddr, &true).unwrap();
|
||||
let mut flt: [libc::sock_filter; 2] = unsafe { std::mem::zeroed() };
|
||||
flt[0].code = (libc::BPF_LD | libc::BPF_W | libc::BPF_ABS) as u16;
|
||||
flt[0].k = (libc::SKF_AD_OFF + libc::SKF_AD_CPU) as u32;
|
||||
flt[1].code = (libc::BPF_RET | 0x10) as u16;
|
||||
let fp = libc::sock_fprog {
|
||||
len: flt.len() as u16,
|
||||
filter: flt.as_mut_ptr(),
|
||||
};
|
||||
setsockopt(&fd, sockopt::AttachReusePortCbpf, &fp).unwrap_or_else(|e| {
|
||||
assert_eq!(e, nix::errno::Errno::ENOPROTOOPT);
|
||||
});
|
||||
}
|
||||
|
||||
493
third_party/rust/nix/test/sys/test_stat.rs
vendored
493
third_party/rust/nix/test/sys/test_stat.rs
vendored
@@ -1,3 +1,485 @@
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::os::unix::fs::symlink;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::path::Path;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
use libc::mode_t;
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use libc::{S_IFLNK, S_IFMT};
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::errno::Errno;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::fcntl;
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
apple_targets,
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
use nix::sys::stat::lutimes;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::utimensat;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::FchmodatFlags;
|
||||
use nix::sys::stat::Mode;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::UtimensatFlags;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::{self};
|
||||
use nix::sys::stat::{fchmod, stat};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::{fchmodat, mkdirat};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::{futimens, utimes};
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use nix::sys::stat::FileStat;
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::unistd::chdir;
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use nix::Result;
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn assert_stat_results(stat_result: Result<FileStat>) {
|
||||
let stats = stat_result.expect("stat call failed");
|
||||
assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
|
||||
assert!(stats.st_mode > 0); // must be positive integer
|
||||
assert_eq!(stats.st_nlink, 1); // there links created, must be 1
|
||||
assert_eq!(stats.st_size, 0); // size is 0 because we did not write anything to the file
|
||||
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
// (Android's st_blocks is ulonglong which is always non-negative.)
|
||||
#[cfg_attr(target_os = "android", allow(unused_comparisons))]
|
||||
#[allow(clippy::absurd_extreme_comparisons)] // Not absurd on all OSes
|
||||
fn assert_lstat_results(stat_result: Result<FileStat>) {
|
||||
let stats = stat_result.expect("stat call failed");
|
||||
assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
|
||||
assert!(stats.st_mode > 0); // must be positive integer
|
||||
|
||||
// st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
|
||||
// (u16 on Android), and that will be a compile error.
|
||||
// On other platforms they are the same (either both are u16 or u32).
|
||||
assert_eq!(
|
||||
(stats.st_mode as usize) & (S_IFMT as usize),
|
||||
S_IFLNK as usize
|
||||
); // should be a link
|
||||
assert_eq!(stats.st_nlink, 1); // there links created, must be 1
|
||||
assert!(stats.st_size > 0); // size is > 0 because it points to another file
|
||||
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
|
||||
|
||||
// st_blocks depends on whether the machine's file system uses fast
|
||||
// or slow symlinks, so just make sure it's not negative
|
||||
assert!(stats.st_blocks >= 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_stat_and_fstat() {
|
||||
use nix::sys::stat::fstat;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
let file = File::create(&filename).unwrap();
|
||||
|
||||
let stat_result = stat(&filename);
|
||||
assert_stat_results(stat_result);
|
||||
|
||||
let fstat_result = fstat(&file);
|
||||
assert_stat_results(fstat_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_fstatat() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
File::create(&filename).unwrap();
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let result = stat::fstatat(&dirfd, &filename, fcntl::AtFlags::empty());
|
||||
assert_stat_results(result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_stat_fstat_lstat() {
|
||||
use nix::sys::stat::{fstat, lstat};
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("bar.txt");
|
||||
let linkname = tempdir.path().join("barlink");
|
||||
|
||||
File::create(&filename).unwrap();
|
||||
symlink("bar.txt", &linkname).unwrap();
|
||||
let link = File::open(&linkname).unwrap();
|
||||
|
||||
// should be the same result as calling stat,
|
||||
// since it's a regular file
|
||||
let stat_result = stat(&filename);
|
||||
assert_stat_results(stat_result);
|
||||
|
||||
let lstat_result = lstat(&linkname);
|
||||
assert_lstat_results(lstat_result);
|
||||
|
||||
let fstat_result = fstat(&link);
|
||||
assert_stat_results(fstat_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fchmod() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
let file = File::create(&filename).unwrap();
|
||||
|
||||
let mut mode1 = Mode::empty();
|
||||
mode1.insert(Mode::S_IRUSR);
|
||||
mode1.insert(Mode::S_IWUSR);
|
||||
fchmod(&file, mode1).unwrap();
|
||||
|
||||
let file_stat1 = stat(&filename).unwrap();
|
||||
assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
|
||||
|
||||
let mut mode2 = Mode::empty();
|
||||
mode2.insert(Mode::S_IROTH);
|
||||
fchmod(&file, mode2).unwrap();
|
||||
|
||||
let file_stat2 = stat(&filename).unwrap();
|
||||
assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_fchmodat() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
File::create(&fullpath).unwrap();
|
||||
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let mut mode1 = Mode::empty();
|
||||
mode1.insert(Mode::S_IRUSR);
|
||||
mode1.insert(Mode::S_IWUSR);
|
||||
fchmodat(&dirfd, filename, mode1, FchmodatFlags::FollowSymlink).unwrap();
|
||||
|
||||
let file_stat1 = stat(&fullpath).unwrap();
|
||||
assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
|
||||
|
||||
chdir(tempdir.path()).unwrap();
|
||||
|
||||
let mut mode2 = Mode::empty();
|
||||
mode2.insert(Mode::S_IROTH);
|
||||
fchmodat(
|
||||
fcntl::AT_FDCWD,
|
||||
filename,
|
||||
mode2,
|
||||
FchmodatFlags::FollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let file_stat2 = stat(&fullpath).unwrap();
|
||||
assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
|
||||
}
|
||||
|
||||
/// Asserts that the atime and mtime in a file's metadata match expected values.
|
||||
///
|
||||
/// The atime and mtime are expressed with a resolution of seconds because some file systems
|
||||
/// (like macOS's HFS+) do not have higher granularity.
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn assert_times_eq(
|
||||
exp_atime_sec: u64,
|
||||
exp_mtime_sec: u64,
|
||||
attr: &fs::Metadata,
|
||||
) {
|
||||
assert_eq!(
|
||||
Duration::new(exp_atime_sec, 0),
|
||||
attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::new(exp_mtime_sec, 0),
|
||||
attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimes() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550))
|
||||
.unwrap();
|
||||
assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
apple_targets,
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
fn test_lutimes() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target = tempdir.path().join("target");
|
||||
let fullpath = tempdir.path().join("symlink");
|
||||
drop(File::create(&target).unwrap());
|
||||
symlink(&target, &fullpath).unwrap();
|
||||
|
||||
let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
|
||||
lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230))
|
||||
.unwrap();
|
||||
assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
|
||||
|
||||
let target_metadata = fs::symlink_metadata(&target).unwrap();
|
||||
assert_eq!(
|
||||
exp_target_metadata.accessed().unwrap(),
|
||||
target_metadata.accessed().unwrap(),
|
||||
"atime of symlink target was unexpectedly modified"
|
||||
);
|
||||
assert_eq!(
|
||||
exp_target_metadata.modified().unwrap(),
|
||||
target_metadata.modified().unwrap(),
|
||||
"mtime of symlink target was unexpectedly modified"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_futimens() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
futimens(&fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
|
||||
assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimensat() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
utimensat(
|
||||
&dirfd,
|
||||
filename,
|
||||
&TimeSpec::seconds(12345),
|
||||
&TimeSpec::seconds(678),
|
||||
UtimensatFlags::FollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
|
||||
|
||||
chdir(tempdir.path()).unwrap();
|
||||
|
||||
utimensat(
|
||||
fcntl::AT_FDCWD,
|
||||
filename,
|
||||
&TimeSpec::seconds(500),
|
||||
&TimeSpec::seconds(800),
|
||||
UtimensatFlags::FollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_mkdirat_success_path() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "example_subdir";
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
mkdirat(&dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
|
||||
assert!(Path::exists(&tempdir.path().join(filename)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_mkdirat_success_mode() {
|
||||
let expected_bits =
|
||||
stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "example_subdir";
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
mkdirat(&dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
|
||||
let permissions = fs::metadata(tempdir.path().join(filename))
|
||||
.unwrap()
|
||||
.permissions();
|
||||
let mode = permissions.mode();
|
||||
assert_eq!(mode as mode_t, expected_bits)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_mkdirat_fail() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let not_dir_filename = "example_not_dir";
|
||||
let filename = "example_subdir_dir";
|
||||
let dirfd = fcntl::open(
|
||||
&tempdir.path().join(not_dir_filename),
|
||||
fcntl::OFlag::O_CREAT,
|
||||
stat::Mode::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
|
||||
assert_eq!(result, Errno::ENOTDIR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(
|
||||
freebsdlike,
|
||||
apple_targets,
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
fn test_mknod() {
|
||||
use stat::{lstat, mknod, SFlag};
|
||||
|
||||
let file_name = "test_file";
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target = tempdir.path().join(file_name);
|
||||
mknod(&target, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap();
|
||||
let mode = lstat(&target).unwrap().st_mode as mode_t;
|
||||
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
|
||||
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
freebsdlike,
|
||||
apple_targets,
|
||||
target_os = "haiku",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
fn test_mknodat() {
|
||||
use fcntl::{AtFlags, OFlag};
|
||||
use nix::dir::Dir;
|
||||
use stat::{fstatat, mknodat, SFlag};
|
||||
|
||||
let file_name = "test_file";
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target_dir =
|
||||
Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
|
||||
mknodat(&target_dir, file_name, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap();
|
||||
let mode = fstatat(&target_dir, file_name, AtFlags::AT_SYMLINK_NOFOLLOW)
|
||||
.unwrap()
|
||||
.st_mode as mode_t;
|
||||
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
|
||||
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_futimens_unchanged() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let old_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let old_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
|
||||
futimens(&fd, &TimeSpec::UTIME_OMIT, &TimeSpec::UTIME_OMIT).unwrap();
|
||||
|
||||
let new_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let new_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
assert_eq!(old_atime, new_atime);
|
||||
assert_eq!(old_mtime, new_mtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimensat_unchanged() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let old_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let old_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
utimensat(
|
||||
&dirfd,
|
||||
filename,
|
||||
&TimeSpec::UTIME_OMIT,
|
||||
&TimeSpec::UTIME_OMIT,
|
||||
UtimensatFlags::NoFollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
let new_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let new_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
assert_eq!(old_atime, new_atime);
|
||||
assert_eq!(old_mtime, new_mtime);
|
||||
}
|
||||
|
||||
// The conversion is not useless on all platforms.
|
||||
#[allow(clippy::useless_conversion)]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
@@ -7,23 +489,20 @@ fn test_chflags() {
|
||||
sys::stat::{fstat, FileFlag},
|
||||
unistd::chflags,
|
||||
};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
let f = NamedTempFile::new().unwrap();
|
||||
|
||||
let initial = FileFlag::from_bits_truncate(
|
||||
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
|
||||
);
|
||||
let initial =
|
||||
FileFlag::from_bits_truncate(fstat(&f).unwrap().st_flags.into());
|
||||
// UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted
|
||||
// in any way, so it's handy for testing.
|
||||
let commanded = initial ^ FileFlag::UF_OFFLINE;
|
||||
|
||||
chflags(f.path(), commanded).unwrap();
|
||||
|
||||
let changed = FileFlag::from_bits_truncate(
|
||||
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
|
||||
);
|
||||
let changed =
|
||||
FileFlag::from_bits_truncate(fstat(&f).unwrap().st_flags.into());
|
||||
|
||||
assert_eq!(commanded, changed);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::os::unix::io::{AsFd, AsRawFd};
|
||||
use std::os::unix::io::AsFd;
|
||||
use tempfile::tempfile;
|
||||
|
||||
use nix::errno::Errno;
|
||||
@@ -80,6 +80,7 @@ fn test_output_flags() {
|
||||
|
||||
// Test modifying local flags
|
||||
#[test]
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
fn test_local_flags() {
|
||||
// openpty uses ptname(3) internally
|
||||
let _m = crate::PTSNAME_MTX.lock();
|
||||
@@ -100,10 +101,10 @@ fn test_local_flags() {
|
||||
let pty = openpty(None, &termios).unwrap();
|
||||
|
||||
// Set the master is in nonblocking mode or reading will never return.
|
||||
let flags = fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_GETFL).unwrap();
|
||||
let flags = fcntl::fcntl(&pty.master, fcntl::F_GETFL).unwrap();
|
||||
let new_flags =
|
||||
fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
|
||||
fcntl::fcntl(pty.master.as_raw_fd(), fcntl::F_SETFL(new_flags)).unwrap();
|
||||
fcntl::fcntl(pty.master.as_fd(), fcntl::F_SETFL(new_flags)).unwrap();
|
||||
|
||||
// Write into the master
|
||||
let string = "foofoofoo\r";
|
||||
@@ -111,6 +112,6 @@ fn test_local_flags() {
|
||||
|
||||
// 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.as_raw_fd(), &mut buf).unwrap_err();
|
||||
let read = read(&pty.master, &mut buf).unwrap_err();
|
||||
assert_eq!(read, Errno::EAGAIN);
|
||||
}
|
||||
|
||||
26
third_party/rust/nix/test/sys/test_uio.rs
vendored
26
third_party/rust/nix/test/sys/test_uio.rs
vendored
@@ -1,10 +1,9 @@
|
||||
use nix::sys::uio::*;
|
||||
use nix::unistd::*;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand::distr::Alphanumeric;
|
||||
use rand::{rng, Rng};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::IoSlice;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::{cmp, iter};
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -15,10 +14,12 @@ use tempfile::tempdir;
|
||||
use tempfile::tempfile;
|
||||
|
||||
#[test]
|
||||
// On Solaris sometimes wrtitev() returns EINVAL.
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
fn test_writev() {
|
||||
let mut to_write = Vec::with_capacity(16 * 128);
|
||||
for _ in 0..16 {
|
||||
let s: String = thread_rng()
|
||||
let s: String = rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(128)
|
||||
@@ -34,7 +35,7 @@ fn test_writev() {
|
||||
let slice_len = if left <= 64 {
|
||||
left
|
||||
} else {
|
||||
thread_rng().gen_range(64..cmp::min(256, left))
|
||||
rng().random_range(64..cmp::min(256, left))
|
||||
};
|
||||
let b = &to_write[consumed..consumed + slice_len];
|
||||
iovecs.push(IoSlice::new(b));
|
||||
@@ -49,7 +50,7 @@ fn test_writev() {
|
||||
let written = write_res.expect("couldn't write");
|
||||
// Check whether we written all data
|
||||
assert_eq!(to_write.len(), written);
|
||||
let read_res = read(reader.as_raw_fd(), &mut read_buf[..]);
|
||||
let read_res = read(&reader, &mut read_buf[..]);
|
||||
let read = read_res.expect("couldn't read");
|
||||
// Check we have read as much as we written
|
||||
assert_eq!(read, written);
|
||||
@@ -60,7 +61,7 @@ fn test_writev() {
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_readv() {
|
||||
let s: String = thread_rng()
|
||||
let s: String = rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(128)
|
||||
@@ -73,7 +74,7 @@ fn test_readv() {
|
||||
let vec_len = if left <= 64 {
|
||||
left
|
||||
} else {
|
||||
thread_rng().gen_range(64..cmp::min(256, left))
|
||||
rng().random_range(64..cmp::min(256, left))
|
||||
};
|
||||
let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
|
||||
storage.push(v);
|
||||
@@ -143,7 +144,8 @@ fn test_pread() {
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "haiku",
|
||||
target_os = "solaris"
|
||||
target_os = "solaris",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
fn test_pwritev() {
|
||||
use std::io::Read;
|
||||
@@ -182,7 +184,8 @@ fn test_pwritev() {
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "haiku",
|
||||
target_os = "solaris"
|
||||
target_os = "solaris",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
fn test_preadv() {
|
||||
use std::io::Write;
|
||||
@@ -228,7 +231,6 @@ fn test_process_vm_readv() {
|
||||
use nix::sys::signal::*;
|
||||
use nix::sys::wait::*;
|
||||
use nix::unistd::ForkResult::*;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
|
||||
let _m = crate::FORK_MTX.lock();
|
||||
@@ -242,7 +244,7 @@ fn test_process_vm_readv() {
|
||||
Parent { child } => {
|
||||
drop(w);
|
||||
// wait for child
|
||||
read(r.as_raw_fd(), &mut [0u8]).unwrap();
|
||||
read(&r, &mut [0u8]).unwrap();
|
||||
drop(r);
|
||||
|
||||
let ptr = vector.as_ptr() as usize;
|
||||
|
||||
35
third_party/rust/nix/test/test.rs
vendored
35
third_party/rust/nix/test/test.rs
vendored
@@ -1,6 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
#[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)]
|
||||
#[cfg_attr(not(any(target_os = "redox")), macro_use)]
|
||||
extern crate nix;
|
||||
|
||||
#[macro_use]
|
||||
@@ -13,7 +13,11 @@ mod test_errno;
|
||||
mod test_fcntl;
|
||||
#[cfg(linux_android)]
|
||||
mod test_kmod;
|
||||
#[cfg(any(freebsdlike, target_os = "linux", target_os = "netbsd"))]
|
||||
#[cfg(any(
|
||||
freebsdlike,
|
||||
all(target_os = "linux", not(target_env = "ohos")),
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
mod test_mq;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
mod test_net;
|
||||
@@ -33,13 +37,23 @@ mod test_pty;
|
||||
mod test_sched;
|
||||
#[cfg(any(linux_android, freebsdlike, apple_targets, solarish))]
|
||||
mod test_sendfile;
|
||||
mod test_stat;
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
apple_targets
|
||||
))]
|
||||
mod test_spawn;
|
||||
|
||||
mod test_syslog;
|
||||
|
||||
mod test_time;
|
||||
mod test_unistd;
|
||||
|
||||
use nix::unistd::{chdir, getcwd, read};
|
||||
use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
|
||||
use std::os::unix::io::{AsFd, AsRawFd};
|
||||
use std::os::unix::io::AsFd;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s
|
||||
@@ -48,13 +62,14 @@ fn read_exact<Fd: AsFd>(f: Fd, buf: &mut [u8]) {
|
||||
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.as_fd().as_raw_fd(), remaining).unwrap();
|
||||
len += read(&f, remaining).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Any test that creates child processes or can be affected by child processes must grab this mutex, regardless
|
||||
/// of what it does with those children. It must hold the mutex until the
|
||||
/// child processes are waited upon.
|
||||
/// Any test that creates child processes or can be affected by child processes
|
||||
/// must grab this mutex, regardless of what it does with those children.
|
||||
///
|
||||
/// It must hold the mutex until the child processes are waited upon.
|
||||
pub static FORK_MTX: Mutex<()> = Mutex::new(());
|
||||
/// Any test that changes the process's current working directory must grab
|
||||
/// the RwLock exclusively. Any process that cares about the current
|
||||
@@ -76,7 +91,7 @@ struct DirRestore<'a> {
|
||||
_g: RwLockWriteGuard<'a, ()>,
|
||||
}
|
||||
|
||||
impl<'a> DirRestore<'a> {
|
||||
impl DirRestore<'_> {
|
||||
fn new() -> Self {
|
||||
let guard = crate::CWD_LOCK.write();
|
||||
DirRestore {
|
||||
@@ -86,7 +101,7 @@ impl<'a> DirRestore<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for DirRestore<'a> {
|
||||
impl Drop for DirRestore<'_> {
|
||||
fn drop(&mut self) {
|
||||
let r = chdir(&self.d);
|
||||
if std::thread::panicking() {
|
||||
|
||||
7
third_party/rust/nix/test/test_dir.rs
vendored
7
third_party/rust/nix/test/test_dir.rs
vendored
@@ -16,7 +16,6 @@ fn flags() -> OFlag {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::unnecessary_sort_by)] // False positive
|
||||
fn read() {
|
||||
let tmp = tempdir().unwrap();
|
||||
File::create(tmp.path().join("foo")).unwrap();
|
||||
@@ -57,9 +56,3 @@ fn rewind() {
|
||||
assert_eq!(entries1, entries2);
|
||||
assert_eq!(entries2, entries3);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
#[test]
|
||||
fn ebadf() {
|
||||
assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::EBADF);
|
||||
}
|
||||
|
||||
222
third_party/rust/nix/test/test_fcntl.rs
vendored
222
third_party/rust/nix/test/test_fcntl.rs
vendored
@@ -21,7 +21,7 @@ use nix::fcntl::{renameat2, RenameFlags};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::Mode;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::unistd::{close, read};
|
||||
use nix::unistd::read;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::fs::File;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -45,7 +45,7 @@ fn test_openat() {
|
||||
open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty())
|
||||
.unwrap();
|
||||
let fd = openat(
|
||||
Some(dirfd),
|
||||
dirfd,
|
||||
tmp.path().file_name().unwrap(),
|
||||
OFlag::O_RDONLY,
|
||||
Mode::empty(),
|
||||
@@ -53,11 +53,8 @@ fn test_openat() {
|
||||
.unwrap();
|
||||
|
||||
let mut buf = [0u8; 1024];
|
||||
assert_eq!(4, read(fd, &mut buf).unwrap());
|
||||
assert_eq!(4, read(&fd, &mut buf).unwrap());
|
||||
assert_eq!(CONTENTS, &buf[0..4]);
|
||||
|
||||
close(fd).unwrap();
|
||||
close(dirfd).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -85,11 +82,8 @@ fn test_openat2() {
|
||||
.unwrap();
|
||||
|
||||
let mut buf = [0u8; 1024];
|
||||
assert_eq!(4, read(fd, &mut buf).unwrap());
|
||||
assert_eq!(4, read(&fd, &mut buf).unwrap());
|
||||
assert_eq!(CONTENTS, &buf[0..4]);
|
||||
|
||||
close(fd).unwrap();
|
||||
close(dirfd).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -115,7 +109,7 @@ fn test_openat2_forbidden() {
|
||||
.flags(OFlag::O_RDONLY)
|
||||
.resolve(ResolveFlag::RESOLVE_BENEATH),
|
||||
);
|
||||
assert_eq!(Err(Errno::EXDEV), res);
|
||||
assert_eq!(res.unwrap_err(), Errno::EXDEV);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -129,13 +123,11 @@ fn test_renameat() {
|
||||
let new_dir = tempfile::tempdir().unwrap();
|
||||
let new_dirfd =
|
||||
open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
|
||||
renameat(&old_dirfd, "old", &new_dirfd, "new").unwrap();
|
||||
assert_eq!(
|
||||
renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
|
||||
renameat(&old_dirfd, "old", &new_dirfd, "new").unwrap_err(),
|
||||
Errno::ENOENT
|
||||
);
|
||||
close(old_dirfd).unwrap();
|
||||
close(new_dirfd).unwrap();
|
||||
assert!(new_dir.path().join("new").exists());
|
||||
}
|
||||
|
||||
@@ -158,27 +150,13 @@ fn test_renameat2_behaves_like_renameat_with_no_flags() {
|
||||
let new_dir = tempfile::tempdir().unwrap();
|
||||
let new_dirfd =
|
||||
open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
renameat2(
|
||||
Some(old_dirfd),
|
||||
"old",
|
||||
Some(new_dirfd),
|
||||
"new",
|
||||
RenameFlags::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
renameat2(&old_dirfd, "old", &new_dirfd, "new", RenameFlags::empty())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
renameat2(
|
||||
Some(old_dirfd),
|
||||
"old",
|
||||
Some(new_dirfd),
|
||||
"new",
|
||||
RenameFlags::empty()
|
||||
)
|
||||
.unwrap_err(),
|
||||
renameat2(&old_dirfd, "old", &new_dirfd, "new", RenameFlags::empty())
|
||||
.unwrap_err(),
|
||||
Errno::ENOENT
|
||||
);
|
||||
close(old_dirfd).unwrap();
|
||||
close(new_dirfd).unwrap();
|
||||
assert!(new_dir.path().join("new").exists());
|
||||
}
|
||||
|
||||
@@ -210,9 +188,9 @@ fn test_renameat2_exchange() {
|
||||
new_f.write_all(b"new").unwrap();
|
||||
}
|
||||
renameat2(
|
||||
Some(old_dirfd),
|
||||
&old_dirfd,
|
||||
"old",
|
||||
Some(new_dirfd),
|
||||
&new_dirfd,
|
||||
"new",
|
||||
RenameFlags::RENAME_EXCHANGE,
|
||||
)
|
||||
@@ -225,8 +203,6 @@ fn test_renameat2_exchange() {
|
||||
let mut old_f = File::open(&old_path).unwrap();
|
||||
old_f.read_to_string(&mut buf).unwrap();
|
||||
assert_eq!(buf, "new");
|
||||
close(old_dirfd).unwrap();
|
||||
close(new_dirfd).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -252,17 +228,15 @@ fn test_renameat2_noreplace() {
|
||||
File::create(new_path).unwrap();
|
||||
assert_eq!(
|
||||
renameat2(
|
||||
Some(old_dirfd),
|
||||
&old_dirfd,
|
||||
"old",
|
||||
Some(new_dirfd),
|
||||
&new_dirfd,
|
||||
"new",
|
||||
RenameFlags::RENAME_NOREPLACE
|
||||
)
|
||||
.unwrap_err(),
|
||||
Errno::EEXIST
|
||||
);
|
||||
close(old_dirfd).unwrap();
|
||||
close(new_dirfd).unwrap();
|
||||
assert!(new_dir.path().join("new").exists());
|
||||
assert!(old_dir.path().join("old").exists());
|
||||
}
|
||||
@@ -280,7 +254,7 @@ fn test_readlink() {
|
||||
|
||||
assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
|
||||
assert_eq!(
|
||||
readlinkat(Some(dirfd), "b").unwrap().to_str().unwrap(),
|
||||
readlinkat(dirfd, "b").unwrap().to_str().unwrap(),
|
||||
expected_dir
|
||||
);
|
||||
}
|
||||
@@ -301,7 +275,6 @@ fn test_readlink() {
|
||||
#[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";
|
||||
|
||||
@@ -312,14 +285,7 @@ fn test_copy_file_range() {
|
||||
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();
|
||||
copy_file_range(&tmp1, Some(&mut from_offset), &tmp2, None, 3).unwrap();
|
||||
|
||||
let mut res: String = String::new();
|
||||
tmp2.rewind().unwrap();
|
||||
@@ -334,7 +300,6 @@ mod linux_android {
|
||||
use libc::loff_t;
|
||||
use std::io::prelude::*;
|
||||
use std::io::IoSlice;
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
use nix::fcntl::*;
|
||||
use nix::unistd::{pipe, read, write};
|
||||
@@ -360,7 +325,7 @@ mod linux_android {
|
||||
assert_eq!(2, res);
|
||||
|
||||
let mut buf = [0u8; 1024];
|
||||
assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(2, read(&rd, &mut buf).unwrap());
|
||||
assert_eq!(b"f1", &buf[0..2]);
|
||||
assert_eq!(7, offset);
|
||||
}
|
||||
@@ -379,11 +344,11 @@ mod linux_android {
|
||||
let mut buf = [0u8; 1024];
|
||||
|
||||
// Check the tee'd bytes are at rd2.
|
||||
assert_eq!(2, read(rd2.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(2, read(&rd2, &mut buf).unwrap());
|
||||
assert_eq!(b"ab", &buf[0..2]);
|
||||
|
||||
// Check all the bytes are still at rd1.
|
||||
assert_eq!(3, read(rd1.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(3, read(&rd1, &mut buf).unwrap());
|
||||
assert_eq!(b"abc", &buf[0..3]);
|
||||
}
|
||||
|
||||
@@ -401,7 +366,7 @@ mod linux_android {
|
||||
|
||||
// Check the bytes can be read at rd.
|
||||
let mut buf = [0u8; 32];
|
||||
assert_eq!(6, read(rd.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(6, read(&rd, &mut buf).unwrap());
|
||||
assert_eq!(b"abcdef", &buf[0..6]);
|
||||
}
|
||||
|
||||
@@ -410,12 +375,11 @@ mod linux_android {
|
||||
fn test_fallocate() {
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
|
||||
let fd = tmp.as_raw_fd();
|
||||
fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
|
||||
fallocate(&tmp, FallocateFlags::empty(), 0, 100).unwrap();
|
||||
|
||||
// Check if we read exactly 100 bytes
|
||||
let mut buf = [0u8; 200];
|
||||
assert_eq!(100, read(fd, &mut buf).unwrap());
|
||||
assert_eq!(100, read(&tmp, &mut buf).unwrap());
|
||||
}
|
||||
|
||||
// The tests below are disabled for the listed targets
|
||||
@@ -432,7 +396,6 @@ mod linux_android {
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
|
||||
let fd = tmp.as_raw_fd();
|
||||
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
|
||||
@@ -440,7 +403,7 @@ mod linux_android {
|
||||
// skip the test.
|
||||
skip!("/proc/locks does not work on overlayfs");
|
||||
}
|
||||
let inode = fstat(fd).expect("fstat failed").st_ino as usize;
|
||||
let inode = fstat(&tmp).expect("fstat failed").st_ino as usize;
|
||||
|
||||
let mut flock: libc::flock = unsafe {
|
||||
mem::zeroed() // required for Linux/mips
|
||||
@@ -450,14 +413,15 @@ mod linux_android {
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
flock.l_pid = 0;
|
||||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
|
||||
fcntl(&tmp, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
|
||||
assert_eq!(
|
||||
Some(("OFDLCK".to_string(), "WRITE".to_string())),
|
||||
lock_info(inode)
|
||||
);
|
||||
|
||||
flock.l_type = libc::F_UNLCK as libc::c_short;
|
||||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed");
|
||||
fcntl(&tmp, FcntlArg::F_OFD_SETLKW(&flock))
|
||||
.expect("write unlock failed");
|
||||
assert_eq!(None, lock_info(inode));
|
||||
}
|
||||
|
||||
@@ -470,7 +434,6 @@ mod linux_android {
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
|
||||
let fd = tmp.as_raw_fd();
|
||||
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
|
||||
@@ -478,7 +441,7 @@ mod linux_android {
|
||||
// skip the test.
|
||||
skip!("/proc/locks does not work on overlayfs");
|
||||
}
|
||||
let inode = fstat(fd).expect("fstat failed").st_ino as usize;
|
||||
let inode = fstat(&tmp).expect("fstat failed").st_ino as usize;
|
||||
|
||||
let mut flock: libc::flock = unsafe {
|
||||
mem::zeroed() // required for Linux/mips
|
||||
@@ -488,14 +451,15 @@ mod linux_android {
|
||||
flock.l_start = 0;
|
||||
flock.l_len = 0;
|
||||
flock.l_pid = 0;
|
||||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
|
||||
fcntl(&tmp, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
|
||||
assert_eq!(
|
||||
Some(("OFDLCK".to_string(), "READ".to_string())),
|
||||
lock_info(inode)
|
||||
);
|
||||
|
||||
flock.l_type = libc::F_UNLCK as libc::c_short;
|
||||
fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed");
|
||||
fcntl(&tmp, FcntlArg::F_OFD_SETLKW(&flock))
|
||||
.expect("read unlock failed");
|
||||
assert_eq!(None, lock_info(inode));
|
||||
}
|
||||
|
||||
@@ -530,30 +494,23 @@ mod linux_android {
|
||||
target_os = "freebsd"
|
||||
))]
|
||||
mod test_posix_fadvise {
|
||||
|
||||
use nix::errno::Errno;
|
||||
use nix::fcntl::*;
|
||||
use nix::unistd::pipe;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[test]
|
||||
fn test_success() {
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
let fd = tmp.as_raw_fd();
|
||||
posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
|
||||
posix_fadvise(&tmp, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
|
||||
.expect("posix_fadvise failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_errno() {
|
||||
let (rd, _wr) = pipe().unwrap();
|
||||
let res = posix_fadvise(
|
||||
rd.as_raw_fd(),
|
||||
0,
|
||||
100,
|
||||
PosixFadviseAdvice::POSIX_FADV_WILLNEED,
|
||||
);
|
||||
let res =
|
||||
posix_fadvise(&rd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED);
|
||||
assert_eq!(res, Err(Errno::ESPIPE));
|
||||
}
|
||||
}
|
||||
@@ -570,15 +527,14 @@ mod test_posix_fallocate {
|
||||
use nix::errno::Errno;
|
||||
use nix::fcntl::*;
|
||||
use nix::unistd::pipe;
|
||||
use std::{io::Read, os::unix::io::AsRawFd};
|
||||
use std::io::Read;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[test]
|
||||
fn success() {
|
||||
const LEN: usize = 100;
|
||||
let mut tmp = NamedTempFile::new().unwrap();
|
||||
let fd = tmp.as_raw_fd();
|
||||
let res = posix_fallocate(fd, 0, LEN as libc::off_t);
|
||||
let res = posix_fallocate(&tmp, 0, LEN as libc::off_t);
|
||||
match res {
|
||||
Ok(_) => {
|
||||
let mut data = [1u8; LEN];
|
||||
@@ -600,7 +556,7 @@ mod test_posix_fallocate {
|
||||
#[test]
|
||||
fn errno() {
|
||||
let (rd, _wr) = pipe().unwrap();
|
||||
let err = posix_fallocate(rd.as_raw_fd(), 0, 100).unwrap_err();
|
||||
let err = posix_fallocate(&rd, 0, 100).unwrap_err();
|
||||
match err {
|
||||
Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
|
||||
errno => panic!("unexpected errno {errno}",),
|
||||
@@ -612,13 +568,12 @@ mod test_posix_fallocate {
|
||||
#[test]
|
||||
fn test_f_get_path() {
|
||||
use nix::fcntl::*;
|
||||
use std::{os::unix::io::AsRawFd, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
let fd = tmp.as_raw_fd();
|
||||
let mut path = PathBuf::new();
|
||||
let res =
|
||||
fcntl(fd, FcntlArg::F_GETPATH(&mut path)).expect("get path failed");
|
||||
fcntl(&tmp, FcntlArg::F_GETPATH(&mut path)).expect("get path failed");
|
||||
assert_ne!(res, -1);
|
||||
assert_eq!(
|
||||
path.as_path().canonicalize().unwrap(),
|
||||
@@ -628,14 +583,31 @@ fn test_f_get_path() {
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_f_get_path_nofirmlink() {
|
||||
fn test_f_preallocate() {
|
||||
use nix::fcntl::*;
|
||||
use std::{os::unix::io::AsRawFd, path::PathBuf};
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
let fd = tmp.as_raw_fd();
|
||||
let mut st: libc::fstore_t = unsafe { std::mem::zeroed() };
|
||||
|
||||
st.fst_flags = libc::F_ALLOCATECONTIG as libc::c_uint;
|
||||
st.fst_posmode = libc::F_PEOFPOSMODE;
|
||||
st.fst_length = 1024;
|
||||
let res = fcntl(tmp, FcntlArg::F_PREALLOCATE(&mut st))
|
||||
.expect("preallocation failed");
|
||||
|
||||
assert_eq!(res, 0);
|
||||
assert!(st.fst_bytesalloc > 0);
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_f_get_path_nofirmlink() {
|
||||
use nix::fcntl::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
let mut path = PathBuf::new();
|
||||
let res = fcntl(fd, FcntlArg::F_GETPATH_NOFIRMLINK(&mut path))
|
||||
let res = fcntl(&tmp, FcntlArg::F_GETPATH_NOFIRMLINK(&mut path))
|
||||
.expect("get path failed");
|
||||
let mut tmpstr = String::from("/System/Volumes/Data");
|
||||
tmpstr.push_str(
|
||||
@@ -662,7 +634,7 @@ fn test_f_get_path_nofirmlink() {
|
||||
#[test]
|
||||
fn test_f_kinfo() {
|
||||
use nix::fcntl::*;
|
||||
use std::{os::unix::io::AsRawFd, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
// With TMPDIR set with UFS, the vnode name is not entered
|
||||
@@ -670,9 +642,9 @@ fn test_f_kinfo() {
|
||||
// Therefore, we reopen the tempfile a second time for the test
|
||||
// to pass.
|
||||
let tmp2 = File::open(tmp.path()).unwrap();
|
||||
let fd = tmp2.as_raw_fd();
|
||||
let mut path = PathBuf::new();
|
||||
let res = fcntl(fd, FcntlArg::F_KINFO(&mut path)).expect("get path failed");
|
||||
let res =
|
||||
fcntl(&tmp2, FcntlArg::F_KINFO(&mut path)).expect("get path failed");
|
||||
assert_ne!(res, -1);
|
||||
assert_eq!(path, tmp.path());
|
||||
}
|
||||
@@ -778,3 +750,71 @@ mod test_flock {
|
||||
.expect_err("Should not have been able to lock the file");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_f_rdadvise() {
|
||||
use nix::fcntl::*;
|
||||
|
||||
let contents = vec![1; 1024];
|
||||
let mut buf = [0; 1024];
|
||||
let mut tmp = NamedTempFile::new().unwrap();
|
||||
tmp.write_all(&contents).unwrap();
|
||||
let fd = open(tmp.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let rad = libc::radvisory {
|
||||
ra_offset: 0,
|
||||
ra_count: contents.len() as _,
|
||||
};
|
||||
let res = fcntl(&tmp, FcntlArg::F_RDADVISE(rad)).expect("rdadivse failed");
|
||||
assert_ne!(res, -1);
|
||||
assert_eq!(contents.len(), read(&fd, &mut buf).unwrap());
|
||||
assert_eq!(contents, &buf[0..contents.len()]);
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_f_log2phys() {
|
||||
use nix::fcntl::*;
|
||||
|
||||
const CONTENTS: &[u8] = b"abcd";
|
||||
let mut tmp = NamedTempFile::new().unwrap();
|
||||
tmp.write_all(CONTENTS).unwrap();
|
||||
let mut offset: libc::off_t = 0;
|
||||
let mut res = fcntl(&tmp, FcntlArg::F_LOG2PHYS(&mut offset))
|
||||
.expect("log2phys failed");
|
||||
assert_ne!(res, -1);
|
||||
assert_ne!(offset, 0);
|
||||
let mut info: libc::log2phys = unsafe { std::mem::zeroed() };
|
||||
info.l2p_contigbytes = CONTENTS.len() as _;
|
||||
info.l2p_devoffset = 3;
|
||||
res = fcntl(&tmp, FcntlArg::F_LOG2PHYS_EXT(&mut info))
|
||||
.expect("log2phys failed");
|
||||
assert_ne!(res, -1);
|
||||
assert_ne!({ info.l2p_devoffset }, 3);
|
||||
}
|
||||
|
||||
#[cfg(apple_targets)]
|
||||
#[test]
|
||||
fn test_f_transferextents() {
|
||||
use nix::fcntl::*;
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let tmp1 = NamedTempFile::new().unwrap();
|
||||
let tmp2 = NamedTempFile::new().unwrap();
|
||||
let res = fcntl(&tmp1, FcntlArg::F_TRANSFEREXTENTS(tmp2.as_raw_fd()))
|
||||
.expect("transferextents failed");
|
||||
assert_ne!(res, -1);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[test]
|
||||
fn test_f_readahead() {
|
||||
use nix::fcntl::*;
|
||||
|
||||
let tmp = NamedTempFile::new().unwrap();
|
||||
let mut res = fcntl(&tmp, FcntlArg::F_READAHEAD(1_000_000))
|
||||
.expect("read ahead failed");
|
||||
assert_ne!(res, -1);
|
||||
res = fcntl(&tmp, FcntlArg::F_READAHEAD(-1024)).expect("read ahead failed");
|
||||
assert_ne!(res, -1);
|
||||
}
|
||||
|
||||
2
third_party/rust/nix/test/test_net.rs
vendored
2
third_party/rust/nix/test/test_net.rs
vendored
@@ -10,11 +10,13 @@ const LOOPBACK: &[u8] = b"lo0";
|
||||
const LOOPBACK: &[u8] = b"loop";
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
fn test_if_nametoindex() {
|
||||
if_nametoindex(LOOPBACK).expect("assertion failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "cygwin", ignore)]
|
||||
fn test_if_indextoname() {
|
||||
let loopback_index = if_nametoindex(LOOPBACK).expect("assertion failed");
|
||||
assert_eq!(
|
||||
|
||||
12
third_party/rust/nix/test/test_pty.rs
vendored
12
third_party/rust/nix/test/test_pty.rs
vendored
@@ -108,20 +108,23 @@ fn open_ptty_pair() -> (PtyMaster, File) {
|
||||
// after opening a device path returned from ptsname().
|
||||
let ptem = b"ptem\0";
|
||||
let ldterm = b"ldterm\0";
|
||||
let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) };
|
||||
let r = unsafe { ioctl(slave_fd.as_raw_fd(), I_FIND, ldterm.as_ptr()) };
|
||||
if r < 0 {
|
||||
panic!("I_FIND failure");
|
||||
} else if r == 0 {
|
||||
if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 {
|
||||
if unsafe { ioctl(slave_fd.as_raw_fd(), I_PUSH, ptem.as_ptr()) } < 0
|
||||
{
|
||||
panic!("I_PUSH ptem failure");
|
||||
}
|
||||
if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 {
|
||||
if unsafe { ioctl(slave_fd.as_raw_fd(), I_PUSH, ldterm.as_ptr()) }
|
||||
< 0
|
||||
{
|
||||
panic!("I_PUSH ldterm failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let slave = unsafe { File::from_raw_fd(slave_fd) };
|
||||
let slave = File::from(slave_fd);
|
||||
|
||||
(master, slave)
|
||||
}
|
||||
@@ -145,6 +148,7 @@ fn make_raw<Fd: AsFd>(fd: Fd) {
|
||||
|
||||
/// Test `io::Read` on the PTTY master
|
||||
#[test]
|
||||
#[cfg(not(target_os = "solaris"))]
|
||||
fn test_read_ptty_pair() {
|
||||
let (mut master, mut slave) = open_ptty_pair();
|
||||
make_raw(&slave);
|
||||
|
||||
22
third_party/rust/nix/test/test_sendfile.rs
vendored
22
third_party/rust/nix/test/test_sendfile.rs
vendored
@@ -7,10 +7,12 @@ use tempfile::tempfile;
|
||||
cfg_if! {
|
||||
if #[cfg(linux_android)] {
|
||||
use nix::unistd::{pipe, read};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
} else if #[cfg(any(freebsdlike, apple_targets, solarish))] {
|
||||
} else if #[cfg(any(freebsdlike, apple_targets))] {
|
||||
use std::net::Shutdown;
|
||||
use std::os::unix::net::UnixStream;
|
||||
} else if #[cfg(solarish)] {
|
||||
use std::net::Shutdown;
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +30,7 @@ fn test_sendfile_linux() {
|
||||
assert_eq!(2, res);
|
||||
|
||||
let mut buf = [0u8; 1024];
|
||||
assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(2, read(&rd, &mut buf).unwrap());
|
||||
assert_eq!(b"f1", &buf[0..2]);
|
||||
assert_eq!(7, offset);
|
||||
}
|
||||
@@ -47,7 +49,7 @@ fn test_sendfile64_linux() {
|
||||
assert_eq!(2, res);
|
||||
|
||||
let mut buf = [0u8; 1024];
|
||||
assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
|
||||
assert_eq!(2, read(&rd, &mut buf).unwrap());
|
||||
assert_eq!(b"f1", &buf[0..2]);
|
||||
assert_eq!(7, offset);
|
||||
}
|
||||
@@ -95,7 +97,7 @@ fn test_sendfile_freebsd() {
|
||||
+ &trailer_strings.concat();
|
||||
|
||||
// Verify the message that was sent
|
||||
assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
|
||||
assert_eq!(bytes_written as usize, expected_string.len());
|
||||
|
||||
let mut read_string = String::new();
|
||||
let bytes_read = rd.read_to_string(&mut read_string).unwrap();
|
||||
@@ -144,7 +146,7 @@ fn test_sendfile_dragonfly() {
|
||||
+ &trailer_strings.concat();
|
||||
|
||||
// Verify the message that was sent
|
||||
assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
|
||||
assert_eq!(bytes_written as usize, expected_string.len());
|
||||
|
||||
let mut read_string = String::new();
|
||||
let bytes_read = rd.read_to_string(&mut read_string).unwrap();
|
||||
@@ -223,7 +225,11 @@ fn test_sendfilev() {
|
||||
trailer_data
|
||||
.write_all(trailer_strings.concat().as_bytes())
|
||||
.unwrap();
|
||||
let (mut rd, wr) = UnixStream::pair().unwrap();
|
||||
// Create a TCP socket pair (listener and client)
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
let mut rd = TcpStream::connect(addr).unwrap();
|
||||
let (wr, _) = listener.accept().unwrap();
|
||||
let vec: &[SendfileVec] = &[
|
||||
SendfileVec::new(
|
||||
header_data.as_fd(),
|
||||
@@ -244,7 +250,7 @@ fn test_sendfilev() {
|
||||
|
||||
let (res, bytes_written) = sendfilev(&wr, vec);
|
||||
assert!(res.is_ok());
|
||||
wr.shutdown(Shutdown::Both).unwrap();
|
||||
wr.shutdown(Shutdown::Write).unwrap();
|
||||
|
||||
// Prepare the expected result
|
||||
let expected_string = header_strings.concat()
|
||||
|
||||
193
third_party/rust/nix/test/test_spawn.rs
vendored
Normal file
193
third_party/rust/nix/test/test_spawn.rs
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
use super::FORK_MTX;
|
||||
use nix::errno::Errno;
|
||||
use nix::spawn::{self, PosixSpawnAttr, PosixSpawnFileActions};
|
||||
use nix::sys::signal;
|
||||
use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
/// Helper function to find a binary in the $PATH
|
||||
fn which(exe_name: &str) -> Option<std::path::PathBuf> {
|
||||
std::env::var_os("PATH").and_then(|paths| {
|
||||
std::env::split_paths(&paths)
|
||||
.filter_map(|dir| {
|
||||
let full_path = dir.join(exe_name);
|
||||
if full_path.is_file() {
|
||||
Some(full_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.next()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_true() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let bin = which("true").unwrap();
|
||||
let args = &[
|
||||
CString::new("true").unwrap(),
|
||||
CString::new("story").unwrap(),
|
||||
];
|
||||
let vars: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let pid =
|
||||
spawn::posix_spawn(bin.as_path(), &actions, &attr, args, vars).unwrap();
|
||||
|
||||
let status = waitpid(pid, Some(WaitPidFlag::empty())).unwrap();
|
||||
|
||||
match status {
|
||||
WaitStatus::Exited(wpid, ret) => {
|
||||
assert_eq!(pid, wpid);
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_sleep() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let bin = which("sleep").unwrap();
|
||||
let args = &[CString::new("sleep").unwrap(), CString::new("30").unwrap()];
|
||||
let vars: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let pid =
|
||||
spawn::posix_spawn(bin.as_path(), &actions, &attr, args, vars).unwrap();
|
||||
|
||||
let status =
|
||||
waitpid(pid, WaitPidFlag::from_bits(WaitPidFlag::WNOHANG.bits()))
|
||||
.unwrap();
|
||||
match status {
|
||||
WaitStatus::StillAlive => {}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
|
||||
signal::kill(pid, signal::SIGTERM).unwrap();
|
||||
|
||||
let status = waitpid(pid, Some(WaitPidFlag::empty())).unwrap();
|
||||
match status {
|
||||
WaitStatus::Signaled(wpid, wsignal, _) => {
|
||||
assert_eq!(pid, wpid);
|
||||
assert_eq!(wsignal, signal::SIGTERM);
|
||||
}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
// `posix_spawn(path_not_exist)` succeeds under QEMU, so ignore the test. No need
|
||||
// to investigate the root cause, this test still works in native environments, which
|
||||
// is sufficient to test the binding.
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
fn spawn_cmd_does_not_exist() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let args = &[CString::new("buzz").unwrap()];
|
||||
let envs: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let bin = "2b7433c4-523b-470c-abb5-d7ee9fd295d5-fdasf";
|
||||
let errno =
|
||||
spawn::posix_spawn(bin, &actions, &attr, args, envs).unwrap_err();
|
||||
assert_eq!(errno, Errno::ENOENT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawnp_true() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let bin = &CString::new("true").unwrap();
|
||||
let args = &[
|
||||
CString::new("true").unwrap(),
|
||||
CString::new("story").unwrap(),
|
||||
];
|
||||
let vars: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let pid = spawn::posix_spawnp(bin, &actions, &attr, args, vars).unwrap();
|
||||
|
||||
let status = waitpid(pid, Some(WaitPidFlag::empty())).unwrap();
|
||||
|
||||
match status {
|
||||
WaitStatus::Exited(wpid, ret) => {
|
||||
assert_eq!(pid, wpid);
|
||||
assert_eq!(ret, 0);
|
||||
}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawnp_sleep() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let bin = &CString::new("sleep").unwrap();
|
||||
let args = &[CString::new("sleep").unwrap(), CString::new("30").unwrap()];
|
||||
let vars: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let pid = spawn::posix_spawnp(bin, &actions, &attr, args, vars).unwrap();
|
||||
|
||||
let status =
|
||||
waitpid(pid, WaitPidFlag::from_bits(WaitPidFlag::WNOHANG.bits()))
|
||||
.unwrap();
|
||||
match status {
|
||||
WaitStatus::StillAlive => {}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
|
||||
signal::kill(pid, signal::SIGTERM).unwrap();
|
||||
|
||||
let status = waitpid(pid, Some(WaitPidFlag::empty())).unwrap();
|
||||
match status {
|
||||
WaitStatus::Signaled(wpid, wsignal, _) => {
|
||||
assert_eq!(pid, wpid);
|
||||
assert_eq!(wsignal, signal::SIGTERM);
|
||||
}
|
||||
_ => {
|
||||
panic!("Invalid WaitStatus");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
// `posix_spawnp(bin_not_exist)` succeeds under QEMU, so ignore the test. No need
|
||||
// to investigate the root cause, this test still works in native environments, which
|
||||
// is sufficient to test the binding.
|
||||
#[cfg_attr(qemu, ignore)]
|
||||
fn spawnp_cmd_does_not_exist() {
|
||||
let _guard = FORK_MTX.lock();
|
||||
|
||||
let args = &[CString::new("buzz").unwrap()];
|
||||
let envs: &[CString] = &[];
|
||||
let actions = PosixSpawnFileActions::init().unwrap();
|
||||
let attr = PosixSpawnAttr::init().unwrap();
|
||||
|
||||
let bin = CStr::from_bytes_with_nul(
|
||||
"2b7433c4-523b-470c-abb5-d7ee9fd295d5-fdasf\0".as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let errno =
|
||||
spawn::posix_spawnp(bin, &actions, &attr, args, envs).unwrap_err();
|
||||
assert_eq!(errno, Errno::ENOENT);
|
||||
}
|
||||
487
third_party/rust/nix/test/test_stat.rs
vendored
487
third_party/rust/nix/test/test_stat.rs
vendored
@@ -1,487 +0,0 @@
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::os::unix::fs::symlink;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::os::unix::prelude::AsRawFd;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use std::path::Path;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
use libc::mode_t;
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use libc::{S_IFLNK, S_IFMT};
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::errno::Errno;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::fcntl;
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
apple_targets,
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
use nix::sys::stat::lutimes;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::utimensat;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::FchmodatFlags;
|
||||
use nix::sys::stat::Mode;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::UtimensatFlags;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::{self};
|
||||
use nix::sys::stat::{fchmod, stat};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::sys::stat::{fchmodat, mkdirat};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::stat::{futimens, utimes};
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use nix::sys::stat::FileStat;
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use nix::unistd::chdir;
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
use nix::Result;
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn assert_stat_results(stat_result: Result<FileStat>) {
|
||||
let stats = stat_result.expect("stat call failed");
|
||||
assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
|
||||
assert!(stats.st_mode > 0); // must be positive integer
|
||||
assert_eq!(stats.st_nlink, 1); // there links created, must be 1
|
||||
assert_eq!(stats.st_size, 0); // size is 0 because we did not write anything to the file
|
||||
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
// (Android's st_blocks is ulonglong which is always non-negative.)
|
||||
#[cfg_attr(target_os = "android", allow(unused_comparisons))]
|
||||
#[allow(clippy::absurd_extreme_comparisons)] // Not absurd on all OSes
|
||||
fn assert_lstat_results(stat_result: Result<FileStat>) {
|
||||
let stats = stat_result.expect("stat call failed");
|
||||
assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
|
||||
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
|
||||
assert!(stats.st_mode > 0); // must be positive integer
|
||||
|
||||
// st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
|
||||
// (u16 on Android), and that will be a compile error.
|
||||
// On other platforms they are the same (either both are u16 or u32).
|
||||
assert_eq!(
|
||||
(stats.st_mode as usize) & (S_IFMT as usize),
|
||||
S_IFLNK as usize
|
||||
); // should be a link
|
||||
assert_eq!(stats.st_nlink, 1); // there links created, must be 1
|
||||
assert!(stats.st_size > 0); // size is > 0 because it points to another file
|
||||
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
|
||||
|
||||
// st_blocks depends on whether the machine's file system uses fast
|
||||
// or slow symlinks, so just make sure it's not negative
|
||||
assert!(stats.st_blocks >= 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_stat_and_fstat() {
|
||||
use nix::sys::stat::fstat;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
let file = File::create(&filename).unwrap();
|
||||
|
||||
let stat_result = stat(&filename);
|
||||
assert_stat_results(stat_result);
|
||||
|
||||
let fstat_result = fstat(file.as_raw_fd());
|
||||
assert_stat_results(fstat_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_fstatat() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
File::create(&filename).unwrap();
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty());
|
||||
|
||||
let result =
|
||||
stat::fstatat(Some(dirfd.unwrap()), &filename, fcntl::AtFlags::empty());
|
||||
assert_stat_results(result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
|
||||
fn test_stat_fstat_lstat() {
|
||||
use nix::sys::stat::{fstat, lstat};
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("bar.txt");
|
||||
let linkname = tempdir.path().join("barlink");
|
||||
|
||||
File::create(&filename).unwrap();
|
||||
symlink("bar.txt", &linkname).unwrap();
|
||||
let link = File::open(&linkname).unwrap();
|
||||
|
||||
// should be the same result as calling stat,
|
||||
// since it's a regular file
|
||||
let stat_result = stat(&filename);
|
||||
assert_stat_results(stat_result);
|
||||
|
||||
let lstat_result = lstat(&linkname);
|
||||
assert_lstat_results(lstat_result);
|
||||
|
||||
let fstat_result = fstat(link.as_raw_fd());
|
||||
assert_stat_results(fstat_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fchmod() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = tempdir.path().join("foo.txt");
|
||||
let file = File::create(&filename).unwrap();
|
||||
|
||||
let mut mode1 = Mode::empty();
|
||||
mode1.insert(Mode::S_IRUSR);
|
||||
mode1.insert(Mode::S_IWUSR);
|
||||
fchmod(file.as_raw_fd(), mode1).unwrap();
|
||||
|
||||
let file_stat1 = stat(&filename).unwrap();
|
||||
assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
|
||||
|
||||
let mut mode2 = Mode::empty();
|
||||
mode2.insert(Mode::S_IROTH);
|
||||
fchmod(file.as_raw_fd(), mode2).unwrap();
|
||||
|
||||
let file_stat2 = stat(&filename).unwrap();
|
||||
assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_fchmodat() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
File::create(&fullpath).unwrap();
|
||||
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let mut mode1 = Mode::empty();
|
||||
mode1.insert(Mode::S_IRUSR);
|
||||
mode1.insert(Mode::S_IWUSR);
|
||||
fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink)
|
||||
.unwrap();
|
||||
|
||||
let file_stat1 = stat(&fullpath).unwrap();
|
||||
assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
|
||||
|
||||
chdir(tempdir.path()).unwrap();
|
||||
|
||||
let mut mode2 = Mode::empty();
|
||||
mode2.insert(Mode::S_IROTH);
|
||||
fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap();
|
||||
|
||||
let file_stat2 = stat(&fullpath).unwrap();
|
||||
assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
|
||||
}
|
||||
|
||||
/// Asserts that the atime and mtime in a file's metadata match expected values.
|
||||
///
|
||||
/// The atime and mtime are expressed with a resolution of seconds because some file systems
|
||||
/// (like macOS's HFS+) do not have higher granularity.
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn assert_times_eq(
|
||||
exp_atime_sec: u64,
|
||||
exp_mtime_sec: u64,
|
||||
attr: &fs::Metadata,
|
||||
) {
|
||||
assert_eq!(
|
||||
Duration::new(exp_atime_sec, 0),
|
||||
attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Duration::new(exp_mtime_sec, 0),
|
||||
attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimes() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550))
|
||||
.unwrap();
|
||||
assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
apple_targets,
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
fn test_lutimes() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target = tempdir.path().join("target");
|
||||
let fullpath = tempdir.path().join("symlink");
|
||||
drop(File::create(&target).unwrap());
|
||||
symlink(&target, &fullpath).unwrap();
|
||||
|
||||
let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
|
||||
lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230))
|
||||
.unwrap();
|
||||
assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
|
||||
|
||||
let target_metadata = fs::symlink_metadata(&target).unwrap();
|
||||
assert_eq!(
|
||||
exp_target_metadata.accessed().unwrap(),
|
||||
target_metadata.accessed().unwrap(),
|
||||
"atime of symlink target was unexpectedly modified"
|
||||
);
|
||||
assert_eq!(
|
||||
exp_target_metadata.modified().unwrap(),
|
||||
target_metadata.modified().unwrap(),
|
||||
"mtime of symlink target was unexpectedly modified"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_futimens() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
|
||||
assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimensat() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
utimensat(
|
||||
Some(dirfd),
|
||||
filename,
|
||||
&TimeSpec::seconds(12345),
|
||||
&TimeSpec::seconds(678),
|
||||
UtimensatFlags::FollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
|
||||
|
||||
chdir(tempdir.path()).unwrap();
|
||||
|
||||
utimensat(
|
||||
None,
|
||||
filename,
|
||||
&TimeSpec::seconds(500),
|
||||
&TimeSpec::seconds(800),
|
||||
UtimensatFlags::FollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_mkdirat_success_path() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "example_subdir";
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
|
||||
assert!(Path::exists(&tempdir.path().join(filename)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_mkdirat_success_mode() {
|
||||
let expected_bits =
|
||||
stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "example_subdir";
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
|
||||
let permissions = fs::metadata(tempdir.path().join(filename))
|
||||
.unwrap()
|
||||
.permissions();
|
||||
let mode = permissions.mode();
|
||||
assert_eq!(mode as mode_t, expected_bits)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_mkdirat_fail() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let not_dir_filename = "example_not_dir";
|
||||
let filename = "example_subdir_dir";
|
||||
let dirfd = fcntl::open(
|
||||
&tempdir.path().join(not_dir_filename),
|
||||
fcntl::OFlag::O_CREAT,
|
||||
stat::Mode::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
let result = mkdirat(Some(dirfd), filename, Mode::S_IRWXU).unwrap_err();
|
||||
assert_eq!(result, Errno::ENOTDIR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(
|
||||
freebsdlike,
|
||||
apple_targets,
|
||||
target_os = "haiku",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
fn test_mknod() {
|
||||
use stat::{lstat, mknod, SFlag};
|
||||
|
||||
let file_name = "test_file";
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target = tempdir.path().join(file_name);
|
||||
mknod(&target, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap();
|
||||
let mode = lstat(&target).unwrap().st_mode as mode_t;
|
||||
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
|
||||
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(
|
||||
solarish,
|
||||
freebsdlike,
|
||||
apple_targets,
|
||||
target_os = "haiku",
|
||||
target_os = "redox"
|
||||
)))]
|
||||
fn test_mknodat() {
|
||||
use fcntl::{AtFlags, OFlag};
|
||||
use nix::dir::Dir;
|
||||
use stat::{fstatat, mknodat, SFlag};
|
||||
|
||||
let file_name = "test_file";
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let target_dir =
|
||||
Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
|
||||
mknodat(
|
||||
Some(target_dir.as_raw_fd()),
|
||||
file_name,
|
||||
SFlag::S_IFREG,
|
||||
Mode::S_IRWXU,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let mode = fstatat(
|
||||
Some(target_dir.as_raw_fd()),
|
||||
file_name,
|
||||
AtFlags::AT_SYMLINK_NOFOLLOW,
|
||||
)
|
||||
.unwrap()
|
||||
.st_mode as mode_t;
|
||||
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
|
||||
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_futimens_unchanged() {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let fullpath = tempdir.path().join("file");
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let old_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let old_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
|
||||
futimens(fd, &TimeSpec::UTIME_OMIT, &TimeSpec::UTIME_OMIT).unwrap();
|
||||
|
||||
let new_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let new_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
assert_eq!(old_atime, new_atime);
|
||||
assert_eq!(old_mtime, new_mtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_utimensat_unchanged() {
|
||||
let _dr = crate::DirRestore::new();
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let filename = "foo.txt";
|
||||
let fullpath = tempdir.path().join(filename);
|
||||
drop(File::create(&fullpath).unwrap());
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
let old_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let old_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
utimensat(
|
||||
Some(dirfd),
|
||||
filename,
|
||||
&TimeSpec::UTIME_OMIT,
|
||||
&TimeSpec::UTIME_OMIT,
|
||||
UtimensatFlags::NoFollowSymlink,
|
||||
)
|
||||
.unwrap();
|
||||
let new_atime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.unwrap();
|
||||
let new_mtime = fs::metadata(fullpath.as_path())
|
||||
.unwrap()
|
||||
.modified()
|
||||
.unwrap();
|
||||
assert_eq!(old_atime, new_atime);
|
||||
assert_eq!(old_mtime, new_mtime);
|
||||
}
|
||||
38
third_party/rust/nix/test/test_syslog.rs
vendored
Normal file
38
third_party/rust/nix/test/test_syslog.rs
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity};
|
||||
|
||||
#[test]
|
||||
fn test_syslog_hello_world() {
|
||||
let flags = LogFlags::LOG_PID;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
openlog(None::<&str>, flags, Facility::LOG_USER).unwrap();
|
||||
#[cfg(target_os = "linux")]
|
||||
openlog(None, flags, Facility::LOG_USER).unwrap();
|
||||
|
||||
syslog(Severity::LOG_EMERG, "Hello, nix!").unwrap();
|
||||
let name = "syslog";
|
||||
syslog(Severity::LOG_NOTICE, &format!("Hello, {name}!")).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_openlog_with_ident() {
|
||||
use std::ffi::CStr;
|
||||
|
||||
const IDENT: &CStr = unsafe {
|
||||
CStr::from_bytes_with_nul_unchecked(b"test_openlog_with_ident\0")
|
||||
};
|
||||
|
||||
let flags = LogFlags::LOG_PID;
|
||||
openlog(Some(IDENT), flags, Facility::LOG_USER).unwrap();
|
||||
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn test_openlog_with_ident() {
|
||||
let flags = LogFlags::LOG_PID;
|
||||
openlog(Some("test_openlog_with_ident"), flags, Facility::LOG_USER)
|
||||
.unwrap();
|
||||
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap();
|
||||
}
|
||||
200
third_party/rust/nix/test/test_unistd.rs
vendored
200
third_party/rust/nix/test/test_unistd.rs
vendored
@@ -26,7 +26,6 @@ use std::ffi::CString;
|
||||
use std::fs::DirBuilder;
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::os::unix::prelude::*;
|
||||
#[cfg(not(any(
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
@@ -121,8 +120,7 @@ fn test_mkstemp() {
|
||||
|
||||
let result = mkstemp(&path);
|
||||
match result {
|
||||
Ok((fd, path)) => {
|
||||
close(fd).unwrap();
|
||||
Ok((_, path)) => {
|
||||
unlink(path.as_path()).unwrap();
|
||||
}
|
||||
Err(e) => panic!("mkstemp failed: {e}"),
|
||||
@@ -163,12 +161,14 @@ fn test_mkfifo_directory() {
|
||||
target_os = "haiku"
|
||||
)))]
|
||||
fn test_mkfifoat_none() {
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _m = crate::CWD_LOCK.read();
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo");
|
||||
|
||||
mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap();
|
||||
mkfifoat(AT_FDCWD, &mkfifoat_fifo, Mode::S_IRUSR).unwrap();
|
||||
|
||||
let stats = stat::stat(&mkfifoat_fifo).unwrap();
|
||||
let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
|
||||
@@ -189,11 +189,10 @@ fn test_mkfifoat() {
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let mkfifoat_name = "mkfifoat_name";
|
||||
|
||||
mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
|
||||
mkfifoat(&dirfd, mkfifoat_name, Mode::S_IRUSR).unwrap();
|
||||
|
||||
let stats =
|
||||
stat::fstatat(Some(dirfd), mkfifoat_name, fcntl::AtFlags::empty())
|
||||
.unwrap();
|
||||
stat::fstatat(&dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
|
||||
let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
|
||||
assert_eq!(typ, SFlag::S_IFIFO);
|
||||
}
|
||||
@@ -206,10 +205,12 @@ fn test_mkfifoat() {
|
||||
target_os = "haiku"
|
||||
)))]
|
||||
fn test_mkfifoat_directory_none() {
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _m = crate::CWD_LOCK.read();
|
||||
|
||||
// mkfifoat should fail if a directory is given
|
||||
mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR)
|
||||
mkfifoat(AT_FDCWD, &env::temp_dir(), Mode::S_IRUSR)
|
||||
.expect_err("assertion failed");
|
||||
}
|
||||
|
||||
@@ -225,9 +226,9 @@ fn test_mkfifoat_directory() {
|
||||
let tempdir = tempdir().unwrap();
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let mkfifoat_dir = "mkfifoat_dir";
|
||||
stat::mkdirat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).unwrap();
|
||||
stat::mkdirat(&dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
|
||||
|
||||
mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR)
|
||||
mkfifoat(&dirfd, mkfifoat_dir, Mode::S_IRUSR)
|
||||
.expect_err("assertion failed");
|
||||
}
|
||||
|
||||
@@ -385,7 +386,7 @@ macro_rules! execve_test_factory (
|
||||
match unsafe{fork()}.unwrap() {
|
||||
Child => {
|
||||
// Make `writer` be the stdout of the new process.
|
||||
dup2(writer.as_raw_fd(), 1).unwrap();
|
||||
nix::unistd::dup2_stdout(&writer).unwrap();
|
||||
let r = syscall();
|
||||
let _ = std::io::stderr()
|
||||
.write_all(format!("{:?}", r).as_bytes());
|
||||
@@ -399,7 +400,7 @@ macro_rules! execve_test_factory (
|
||||
assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
|
||||
// Read 1024 bytes.
|
||||
let mut buf = [0u8; 1024];
|
||||
read(reader.as_raw_fd(), &mut buf).unwrap();
|
||||
read(&reader, &mut buf).unwrap();
|
||||
// It should contain the things we printed using `/bin/sh`.
|
||||
let string = String::from_utf8_lossy(&buf);
|
||||
assert!(string.contains("nix!!!"));
|
||||
@@ -432,12 +433,12 @@ macro_rules! execve_test_factory (
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "android")] {
|
||||
execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str());
|
||||
execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
|
||||
execve_test_factory!(test_fexecve, fexecve, &File::open("/system/bin/sh").unwrap());
|
||||
} else if #[cfg(any(freebsdlike, target_os = "linux", target_os = "hurd"))] {
|
||||
// These tests frequently fail on musl, probably due to
|
||||
// https://github.com/nix-rust/nix/issues/555
|
||||
execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
|
||||
execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
|
||||
execve_test_factory!(test_fexecve, fexecve, &File::open("/bin/sh").unwrap());
|
||||
} else if #[cfg(any(solarish, apple_targets, netbsdlike))] {
|
||||
execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
|
||||
// No fexecve() on ios, macos, NetBSD, OpenBSD.
|
||||
@@ -456,21 +457,21 @@ cfg_if! {
|
||||
if #[cfg(target_os = "android")] {
|
||||
use nix::fcntl::AtFlags;
|
||||
execve_test_factory!(test_execveat_empty, execveat,
|
||||
Some(File::open("/system/bin/sh").unwrap().into_raw_fd()),
|
||||
&File::open("/system/bin/sh").unwrap(),
|
||||
"", AtFlags::AT_EMPTY_PATH);
|
||||
execve_test_factory!(test_execveat_relative, execveat,
|
||||
Some(File::open("/system/bin/").unwrap().into_raw_fd()),
|
||||
&File::open("/system/bin/").unwrap(),
|
||||
"./sh", AtFlags::empty());
|
||||
execve_test_factory!(test_execveat_absolute, execveat,
|
||||
Some(File::open("/").unwrap().into_raw_fd()),
|
||||
&File::open("/").unwrap(),
|
||||
"/system/bin/sh", AtFlags::empty());
|
||||
} else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
|
||||
use nix::fcntl::AtFlags;
|
||||
execve_test_factory!(test_execveat_empty, execveat, Some(File::open("/bin/sh").unwrap().into_raw_fd()),
|
||||
execve_test_factory!(test_execveat_empty, execveat, &File::open("/bin/sh").unwrap(),
|
||||
"", AtFlags::AT_EMPTY_PATH);
|
||||
execve_test_factory!(test_execveat_relative, execveat, Some(File::open("/bin/").unwrap().into_raw_fd()),
|
||||
execve_test_factory!(test_execveat_relative, execveat, &File::open("/bin/").unwrap(),
|
||||
"./sh", AtFlags::empty());
|
||||
execve_test_factory!(test_execveat_absolute, execveat, Some(File::open("/").unwrap().into_raw_fd()),
|
||||
execve_test_factory!(test_execveat_absolute, execveat, &File::open("/").unwrap(),
|
||||
"/bin/sh", AtFlags::empty());
|
||||
}
|
||||
}
|
||||
@@ -483,12 +484,10 @@ fn test_fchdir() {
|
||||
|
||||
let tmpdir = tempdir().unwrap();
|
||||
let tmpdir_path = tmpdir.path().canonicalize().unwrap();
|
||||
let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
|
||||
let tmpdir_fd = File::open(&tmpdir_path).unwrap();
|
||||
|
||||
fchdir(tmpdir_fd).expect("assertion failed");
|
||||
fchdir(&tmpdir_fd).expect("assertion failed");
|
||||
assert_eq!(getcwd().unwrap(), tmpdir_path);
|
||||
|
||||
close(tmpdir_fd).expect("assertion failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -542,19 +541,18 @@ fn test_fchown() {
|
||||
let uid = Some(getuid());
|
||||
let gid = Some(getgid());
|
||||
|
||||
let path = tempfile().unwrap();
|
||||
let fd = path.as_raw_fd();
|
||||
let file = tempfile().unwrap();
|
||||
|
||||
fchown(fd, uid, gid).unwrap();
|
||||
fchown(fd, uid, None).unwrap();
|
||||
fchown(fd, None, gid).unwrap();
|
||||
fchown(999999999, uid, gid).unwrap_err();
|
||||
fchown(&file, uid, gid).unwrap();
|
||||
fchown(&file, uid, None).unwrap();
|
||||
fchown(&file, None, gid).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_fchownat() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _dr = crate::DirRestore::new();
|
||||
// Testing for anything other than our own UID/GID is hard.
|
||||
@@ -569,13 +567,13 @@ fn test_fchownat() {
|
||||
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
|
||||
fchownat(Some(dirfd), "file", uid, gid, AtFlags::empty()).unwrap();
|
||||
fchownat(&dirfd, "file", uid, gid, AtFlags::empty()).unwrap();
|
||||
|
||||
chdir(tempdir.path()).unwrap();
|
||||
fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap();
|
||||
fchownat(AT_FDCWD, "file", uid, gid, AtFlags::empty()).unwrap();
|
||||
|
||||
fs::remove_file(&path).unwrap();
|
||||
fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap_err();
|
||||
fchownat(AT_FDCWD, "file", uid, gid, AtFlags::empty()).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -585,7 +583,7 @@ fn test_lseek() {
|
||||
tmp.write_all(CONTENTS).unwrap();
|
||||
|
||||
let offset: off_t = 5;
|
||||
lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();
|
||||
lseek(&tmp, offset, Whence::SeekSet).unwrap();
|
||||
|
||||
let mut buf = [0u8; 7];
|
||||
crate::read_exact(&tmp, &mut buf);
|
||||
@@ -599,7 +597,7 @@ fn test_lseek64() {
|
||||
let mut tmp = tempfile().unwrap();
|
||||
tmp.write_all(CONTENTS).unwrap();
|
||||
|
||||
lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();
|
||||
lseek64(&tmp, 5, Whence::SeekSet).unwrap();
|
||||
|
||||
let mut buf = [0u8; 7];
|
||||
crate::read_exact(&tmp, &mut buf);
|
||||
@@ -633,7 +631,8 @@ cfg_if! {
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "cygwin"
|
||||
)))]
|
||||
fn test_acct() {
|
||||
use std::process::Command;
|
||||
@@ -733,12 +732,12 @@ fn test_getresgid() {
|
||||
fn test_pipe() {
|
||||
let (fd0, fd1) = pipe().unwrap();
|
||||
let m0 = stat::SFlag::from_bits_truncate(
|
||||
stat::fstat(fd0.as_raw_fd()).unwrap().st_mode as mode_t,
|
||||
stat::fstat(&fd0).unwrap().st_mode as mode_t,
|
||||
);
|
||||
// S_IFIFO means it's a pipe
|
||||
assert_eq!(m0, SFlag::S_IFIFO);
|
||||
let m1 = stat::SFlag::from_bits_truncate(
|
||||
stat::fstat(fd1.as_raw_fd()).unwrap().st_mode as mode_t,
|
||||
stat::fstat(&fd1).unwrap().st_mode as mode_t,
|
||||
);
|
||||
assert_eq!(m1, SFlag::S_IFIFO);
|
||||
}
|
||||
@@ -758,13 +757,11 @@ fn test_pipe2() {
|
||||
use nix::fcntl::{fcntl, FcntlArg, FdFlag};
|
||||
|
||||
let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
|
||||
let f0 = FdFlag::from_bits_truncate(
|
||||
fcntl(fd0.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
|
||||
);
|
||||
let f0 =
|
||||
FdFlag::from_bits_truncate(fcntl(&fd0, FcntlArg::F_GETFD).unwrap());
|
||||
assert!(f0.contains(FdFlag::FD_CLOEXEC));
|
||||
let f1 = FdFlag::from_bits_truncate(
|
||||
fcntl(fd1.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
|
||||
);
|
||||
let f1 =
|
||||
FdFlag::from_bits_truncate(fcntl(&fd1, FcntlArg::F_GETFD).unwrap());
|
||||
assert!(f1.contains(FdFlag::FD_CLOEXEC));
|
||||
}
|
||||
|
||||
@@ -872,13 +869,15 @@ fn test_canceling_alarm() {
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_symlinkat() {
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _m = crate::CWD_LOCK.read();
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
|
||||
let target = tempdir.path().join("a");
|
||||
let linkpath = tempdir.path().join("b");
|
||||
symlinkat(&target, None, &linkpath).unwrap();
|
||||
symlinkat(&target, AT_FDCWD, &linkpath).unwrap();
|
||||
assert_eq!(
|
||||
readlink(&linkpath).unwrap().to_str().unwrap(),
|
||||
target.to_str().unwrap()
|
||||
@@ -887,7 +886,7 @@ fn test_symlinkat() {
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let target = "c";
|
||||
let linkpath = "d";
|
||||
symlinkat(target, Some(dirfd), linkpath).unwrap();
|
||||
symlinkat(target, &dirfd, linkpath).unwrap();
|
||||
assert_eq!(
|
||||
readlink(&tempdir.path().join(linkpath))
|
||||
.unwrap()
|
||||
@@ -919,9 +918,43 @@ fn test_linkat_file() {
|
||||
|
||||
// Attempt hard link file at relative path
|
||||
linkat(
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
oldfilename,
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
newfilename,
|
||||
AtFlags::AT_SYMLINK_FOLLOW,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(newfilepath.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
/// This test is the same as [test_linkat_file], but ensures that two different types can be used
|
||||
/// as the path arguments.
|
||||
fn test_linkat_pathtypes() {
|
||||
use nix::fcntl::AtFlags;
|
||||
|
||||
let tempdir = tempdir().unwrap();
|
||||
let oldfilename = "foo.txt";
|
||||
let oldfilepath = tempdir.path().join(oldfilename);
|
||||
|
||||
let newfilename = "bar.txt";
|
||||
let newfilepath = tempdir.path().join(newfilename);
|
||||
|
||||
// Create file
|
||||
File::create(oldfilepath).unwrap();
|
||||
|
||||
// Get file descriptor for base directory
|
||||
let dirfd =
|
||||
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
|
||||
.unwrap();
|
||||
|
||||
// Attempt hard link file at relative path
|
||||
linkat(
|
||||
&dirfd,
|
||||
PathBuf::from(oldfilename).as_path(),
|
||||
&dirfd,
|
||||
newfilename,
|
||||
AtFlags::AT_SYMLINK_FOLLOW,
|
||||
)
|
||||
@@ -933,6 +966,7 @@ fn test_linkat_file() {
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_linkat_olddirfd_none() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _dr = crate::DirRestore::new();
|
||||
|
||||
@@ -958,9 +992,9 @@ fn test_linkat_olddirfd_none() {
|
||||
// Attempt hard link file using curent working directory as relative path for old file path
|
||||
chdir(tempdir_oldfile.path()).unwrap();
|
||||
linkat(
|
||||
None,
|
||||
AT_FDCWD,
|
||||
oldfilename,
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
newfilename,
|
||||
AtFlags::AT_SYMLINK_FOLLOW,
|
||||
)
|
||||
@@ -972,6 +1006,7 @@ fn test_linkat_olddirfd_none() {
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_linkat_newdirfd_none() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _dr = crate::DirRestore::new();
|
||||
|
||||
@@ -997,9 +1032,9 @@ fn test_linkat_newdirfd_none() {
|
||||
// Attempt hard link file using current working directory as relative path for new file path
|
||||
chdir(tempdir_newfile.path()).unwrap();
|
||||
linkat(
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
oldfilename,
|
||||
None,
|
||||
AT_FDCWD,
|
||||
newfilename,
|
||||
AtFlags::AT_SYMLINK_FOLLOW,
|
||||
)
|
||||
@@ -1011,6 +1046,7 @@ fn test_linkat_newdirfd_none() {
|
||||
#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
|
||||
fn test_linkat_no_follow_symlink() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _m = crate::CWD_LOCK.read();
|
||||
|
||||
@@ -1028,7 +1064,7 @@ fn test_linkat_no_follow_symlink() {
|
||||
File::create(&oldfilepath).unwrap();
|
||||
|
||||
// Create symlink to file
|
||||
symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
|
||||
symlinkat(&oldfilepath, AT_FDCWD, &symoldfilepath).unwrap();
|
||||
|
||||
// Get file descriptor for base directory
|
||||
let dirfd =
|
||||
@@ -1037,9 +1073,9 @@ fn test_linkat_no_follow_symlink() {
|
||||
|
||||
// Attempt link symlink of file at relative path
|
||||
linkat(
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
symoldfilename,
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
newfilename,
|
||||
AtFlags::empty(),
|
||||
)
|
||||
@@ -1056,6 +1092,7 @@ fn test_linkat_no_follow_symlink() {
|
||||
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
|
||||
fn test_linkat_follow_symlink() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let _m = crate::CWD_LOCK.read();
|
||||
|
||||
@@ -1073,7 +1110,7 @@ fn test_linkat_follow_symlink() {
|
||||
File::create(&oldfilepath).unwrap();
|
||||
|
||||
// Create symlink to file
|
||||
symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
|
||||
symlinkat(&oldfilepath, AT_FDCWD, &symoldfilepath).unwrap();
|
||||
|
||||
// Get file descriptor for base directory
|
||||
let dirfd =
|
||||
@@ -1082,9 +1119,9 @@ fn test_linkat_follow_symlink() {
|
||||
|
||||
// Attempt link target of symlink of file at relative path
|
||||
linkat(
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
symoldfilename,
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
newfilename,
|
||||
AtFlags::AT_SYMLINK_FOLLOW,
|
||||
)
|
||||
@@ -1120,7 +1157,7 @@ fn test_unlinkat_dir_noremovedir() {
|
||||
|
||||
// Attempt unlink dir at relative path without proper flag
|
||||
let err_result =
|
||||
unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
|
||||
unlinkat(&dirfd, dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
|
||||
assert!(err_result == Errno::EISDIR || err_result == Errno::EPERM);
|
||||
}
|
||||
|
||||
@@ -1140,7 +1177,7 @@ fn test_unlinkat_dir_removedir() {
|
||||
.unwrap();
|
||||
|
||||
// Attempt unlink dir at relative path with proper flag
|
||||
unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap();
|
||||
unlinkat(&dirfd, dirname, UnlinkatFlags::RemoveDir).unwrap();
|
||||
assert!(!dirpath.exists());
|
||||
}
|
||||
|
||||
@@ -1160,7 +1197,7 @@ fn test_unlinkat_file() {
|
||||
.unwrap();
|
||||
|
||||
// Attempt unlink file at relative path
|
||||
unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap();
|
||||
unlinkat(&dirfd, filename, UnlinkatFlags::NoRemoveDir).unwrap();
|
||||
assert!(!filepath.exists());
|
||||
}
|
||||
|
||||
@@ -1186,12 +1223,16 @@ fn test_access_file_exists() {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[test]
|
||||
fn test_user_into_passwd() {
|
||||
// get the UID of the "nobody" user
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
let test_username = "nobody";
|
||||
// "nobody" unavailable on haiku
|
||||
#[cfg(target_os = "haiku")]
|
||||
let test_username = "user";
|
||||
let test_username = if cfg!(target_os = "haiku") {
|
||||
// "nobody" unavailable on haiku
|
||||
"user"
|
||||
} else if cfg!(target_os = "cygwin") {
|
||||
// the Windows admin user
|
||||
"Administrator"
|
||||
} else {
|
||||
// get the UID of the "nobody" user
|
||||
"nobody"
|
||||
};
|
||||
|
||||
let nobody = User::from_name(test_username).unwrap().unwrap();
|
||||
let pwd: libc::passwd = nobody.into();
|
||||
@@ -1243,6 +1284,8 @@ fn test_setfsuid() {
|
||||
target_os = "haiku"
|
||||
)))]
|
||||
fn test_ttyname() {
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
|
||||
assert!(fd.as_raw_fd() > 0);
|
||||
|
||||
@@ -1291,10 +1334,12 @@ fn test_getpeereid() {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_faccessat_none_not_existing() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let dir = tempdir.path().join("does_not_exist.txt");
|
||||
assert_eq!(
|
||||
faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty())
|
||||
faccessat(AT_FDCWD, &dir, AccessFlags::F_OK, AtFlags::empty())
|
||||
.err()
|
||||
.unwrap(),
|
||||
Errno::ENOENT
|
||||
@@ -1305,18 +1350,14 @@ fn test_faccessat_none_not_existing() {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_faccessat_not_existing() {
|
||||
use nix::fcntl::AtFlags;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let not_exist_file = "does_not_exist.txt";
|
||||
assert_eq!(
|
||||
faccessat(
|
||||
Some(dirfd),
|
||||
not_exist_file,
|
||||
AccessFlags::F_OK,
|
||||
AtFlags::empty(),
|
||||
)
|
||||
.err()
|
||||
.unwrap(),
|
||||
faccessat(&dirfd, not_exist_file, AccessFlags::F_OK, AtFlags::empty(),)
|
||||
.err()
|
||||
.unwrap(),
|
||||
Errno::ENOENT
|
||||
);
|
||||
}
|
||||
@@ -1325,11 +1366,13 @@ fn test_faccessat_not_existing() {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_faccessat_none_file_exists() {
|
||||
use nix::fcntl::AtFlags;
|
||||
use nix::fcntl::AT_FDCWD;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let path = tempdir.path().join("does_exist.txt");
|
||||
let _file = File::create(path.clone()).unwrap();
|
||||
assert!(faccessat(
|
||||
None,
|
||||
AT_FDCWD,
|
||||
&path,
|
||||
AccessFlags::R_OK | AccessFlags::W_OK,
|
||||
AtFlags::empty(),
|
||||
@@ -1341,13 +1384,14 @@ fn test_faccessat_none_file_exists() {
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
fn test_faccessat_file_exists() {
|
||||
use nix::fcntl::AtFlags;
|
||||
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
|
||||
let exist_file = "does_exist.txt";
|
||||
let path = tempdir.path().join(exist_file);
|
||||
let _file = File::create(path.clone()).unwrap();
|
||||
assert!(faccessat(
|
||||
Some(dirfd),
|
||||
&dirfd,
|
||||
&path,
|
||||
AccessFlags::R_OK | AccessFlags::W_OK,
|
||||
AtFlags::empty(),
|
||||
|
||||
@@ -12,7 +12,7 @@ num-derive = "0.4"
|
||||
num-traits = "0.2"
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\", target_os = \"macos\"))".dependencies]
|
||||
nix = { version = "0.29", features = ["process"] }
|
||||
nix = { version = "0.30", features = ["process"] }
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies]
|
||||
minidump-writer = "0.10"
|
||||
|
||||
@@ -11,7 +11,7 @@ num-traits = "0.2"
|
||||
thiserror = "2"
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\", target_os = \"macos\"))".dependencies]
|
||||
nix = { version = "0.29", features = ["fs", "poll", "socket", "uio"] }
|
||||
nix = { version = "0.30", features = ["fs", "poll", "socket", "uio"] }
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies]
|
||||
minidump-writer = "0.10"
|
||||
|
||||
@@ -28,7 +28,7 @@ env_logger = { version = "0.10", default-features = false }
|
||||
android_logger = "0.12"
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies]
|
||||
nix = { version = "0.29", features = ["poll", "socket", "uio"] }
|
||||
nix = { version = "0.30", features = ["poll", "socket", "uio"] }
|
||||
minidump-writer = { version = "0.10" }
|
||||
rust_minidump_writer_linux = { path = "../rust_minidump_writer_linux" }
|
||||
|
||||
@@ -43,7 +43,7 @@ windows-sys = { version = "0.52", features = [
|
||||
] }
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies]
|
||||
nix = { version = "0.29", features = ["fs", "poll", "socket", "uio"] }
|
||||
nix = { version = "0.30", features = ["fs", "poll", "socket", "uio"] }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1"
|
||||
|
||||
Reference in New Issue
Block a user