aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Vander Stoep <jeffv@google.com>2023-01-17 18:17:47 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-01-17 18:17:47 +0000
commit7c087f1848f54cd2d6f34318d1e6bf479d8cf8a3 (patch)
treea8592552e0ad623519128851864362b1b67bfd7c
parent4ede6a59c9cca46d5443f791c98679ef8546da36 (diff)
parentf62f670293e33956eb7343a3ff1104d2abf05a7f (diff)
downloadnix-main-16k-with-phones.tar.gz
Merge "Upgrade nix to 0.26.1"main-16k-with-phones
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp3
-rw-r--r--CHANGELOG.md194
-rw-r--r--Cargo.toml16
-rw-r--r--Cargo.toml.orig14
-rw-r--r--METADATA12
-rw-r--r--README.md2
-rw-r--r--src/dir.rs65
-rw-r--r--src/errno.rs157
-rw-r--r--src/fcntl.rs4
-rw-r--r--src/features.rs40
-rw-r--r--src/ifaddrs.rs72
-rw-r--r--src/kmod.rs10
-rw-r--r--src/lib.rs1
-rw-r--r--src/mount/bsd.rs98
-rw-r--r--src/mount/linux.rs57
-rw-r--r--src/mount/mod.rs25
-rw-r--r--src/mqueue.rs110
-rw-r--r--src/net/if_.rs3
-rw-r--r--src/poll.rs30
-rw-r--r--src/pty.rs60
-rw-r--r--src/sched.rs50
-rw-r--r--src/sys/aio.rs23
-rw-r--r--src/sys/epoll.rs36
-rw-r--r--src/sys/event.rs162
-rw-r--r--src/sys/eventfd.rs4
-rw-r--r--src/sys/inotify.rs53
-rw-r--r--src/sys/memfd.rs21
-rw-r--r--src/sys/mman.rs74
-rw-r--r--src/sys/mod.rs2
-rw-r--r--src/sys/personality.rs10
-rw-r--r--src/sys/pthread.rs1
-rw-r--r--src/sys/ptrace/bsd.rs46
-rw-r--r--src/sys/ptrace/linux.rs180
-rw-r--r--src/sys/ptrace/mod.rs27
-rw-r--r--src/sys/quota.rs115
-rw-r--r--src/sys/reboot.rs10
-rw-r--r--src/sys/resource.rs14
-rw-r--r--src/sys/select.rs73
-rw-r--r--src/sys/sendfile.rs2
-rw-r--r--src/sys/signal.rs17
-rw-r--r--src/sys/signalfd.rs24
-rw-r--r--src/sys/socket/addr.rs1484
-rw-r--r--src/sys/socket/mod.rs855
-rw-r--r--src/sys/socket/sockopt.rs627
-rw-r--r--src/sys/stat.rs150
-rw-r--r--src/sys/statfs.rs387
-rw-r--r--src/sys/statvfs.rs9
-rw-r--r--src/sys/sysinfo.rs4
-rw-r--r--src/sys/termios.rs203
-rw-r--r--src/sys/time.rs78
-rw-r--r--src/sys/timer.rs22
-rw-r--r--src/sys/timerfd.rs25
-rw-r--r--src/sys/uio.rs95
-rw-r--r--src/sys/utsname.rs22
-rw-r--r--src/sys/wait.rs13
-rw-r--r--src/time.rs42
-rw-r--r--src/ucontext.rs16
-rw-r--r--src/unistd.rs61
-rw-r--r--test/sys/test_aio.rs10
-rw-r--r--test/sys/test_ioctl.rs8
-rw-r--r--test/sys/test_mman.rs19
-rw-r--r--test/sys/test_socket.rs181
-rw-r--r--test/sys/test_sockopt.rs102
-rw-r--r--test/sys/test_stat.rs2
-rw-r--r--test/sys/test_timerfd.rs2
-rw-r--r--test/test.rs1
-rw-r--r--test/test_dir.rs2
-rw-r--r--test/test_fcntl.rs14
-rw-r--r--test/test_kmod/mod.rs4
-rw-r--r--test/test_mount.rs4
-rw-r--r--test/test_sched.rs6
-rw-r--r--test/test_unistd.rs45
73 files changed, 4239 insertions, 2173 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index c99e6c8..1448400 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "4d4754a14b080b32b1af16de54dfb822b28b5f06"
+ "sha1": "e7a646ddff63b912b3a5afab6464465d800de350"
},
"path_in_vcs": ""
} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index b690c44..091550b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,7 +26,7 @@ rust_library {
host_supported: true,
crate_name: "nix",
cargo_env_compat: true,
- cargo_pkg_version: "0.25.0",
+ cargo_pkg_version: "0.26.1",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -72,6 +72,7 @@ rust_library {
"liblibc",
"libmemoffset",
"libpin_utils",
+ "libstatic_assertions",
],
apex_available: [
"//apex_available:platform",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f06e412..a332bc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,84 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
+## [0.26.1] - 2022-11-29
+### Added
+### Changed
+### Fixed
+- Fix UB with `sys::socket::sockopt::SockType` using `SOCK_PACKET`.
+ ([#1821](https://github.com/nix-rust/nix/pull/1821))
+
+### Removed
+
+## [0.26.0] - 2022-11-29
+### Added
+
+- Added `SockaddrStorage::{as_unix_addr, as_unix_addr_mut}`
+ ([#1871](https://github.com/nix-rust/nix/pull/1871))
+- Added `MntFlags` and `unmount` on all of the BSDs.
+- Added `any()` and `all()` to `poll::PollFd`.
+ ([#1877](https://github.com/nix-rust/nix/pull/1877))
+- Add `MntFlags` and `unmount` on all of the BSDs.
+ ([#1849](https://github.com/nix-rust/nix/pull/1849))
+- Added a `Statfs::flags` method.
+ ([#1849](https://github.com/nix-rust/nix/pull/1849))
+- Added `NSFS_MAGIC` FsType on Linux and Android.
+ ([#1829](https://github.com/nix-rust/nix/pull/1829))
+- Added `sched_getcpu` on platforms that support it.
+ ([#1825](https://github.com/nix-rust/nix/pull/1825))
+- Added `sched_getaffinity` and `sched_setaffinity` on FreeBSD.
+ ([#1804](https://github.com/nix-rust/nix/pull/1804))
+- Added `line_discipline` field to `Termios` on Linux, Android and Haiku
+ ([#1805](https://github.com/nix-rust/nix/pull/1805))
+- Expose the memfd module on FreeBSD (memfd was added in FreeBSD 13)
+ ([#1808](https://github.com/nix-rust/nix/pull/1808))
+- Added `domainname` field of `UtsName` on Android and Linux
+ ([#1817](https://github.com/nix-rust/nix/pull/1817))
+- Re-export `RLIM_INFINITY` from `libc`
+ ([#1831](https://github.com/nix-rust/nix/pull/1831))
+- Added `syncfs(2)` on Linux
+ ([#1833](https://github.com/nix-rust/nix/pull/1833))
+- Added `faccessat(2)` on illumos
+ ([#1841](https://github.com/nix-rust/nix/pull/1841))
+- Added `eaccess()` on FreeBSD, DragonFly and Linux (glibc and musl).
+ ([#1842](https://github.com/nix-rust/nix/pull/1842))
+- Added `IP_TOS` `SO_PRIORITY` and `IPV6_TCLASS` sockopts for Linux
+ ([#1853](https://github.com/nix-rust/nix/pull/1853))
+- Added `new_unnamed` and `is_unnamed` for `UnixAddr` on Linux and Android.
+ ([#1857](https://github.com/nix-rust/nix/pull/1857))
+- Added `SockProtocol::Raw` for raw sockets
+ ([#1848](https://github.com/nix-rust/nix/pull/1848))
+- added `IP_MTU` (`IpMtu`) `IPPROTO_IP` sockopt on Linux and Android.
+ ([#1865](https://github.com/nix-rust/nix/pull/1865))
+
+### Changed
+
+- The MSRV is now 1.56.1
+ ([#1792](https://github.com/nix-rust/nix/pull/1792))
+- The `addr` argument of `sys::mman::mmap` is now of type `Option<NonZeroUsize>`.
+ ([#1870](https://github.com/nix-rust/nix/pull/1870))
+- The `length` argument of `sys::mman::mmap` is now of type `NonZeroUsize`.
+ ([#1873](https://github.com/nix-rust/nix/pull/1873))
+
+### Fixed
+
+- Fixed using `SockaddrStorage` to store a Unix-domain socket address on Linux.
+ ([#1871](https://github.com/nix-rust/nix/pull/1871))
+- Fix microsecond calculation for `TimeSpec`.
+ ([#1801](https://github.com/nix-rust/nix/pull/1801))
+- Fix `User::from_name` and `Group::from_name` panicking
+ when given a name containing a nul.
+ ([#1815](https://github.com/nix-rust/nix/pull/1815))
+- Fix `User::from_uid` and `User::from_name` crash on Android platform.
+ ([#1824](https://github.com/nix-rust/nix/pull/1824))
+- Workaround XNU bug causing netmasks returned by `getifaddrs` to misbehave.
+ ([#1788](https://github.com/nix-rust/nix/pull/1788))
+
+### Removed
+
+- Removed deprecated error constants and conversions.
+ ([#1860](https://github.com/nix-rust/nix/pull/1860))
+
## [0.25.0] - 2022-08-13
### Added
@@ -44,6 +122,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).
### Changed
+- Reimplemented sendmmsg/recvmmsg to avoid allocations and with better API
+ (#[1744](https://github.com/nix-rust/nix/pull/1744))
+
- Rewrote the aio module. The new module:
* Does more type checking at compile time rather than runtime.
* Gives the caller control over whether and when to `Box` an aio operation.
@@ -313,6 +394,30 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Removed `SigevNotify` on OpenBSD and Redox.
(#[1511](https://github.com/nix-rust/nix/pull/1511))
+## [0.22.3] - 22 January 2022
+### Changed
+- Relaxed the bitflags requirement from 1.3.1 to 1.1. This partially reverts
+ #1492. From now on, the MSRV is not guaranteed to work with all versions of
+ all dependencies, just with some version of all dependencies.
+ (#[1607](https://github.com/nix-rust/nix/pull/1607))
+
+## [0.22.2] - 28 September 2021
+### Fixed
+- Fixed buffer overflow in `unistd::getgrouplist`.
+ (#[1545](https://github.com/nix-rust/nix/pull/1545))
+- Added more errno definitions for better backwards compatibility with
+ Nix 0.21.0.
+ (#[1467](https://github.com/nix-rust/nix/pull/1467))
+
+## [0.22.1] - 13 August 2021
+### Fixed
+- Locked bitflags to < 1.3.0 to fix the build with rust < 1.46.0.
+
+### Removed
+- Removed a couple of termios constants on redox that were never actually
+ supported.
+ (#[1483](https://github.com/nix-rust/nix/pull/1483))
+
## [0.22.0] - 9 July 2021
### Added
- Added `if_nameindex` (#[1445](https://github.com/nix-rust/nix/pull/1445))
@@ -338,8 +443,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
`nix::Error::EINVAL`.
([#1446](https://github.com/nix-rust/nix/pull/1446))
+## [0.21.2] - 29 September 2021
+### Fixed
+- Fixed buffer overflow in `unistd::getgrouplist`.
+ (#[1545](https://github.com/nix-rust/nix/pull/1545))
+
+## [0.21.1] - 13 August 2021
### Fixed
+- Locked bitflags to < 1.3.0 to fix the build with rust < 1.46.0.
+
### Removed
+- Removed a couple of termios constants on redox that were never actually
+ supported.
+ (#[1483](https://github.com/nix-rust/nix/pull/1483))
## [0.21.0] - 31 May 2021
### Added
@@ -395,6 +511,20 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Removed some Errno values from platforms where they aren't actually defined.
(#[1452](https://github.com/nix-rust/nix/pull/1452))
+## [0.20.2] - 28 September 2021
+### Fixed
+- Fixed buffer overflow in `unistd::getgrouplist`.
+ (#[1545](https://github.com/nix-rust/nix/pull/1545))
+
+## [0.20.1] - 13 August 2021
+### Fixed
+- Locked bitflags to < 1.3.0 to fix the build with rust < 1.46.0.
+
+### Removed
+- Removed a couple of termios constants on redox that were never actually
+ supported.
+ (#[1483](https://github.com/nix-rust/nix/pull/1483))
+
## [0.20.0] - 20 February 2021
### Added
@@ -458,8 +588,6 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1278](https://github.com/nix-rust/nix/pull/1278))
- Made `unistd::fork` an unsafe funtion, bringing it in line with [libstd's decision](https://github.com/rust-lang/rust/pull/58059).
(#[1293](https://github.com/nix-rust/nix/pull/1293))
-### Fixed
-### Removed
## [0.18.0] - 26 July 2020
### Added
@@ -572,22 +700,16 @@ This project adheres to [Semantic Versioning](https://semver.org/).
### Added
- Add `CLK_TCK` to `SysconfVar`
(#[1177](https://github.com/nix-rust/nix/pull/1177))
-### Changed
-### Fixed
### Removed
- Removed deprecated Error::description from error types
(#[1175](https://github.com/nix-rust/nix/pull/1175))
## [0.16.1] - 23 December 2019
-### Added
-### Changed
### Fixed
- Fixed the build for OpenBSD
(#[1168](https://github.com/nix-rust/nix/pull/1168))
-### Removed
-
## [0.16.0] - 1 December 2019
### Added
- Added `ptrace::seize()`: similar to `attach()` on Linux
@@ -715,8 +837,6 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Enabled `sched_yield` for all nix hosts.
([#1090](https://github.com/nix-rust/nix/pull/1090))
-### Removed
-
## [0.14.1] - 2019-06-06
### Added
- Macros exported by `nix` may now be imported via `use` on the Rust 2018
@@ -741,8 +861,6 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fix the build on Android and Linux/mips with recent versions of libc.
([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
-### Removed
-
## [0.14.0] - 2019-05-21
### Added
- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd.
@@ -811,6 +929,23 @@ This project adheres to [Semantic Versioning](https://semver.org/).
should've been defined in the first place.
([#1055](https://github.com/nix-rust/nix/pull/1055))
+## [0.13.1] - 2019-06-10
+### Changed
+- Changed some public types from reexports of libc types like `uint32_t` to the
+ native equivalents like `u32.`
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+
+### Fixed
+- Fix the build on Android and Linux/mips with recent versions of libc.
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+- Fixed build on Linux/arm and Linux/s390x with the latest Rust libc
+ ([52102cb](https://github.com/nix-rust/nix/commit/52102cb76398c4dfb9ea141b98c5b01a2e050973))
+
+### Removed
+- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
+ and iOS.
+ ([#1033](https://github.com/nix-rust/nix/pull/1033))
+
## [0.13.0] - 2019-01-15
### Added
- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS.
@@ -828,14 +963,30 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Added an `mprotect` wrapper.
([#991](https://github.com/nix-rust/nix/pull/991))
-### Changed
### Fixed
- `lutimes` never worked on OpenBSD as it is not implemented on OpenBSD. It has
been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
+## [0.12.1] 2019-06-08
+### Changed
+- Changed some public types from reexports of libc types like `uint32_t` to the
+ native equivalents like `u32.`
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+
+### Fixed
+- Fix the build on Android and Linux/mips with recent versions of libc.
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+- Fixed build on Linux/arm and Linux/s390x with the latest Rust libc
+ ([52102cb](https://github.com/nix-rust/nix/commit/52102cb76398c4dfb9ea141b98c5b01a2e050973))
+
### Removed
+- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
+ either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
+- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
+ and iOS.
+ ([#1033](https://github.com/nix-rust/nix/pull/1033))
## [0.12.0] 2018-11-28
@@ -887,7 +1038,24 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fixed passing multiple file descriptors over Unix Sockets.
([#918](https://github.com/nix-rust/nix/pull/918))
+## [0.11.1] 2019-06-06
+### Changed
+- Changed some public types from reexports of libc types like `uint32_t` to the
+ native equivalents like `u32.`
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+
+### Fixed
+- Fix the build on Android and Linux/mips with recent versions of libc.
+ ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
+- Fixed build on Linux/arm and Linux/s390x with the latest Rust libc
+ ([52102cb](https://github.com/nix-rust/nix/commit/52102cb76398c4dfb9ea141b98c5b01a2e050973))
+
### Removed
+- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
+ either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
+- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
+ and iOS.
+ ([#1033](https://github.com/nix-rust/nix/pull/1033))
## [0.11.0] 2018-06-01
diff --git a/Cargo.toml b/Cargo.toml
index 21b316c..24f8974 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2018"
-rust-version = "1.46"
+rust-version = "1.56"
name = "nix"
-version = "0.25.0"
+version = "0.26.1"
authors = ["The nix-rust Project Developers"]
include = [
"src/**/*",
@@ -75,13 +75,16 @@ version = "1.1"
version = "1.0"
[dependencies.libc]
-version = "0.2.127"
+version = "0.2.137"
features = ["extra_traits"]
[dependencies.pin-utils]
version = "0.1.0"
optional = true
+[dependencies.static_assertions]
+version = "1"
+
[dev-dependencies.assert-impl]
version = "0.1"
@@ -89,7 +92,7 @@ version = "0.1"
version = "1.4"
[dev-dependencies.parking_lot]
-version = "0.11.2"
+version = "0.12"
[dev-dependencies.rand]
version = "0.8"
@@ -100,9 +103,6 @@ version = "1.0.7"
[dev-dependencies.tempfile]
version = "3.3.0"
-[build-dependencies.autocfg]
-version = "1.1.0"
-
[features]
acct = []
aio = ["pin-utils"]
@@ -178,7 +178,7 @@ zerocopy = [
version = "0.5.3"
[target."cfg(not(target_os = \"redox\"))".dependencies.memoffset]
-version = "0.6.3"
+version = "0.7"
optional = true
[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 1d96efe..cfe20d8 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -2,8 +2,8 @@
name = "nix"
description = "Rust friendly bindings to *nix APIs"
edition = "2018"
-version = "0.25.0"
-rust-version = "1.46"
+version = "0.26.1"
+rust-version = "1.56"
authors = ["The nix-rust Project Developers"]
repository = "https://github.com/nix-rust/nix"
license = "MIT"
@@ -27,16 +27,14 @@ targets = [
]
[dependencies]
-libc = { version = "0.2.127", features = [ "extra_traits" ] }
+libc = { version = "0.2.137", features = [ "extra_traits" ] }
bitflags = "1.1"
cfg-if = "1.0"
pin-utils = { version = "0.1.0", optional = true }
+static_assertions = "1"
[target.'cfg(not(target_os = "redox"))'.dependencies]
-memoffset = { version = "0.6.3", optional = true }
-
-[build-dependencies]
-autocfg = "1.1.0"
+memoffset = { version = "0.7", optional = true }
[features]
default = [
@@ -83,7 +81,7 @@ zerocopy = ["fs", "uio"]
[dev-dependencies]
assert-impl = "0.1"
lazy_static = "1.4"
-parking_lot = "0.11.2"
+parking_lot = "0.12"
rand = "0.8"
tempfile = "3.3.0"
semver = "1.0.7"
diff --git a/METADATA b/METADATA
index b55d717..ef52918 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/nix
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
name: "nix"
description: "Rust friendly bindings to *nix APIs"
third_party {
@@ -7,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/nix/nix-0.25.0.crate"
+ value: "https://static.crates.io/crates/nix/nix-0.26.1.crate"
}
- version: "0.25.0"
+ version: "0.26.1"
license_type: NOTICE
last_upgrade_date {
year: 2022
- month: 10
- day: 6
+ month: 12
+ day: 12
}
}
diff --git a/README.md b/README.md
index 7c13cf2..7597ba0 100644
--- a/README.md
+++ b/README.md
@@ -89,7 +89,7 @@ Tier 3:
## Minimum Supported Rust Version (MSRV)
-nix is supported on Rust 1.46.0 and higher. Its MSRV will not be
+nix is supported on Rust 1.56.1 and higher. Its MSRV will not be
changed in the future without bumping the major or minor version.
## Contributing
diff --git a/src/dir.rs b/src/dir.rs
index 6d5fc3b..5ce5036 100644
--- a/src/dir.rs
+++ b/src/dir.rs
@@ -1,13 +1,13 @@
//! List directory contents
-use crate::{Error, NixPath, Result};
use crate::errno::Errno;
use crate::fcntl::{self, OFlag};
-use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
-use std::ptr;
-use std::ffi;
use crate::sys;
+use crate::{Error, NixPath, Result};
use cfg_if::cfg_if;
+use std::ffi;
+use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
+use std::ptr;
#[cfg(target_os = "linux")]
use libc::{dirent64 as dirent, readdir64_r as readdir_r};
@@ -29,21 +29,26 @@ use libc::{dirent, readdir_r};
/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
/// does).
#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct Dir(
- ptr::NonNull<libc::DIR>
-);
+pub struct Dir(ptr::NonNull<libc::DIR>);
impl Dir {
/// Opens the given path as with `fcntl::open`.
- pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag,
- mode: sys::stat::Mode) -> Result<Self> {
+ pub fn open<P: ?Sized + NixPath>(
+ path: &P,
+ oflag: OFlag,
+ mode: sys::stat::Mode,
+ ) -> Result<Self> {
let fd = fcntl::open(path, oflag, mode)?;
Dir::from_fd(fd)
}
/// Opens the given path as with `fcntl::openat`.
- pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag,
- mode: sys::stat::Mode) -> Result<Self> {
+ pub fn openat<P: ?Sized + NixPath>(
+ dirfd: RawFd,
+ path: &P,
+ oflag: OFlag,
+ mode: sys::stat::Mode,
+ ) -> Result<Self> {
let fd = fcntl::openat(dirfd, path, oflag, mode)?;
Dir::from_fd(fd)
}
@@ -55,13 +60,15 @@ impl Dir {
}
/// Converts from a file descriptor, closing it on success or failure.
- #[cfg_attr(has_doc_alias, doc(alias("fdopendir")))]
+ #[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
- })?;
+ let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(
+ || {
+ let e = Error::last();
+ unsafe { libc::close(fd) };
+ e
+ },
+ )?;
Ok(Dir(d))
}
@@ -103,9 +110,11 @@ fn next(dir: &mut Dir) -> Option<Result<Entry>> {
// Probably fine here too then.
let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
let mut result = ptr::null_mut();
- if let Err(e) = Errno::result(
- readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result))
- {
+ if let Err(e) = Errno::result(readdir_r(
+ dir.0.as_ptr(),
+ ent.as_mut_ptr(),
+ &mut result,
+ )) {
return Some(Err(e));
}
if result.is_null() {
@@ -207,7 +216,9 @@ pub enum Type {
impl Entry {
/// Returns the inode number (`d_ino`) of the underlying `dirent`.
- #[allow(clippy::useless_conversion)] // Not useless on all OSes
+ #[allow(clippy::useless_conversion)] // Not useless on all OSes
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
pub fn ino(&self) -> u64 {
cfg_if! {
if #[cfg(any(target_os = "android",
@@ -238,7 +249,11 @@ impl Entry {
/// notably, some Linux filesystems don't implement this. The caller should use `stat` or
/// `fstat` if this returns `None`.
pub fn file_type(&self) -> Option<Type> {
- #[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))]
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "solaris",
+ target_os = "haiku"
+ )))]
match self.0.d_type {
libc::DT_FIFO => Some(Type::Fifo),
libc::DT_CHR => Some(Type::CharacterDevice),
@@ -251,7 +266,11 @@ impl Entry {
}
// illumos, Solaris, and Haiku systems do not have the d_type member at all:
- #[cfg(any(target_os = "illumos", target_os = "solaris", target_os = "haiku"))]
+ #[cfg(any(
+ target_os = "illumos",
+ target_os = "solaris",
+ target_os = "haiku"
+ ))]
None
}
}
diff --git a/src/errno.rs b/src/errno.rs
index 912fb94..d8ad28d 100644
--- a/src/errno.rs
+++ b/src/errno.rs
@@ -1,4 +1,4 @@
-use crate::{Error, Result};
+use crate::Result;
use cfg_if::cfg_if;
use libc::{c_int, c_void};
use std::convert::TryFrom;
@@ -47,38 +47,10 @@ fn clear() {
/// Returns the platform-specific value of errno
pub fn errno() -> i32 {
- unsafe { (*errno_location()) as i32 }
+ unsafe { *errno_location() }
}
impl Errno {
- /// Convert this `Error` to an [`Errno`](enum.Errno.html).
- ///
- /// # Example
- ///
- /// ```
- /// # use nix::Error;
- /// # use nix::errno::Errno;
- /// let e = Error::from(Errno::EPERM);
- /// assert_eq!(Some(Errno::EPERM), e.as_errno());
- /// ```
- #[deprecated(since = "0.22.0", note = "It's a no-op now; just delete it.")]
- pub const fn as_errno(self) -> Option<Self> {
- Some(self)
- }
-
- /// Create a nix Error from a given errno
- #[deprecated(since = "0.22.0", note = "It's a no-op now; just delete it.")]
- #[allow(clippy::wrong_self_convention)] // False positive
- pub fn from_errno(errno: Errno) -> Error {
- errno
- }
-
- /// Create a new invalid argument error (`EINVAL`)
- #[deprecated(since = "0.22.0", note = "Use Errno::EINVAL instead")]
- pub const fn invalid_argument() -> Error {
- Errno::EINVAL
- }
-
pub fn last() -> Self {
last()
}
@@ -105,18 +77,6 @@ impl Errno {
Ok(value)
}
}
-
- /// Backwards compatibility hack for Nix <= 0.21.0 users
- ///
- /// In older versions of Nix, `Error::Sys` was an enum variant. Now it's a
- /// function, which is compatible with most of the former use cases of the
- /// enum variant. But you should use `Error(Errno::...)` instead.
- #[deprecated(since = "0.22.0", note = "Use Errno::... instead")]
- #[allow(non_snake_case)]
- #[inline]
- pub const fn Sys(errno: Errno) -> Error {
- errno
- }
}
/// The sentinel value indicates that a function failed and more detailed
@@ -1297,22 +1257,6 @@ mod consts {
EHWPOISON = libc::EHWPOISON,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EDEADLOCK instead"
- )]
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ENOTSUP instead"
- )]
- pub const ENOTSUP: Errno = Errno::EOPNOTSUPP;
-
impl Errno {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub const EDEADLOCK: Errno = Errno::EDEADLK;
@@ -1576,22 +1520,6 @@ mod consts {
EQFULL = libc::EQFULL,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::EQFULL;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EDEADLOCK instead"
- )]
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
-
impl Errno {
pub const ELAST: Errno = Errno::EQFULL;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
@@ -1818,27 +1746,6 @@ mod consts {
EOWNERDEAD = libc::EOWNERDEAD,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::EOWNERDEAD;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EDEADLOCK instead"
- )]
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EOPNOTSUPP instead"
- )]
- pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
-
impl Errno {
pub const ELAST: Errno = Errno::EOWNERDEAD;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
@@ -2056,27 +1963,6 @@ mod consts {
EASYNC = libc::EASYNC,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::EASYNC;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EDEADLOCK instead"
- )]
- pub const EDEADLOCK: Errno = Errno::EDEADLK;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EOPNOTSUPP instead"
- )]
- pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
-
impl Errno {
pub const ELAST: Errno = Errno::EASYNC;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
@@ -2291,17 +2177,6 @@ mod consts {
EPROTO = libc::EPROTO,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::ENOTSUP;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
impl Errno {
pub const ELAST: Errno = Errno::ENOTSUP;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
@@ -2516,17 +2391,6 @@ mod consts {
EPROTO = libc::EPROTO,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::ENOTSUP;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
impl Errno {
pub const ELAST: Errno = Errno::ENOTSUP;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
@@ -2731,12 +2595,6 @@ mod consts {
EPROTO = libc::EPROTO,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
impl Errno {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}
@@ -2965,17 +2823,6 @@ mod consts {
ESTALE = libc::ESTALE,
}
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::ELAST instead"
- )]
- pub const ELAST: Errno = Errno::ELAST;
- #[deprecated(
- since = "0.22.1",
- note = "use nix::errno::Errno::EWOULDBLOCK instead"
- )]
- pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
impl Errno {
pub const ELAST: Errno = Errno::ESTALE;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
diff --git a/src/fcntl.rs b/src/fcntl.rs
index 160b022..6508283 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -809,9 +809,7 @@ pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t)
0, // No flags are currently supported
&mut rqsr
)};
- if let Err(e) = Errno::result(res) {
- return Err(e);
- }
+ Errno::result(res)?;
}
Ok(())
}
diff --git a/src/features.rs b/src/features.rs
index d2adc16..39d1760 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -3,9 +3,9 @@ pub use self::os::*;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod os {
- use std::os::unix::ffi::OsStrExt;
use crate::sys::utsname::uname;
use crate::Result;
+ use std::os::unix::ffi::OsStrExt;
// Features:
// * atomic cloexec on socket: 2.6.27
@@ -13,10 +13,10 @@ mod os {
// * accept4: 2.6.28
static VERS_UNKNOWN: usize = 1;
- static VERS_2_6_18: usize = 2;
- static VERS_2_6_27: usize = 3;
- static VERS_2_6_28: usize = 4;
- static VERS_3: usize = 5;
+ static VERS_2_6_18: usize = 2;
+ static VERS_2_6_27: usize = 3;
+ static VERS_2_6_28: usize = 4;
+ static VERS_3: usize = 5;
#[inline]
fn digit(dst: &mut usize, b: u8) {
@@ -27,7 +27,7 @@ mod os {
fn parse_kernel_version() -> Result<usize> {
let u = uname()?;
- let mut curr: usize = 0;
+ let mut curr: usize = 0;
let mut major: usize = 0;
let mut minor: usize = 0;
let mut patch: usize = 0;
@@ -41,13 +41,11 @@ mod os {
b'.' | b'-' => {
curr += 1;
}
- b'0'..=b'9' => {
- match curr {
- 0 => digit(&mut major, b),
- 1 => digit(&mut minor, b),
- _ => digit(&mut patch, b),
- }
- }
+ b'0'..=b'9' => match curr {
+ 0 => digit(&mut major, b),
+ 1 => digit(&mut minor, b),
+ _ => digit(&mut patch, b),
+ },
_ => break,
}
}
@@ -87,7 +85,9 @@ mod os {
/// Check if the OS supports atomic close-on-exec for sockets
pub fn socket_atomic_cloexec() -> bool {
- kernel_version().map(|version| version >= VERS_2_6_27).unwrap_or(false)
+ kernel_version()
+ .map(|version| version >= VERS_2_6_27)
+ .unwrap_or(false)
}
#[test]
@@ -111,11 +111,13 @@ mod os {
}
}
-#[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "fuchsia",
- target_os = "haiku",
- target_os = "solaris"))]
+#[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "fuchsia",
+ target_os = "haiku",
+ target_os = "solaris"
+))]
mod os {
/// Check if the OS supports atomic close-on-exec for sockets
pub const fn socket_atomic_cloexec() -> bool {
diff --git a/src/ifaddrs.rs b/src/ifaddrs.rs
index f834d30..70b50b0 100644
--- a/src/ifaddrs.rs
+++ b/src/ifaddrs.rs
@@ -4,14 +4,16 @@
//! of interfaces and their associated addresses.
use cfg_if::cfg_if;
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+use std::convert::TryFrom;
use std::ffi;
use std::iter::Iterator;
use std::mem;
use std::option::Option;
-use crate::{Result, Errno};
-use crate::sys::socket::{SockaddrLike, SockaddrStorage};
use crate::net::if_::*;
+use crate::sys::socket::{SockaddrLike, SockaddrStorage};
+use crate::{Errno, Result};
/// Describes a single address for an interface as returned by `getifaddrs`.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
@@ -42,12 +44,52 @@ cfg_if! {
}
}
+/// Workaround a bug in XNU where netmasks will always have the wrong size in
+/// the sa_len field due to the kernel ignoring trailing zeroes in the structure
+/// when setting the field. See https://github.com/nix-rust/nix/issues/1709#issuecomment-1199304470
+///
+/// To fix this, we stack-allocate a new sockaddr_storage, zero it out, and
+/// memcpy sa_len of the netmask to that new storage. Finally, we reset the
+/// ss_len field to sizeof(sockaddr_storage). This is supposedly valid as all
+/// members of the sockaddr_storage are "ok" with being zeroed out (there are
+/// no pointers).
+#[cfg(any(target_os = "ios", target_os = "macos"))]
+unsafe fn workaround_xnu_bug(info: &libc::ifaddrs) -> Option<SockaddrStorage> {
+ let src_sock = info.ifa_netmask;
+ if src_sock.is_null() {
+ return None;
+ }
+
+ let mut dst_sock = mem::MaybeUninit::<libc::sockaddr_storage>::zeroed();
+
+ // memcpy only sa_len bytes, assume the rest is zero
+ std::ptr::copy_nonoverlapping(
+ src_sock as *const u8,
+ dst_sock.as_mut_ptr() as *mut u8,
+ (*src_sock).sa_len.into(),
+ );
+
+ // Initialize ss_len to sizeof(libc::sockaddr_storage).
+ (*dst_sock.as_mut_ptr()).ss_len =
+ u8::try_from(mem::size_of::<libc::sockaddr_storage>()).unwrap();
+ let dst_sock = dst_sock.assume_init();
+
+ let dst_sock_ptr =
+ &dst_sock as *const libc::sockaddr_storage as *const libc::sockaddr;
+
+ SockaddrStorage::from_raw(dst_sock_ptr, None)
+}
+
impl InterfaceAddress {
/// Create an `InterfaceAddress` from the libc struct.
fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
let address = unsafe { SockaddrStorage::from_raw(info.ifa_addr, None) };
- let netmask = unsafe { SockaddrStorage::from_raw(info.ifa_netmask, None) };
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ let netmask = unsafe { workaround_xnu_bug(info) };
+ #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ let netmask =
+ unsafe { SockaddrStorage::from_raw(info.ifa_netmask, None) };
let mut addr = InterfaceAddress {
interface_name: ifname.to_string_lossy().to_string(),
flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
@@ -144,4 +186,28 @@ mod tests {
fn test_getifaddrs() {
let _ = getifaddrs();
}
+
+ // Ensures getting the netmask works, and in particular that
+ // `workaround_xnu_bug` works properly.
+ #[test]
+ fn test_getifaddrs_netmask_correct() {
+ let addrs = getifaddrs().unwrap();
+ for iface in addrs {
+ let sock = if let Some(sock) = iface.netmask {
+ sock
+ } else {
+ continue;
+ };
+ if sock.family() == Some(crate::sys::socket::AddressFamily::Inet) {
+ let _ = sock.as_sockaddr_in().unwrap();
+ return;
+ } else if sock.family()
+ == Some(crate::sys::socket::AddressFamily::Inet6)
+ {
+ let _ = sock.as_sockaddr_in6().unwrap();
+ return;
+ }
+ }
+ panic!("No address?");
+ }
}
diff --git a/src/kmod.rs b/src/kmod.rs
index c42068c..1fa6c17 100644
--- a/src/kmod.rs
+++ b/src/kmod.rs
@@ -79,7 +79,11 @@ libc_bitflags!(
/// ```
///
/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
-pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
+pub fn finit_module<T: AsRawFd>(
+ fd: &T,
+ param_values: &CStr,
+ flags: ModuleInitFlags,
+) -> Result<()> {
let res = unsafe {
libc::syscall(
libc::SYS_finit_module,
@@ -116,7 +120,9 @@ libc_bitflags!(
///
/// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
- let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
+ let res = unsafe {
+ libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits())
+ };
Errno::result(res).map(drop)
}
diff --git a/src/lib.rs b/src/lib.rs
index 770258d..6b82125 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -106,7 +106,6 @@ feature! {
#[allow(missing_docs)]
pub mod kmod;
}
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
feature! {
#![feature = "mount"]
pub mod mount;
diff --git a/src/mount/bsd.rs b/src/mount/bsd.rs
index 109522f..d124f1f 100644
--- a/src/mount/bsd.rs
+++ b/src/mount/bsd.rs
@@ -1,19 +1,17 @@
-use crate::{
- Error,
- Errno,
- NixPath,
- Result,
-};
-use libc::{c_char, c_int, c_uint, c_void};
+#[cfg(target_os = "freebsd")]
+use crate::Error;
+use crate::{Errno, NixPath, Result};
+use libc::c_int;
+#[cfg(target_os = "freebsd")]
+use libc::{c_char, c_uint, c_void};
+#[cfg(target_os = "freebsd")]
use std::{
borrow::Cow,
- ffi::{CString, CStr},
- fmt,
- io,
+ ffi::{CStr, CString},
+ fmt, io,
marker::PhantomData,
};
-
libc_bitflags!(
/// Used with [`Nmount::nmount`].
pub struct MntFlags: c_int {
@@ -105,17 +103,18 @@ libc_bitflags!(
}
);
-
/// The Error type of [`Nmount::nmount`].
///
/// It wraps an [`Errno`], but also may contain an additional message returned
/// by `nmount(2)`.
+#[cfg(target_os = "freebsd")]
#[derive(Debug)]
pub struct NmountError {
errno: Error,
- errmsg: Option<String>
+ errmsg: Option<String>,
}
+#[cfg(target_os = "freebsd")]
impl NmountError {
/// Returns the additional error string sometimes generated by `nmount(2)`.
pub fn errmsg(&self) -> Option<&str> {
@@ -130,13 +129,15 @@ impl NmountError {
fn new(error: Error, errmsg: Option<&CStr>) -> Self {
Self {
errno: error,
- errmsg: errmsg.map(CStr::to_string_lossy).map(Cow::into_owned)
+ errmsg: errmsg.map(CStr::to_string_lossy).map(Cow::into_owned),
}
}
}
+#[cfg(target_os = "freebsd")]
impl std::error::Error for NmountError {}
+#[cfg(target_os = "freebsd")]
impl fmt::Display for NmountError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(errmsg) = &self.errmsg {
@@ -147,6 +148,7 @@ impl fmt::Display for NmountError {
}
}
+#[cfg(target_os = "freebsd")]
impl From<NmountError> for io::Error {
fn from(err: NmountError) -> Self {
err.errno.into()
@@ -154,6 +156,7 @@ impl From<NmountError> for io::Error {
}
/// Result type of [`Nmount::nmount`].
+#[cfg(target_os = "freebsd")]
pub type NmountResult = std::result::Result<(), NmountError>;
/// Mount a FreeBSD file system.
@@ -187,7 +190,7 @@ pub type NmountResult = std::result::Result<(), NmountError>;
/// .str_opt_owned("fspath", mountpoint.path().to_str().unwrap())
/// .str_opt_owned("target", target.path().to_str().unwrap())
/// .nmount(MntFlags::empty()).unwrap();
-///
+///
/// unmount(mountpoint.path(), MntFlags::empty()).unwrap();
/// ```
///
@@ -197,7 +200,7 @@ pub type NmountResult = std::result::Result<(), NmountError>;
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[derive(Debug, Default)]
-pub struct Nmount<'a>{
+pub struct Nmount<'a> {
// n.b. notgull: In reality, this is a list that contains
// both mutable and immutable pointers.
// Be careful using this.
@@ -219,7 +222,12 @@ impl<'a> Nmount<'a> {
}
/// Helper function to push a pointer and its length onto the `iov` array.
- fn push_pointer_and_length(&mut self, val: *const u8, len: usize, is_owned: bool) {
+ fn push_pointer_and_length(
+ &mut self,
+ val: *const u8,
+ len: usize,
+ is_owned: bool,
+ ) {
self.iov.push(libc::iovec {
iov_base: val as *mut _,
iov_len: len,
@@ -234,7 +242,8 @@ impl<'a> Nmount<'a> {
let ptr = s.to_owned().into_raw() as *const u8;
self.push_pointer_and_length(ptr, len, true);
- }).unwrap();
+ })
+ .unwrap();
}
/// Add an opaque mount option.
@@ -268,9 +277,8 @@ impl<'a> Nmount<'a> {
&mut self,
name: &'a CStr,
val: *mut c_void,
- len: usize
- ) -> &mut Self
- {
+ len: usize,
+ ) -> &mut Self {
self.push_slice(name.to_bytes_with_nul(), false);
self.push_pointer_and_length(val.cast(), len, false);
self
@@ -309,8 +317,10 @@ impl<'a> Nmount<'a> {
/// let mut nmount: Nmount<'static> = Nmount::new();
/// nmount.null_opt_owned(read_only);
/// ```
- pub fn null_opt_owned<P: ?Sized + NixPath>(&mut self, name: &P) -> &mut Self
- {
+ pub fn null_opt_owned<P: ?Sized + NixPath>(
+ &mut self,
+ name: &P,
+ ) -> &mut Self {
self.push_nix_path(name);
self.push_slice(&[], false);
self
@@ -328,12 +338,7 @@ impl<'a> Nmount<'a> {
/// Nmount::new()
/// .str_opt(&fstype, &nullfs);
/// ```
- pub fn str_opt(
- &mut self,
- name: &'a CStr,
- val: &'a CStr
- ) -> &mut Self
- {
+ pub fn str_opt(&mut self, name: &'a CStr, val: &'a CStr) -> &mut Self {
self.push_slice(name.to_bytes_with_nul(), false);
self.push_slice(val.to_bytes_with_nul(), false);
self
@@ -355,8 +360,9 @@ impl<'a> Nmount<'a> {
/// .str_opt_owned("fspath", mountpoint.to_str().unwrap());
/// ```
pub fn str_opt_owned<P1, P2>(&mut self, name: &P1, val: &P2) -> &mut Self
- where P1: ?Sized + NixPath,
- P2: ?Sized + NixPath
+ where
+ P1: ?Sized + NixPath,
+ P2: ?Sized + NixPath,
{
self.push_nix_path(name);
self.push_nix_path(val);
@@ -386,9 +392,7 @@ impl<'a> Nmount<'a> {
let niov = self.iov.len() as c_uint;
let iovp = self.iov.as_mut_ptr() as *mut libc::iovec;
- let res = unsafe {
- libc::nmount(iovp, niov, flags.bits)
- };
+ let res = unsafe { libc::nmount(iovp, niov, flags.bits) };
match Errno::result(res) {
Ok(_) => Ok(()),
Err(error) => {
@@ -425,18 +429,24 @@ impl<'a> Drop for Nmount<'a> {
///
/// Useful flags include
/// * `MNT_FORCE` - Unmount even if still in use.
-/// * `MNT_BYFSID` - `mountpoint` is not a path, but a file system ID
-/// encoded as `FSID:val0:val1`, where `val0` and `val1`
-/// are the contents of the `fsid_t val[]` array in decimal.
-/// The file system that has the specified file system ID
-/// will be unmounted. See
-/// [`statfs`](crate::sys::statfs::statfs) to determine the
-/// `fsid`.
+#[cfg_attr(
+ target_os = "freebsd",
+ doc = "
+* `MNT_BYFSID` - `mountpoint` is not a path, but a file system ID
+ encoded as `FSID:val0:val1`, where `val0` and `val1`
+ are the contents of the `fsid_t val[]` array in decimal.
+ The file system that has the specified file system ID
+ will be unmounted. See
+ [`statfs`](crate::sys::statfs::statfs) to determine the
+ `fsid`.
+"
+)]
pub fn unmount<P>(mountpoint: &P, flags: MntFlags) -> Result<()>
- where P: ?Sized + NixPath
+where
+ P: ?Sized + NixPath,
{
- let res = mountpoint.with_nix_path(|cstr| {
- unsafe { libc::unmount(cstr.as_ptr(), flags.bits) }
+ let res = mountpoint.with_nix_path(|cstr| unsafe {
+ libc::unmount(cstr.as_ptr(), flags.bits)
})?;
Errno::result(res).map(drop)
diff --git a/src/mount/linux.rs b/src/mount/linux.rs
index 4c976dc..cf6a60b 100644
--- a/src/mount/linux.rs
+++ b/src/mount/linux.rs
@@ -1,7 +1,7 @@
#![allow(missing_docs)]
-use libc::{self, c_ulong, c_int};
-use crate::{Result, NixPath};
use crate::errno::Errno;
+use crate::{NixPath, Result};
+use libc::{self, c_int, c_ulong};
libc_bitflags!(
pub struct MsFlags: c_ulong {
@@ -57,36 +57,40 @@ libc_bitflags!(
}
);
-pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
- source: Option<&P1>,
- target: &P2,
- fstype: Option<&P3>,
- flags: MsFlags,
- data: Option<&P4>) -> Result<()> {
-
+pub fn mount<
+ P1: ?Sized + NixPath,
+ P2: ?Sized + NixPath,
+ P3: ?Sized + NixPath,
+ P4: ?Sized + NixPath,
+>(
+ source: Option<&P1>,
+ target: &P2,
+ fstype: Option<&P3>,
+ flags: MsFlags,
+ data: Option<&P4>,
+) -> Result<()> {
fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
- where P: ?Sized + NixPath,
- F: FnOnce(*const libc::c_char) -> T
+ where
+ P: ?Sized + NixPath,
+ F: FnOnce(*const libc::c_char) -> T,
{
match p {
Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
- None => Ok(f(std::ptr::null()))
+ None => Ok(f(std::ptr::null())),
}
}
let res = with_opt_nix_path(source, |s| {
target.with_nix_path(|t| {
with_opt_nix_path(fstype, |ty| {
- with_opt_nix_path(data, |d| {
- unsafe {
- libc::mount(
- s,
- t.as_ptr(),
- ty,
- flags.bits,
- d as *const libc::c_void
- )
- }
+ with_opt_nix_path(data, |d| unsafe {
+ libc::mount(
+ s,
+ t.as_ptr(),
+ ty,
+ flags.bits,
+ d as *const libc::c_void,
+ )
})
})
})
@@ -96,16 +100,15 @@ pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P
}
pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
- let res = target.with_nix_path(|cstr| {
- unsafe { libc::umount(cstr.as_ptr()) }
- })?;
+ let res =
+ target.with_nix_path(|cstr| unsafe { libc::umount(cstr.as_ptr()) })?;
Errno::result(res).map(drop)
}
pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
- let res = target.with_nix_path(|cstr| {
- unsafe { libc::umount2(cstr.as_ptr(), flags.bits) }
+ let res = target.with_nix_path(|cstr| unsafe {
+ libc::umount2(cstr.as_ptr(), flags.bits)
})?;
Errno::result(res).map(drop)
diff --git a/src/mount/mod.rs b/src/mount/mod.rs
index e89c1a0..e98b49c 100644
--- a/src/mount/mod.rs
+++ b/src/mount/mod.rs
@@ -6,18 +6,21 @@ mod linux;
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use self::linux::*;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod bsd;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
pub use self::bsd::*;
diff --git a/src/mqueue.rs b/src/mqueue.rs
index e3c0c43..33599bf 100644
--- a/src/mqueue.rs
+++ b/src/mqueue.rs
@@ -30,15 +30,15 @@
//! ```
//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
+use crate::sys::stat::Mode;
use libc::{self, c_char, mqd_t, size_t};
use std::ffi::CStr;
-use crate::sys::stat::Mode;
use std::mem;
-libc_bitflags!{
+libc_bitflags! {
/// Used with [`mq_open`].
pub struct MQ_OFlag: libc::c_int {
/// Open the message queue for receiving messages.
@@ -96,12 +96,12 @@ impl MqAttr {
/// - `mq_maxmsg`: Maximum number of messages on the queue.
/// - `mq_msgsize`: Maximum message size in bytes.
/// - `mq_curmsgs`: Number of messages currently in the queue.
- pub fn new(mq_flags: mq_attr_member_t,
- mq_maxmsg: mq_attr_member_t,
- mq_msgsize: mq_attr_member_t,
- mq_curmsgs: mq_attr_member_t)
- -> MqAttr
- {
+ pub fn new(
+ mq_flags: mq_attr_member_t,
+ mq_maxmsg: mq_attr_member_t,
+ mq_msgsize: mq_attr_member_t,
+ mq_curmsgs: mq_attr_member_t,
+ ) -> MqAttr {
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
unsafe {
let p = attr.as_mut_ptr();
@@ -109,7 +109,9 @@ impl MqAttr {
(*p).mq_maxmsg = mq_maxmsg;
(*p).mq_msgsize = mq_msgsize;
(*p).mq_curmsgs = mq_curmsgs;
- MqAttr { mq_attr: attr.assume_init() }
+ MqAttr {
+ mq_attr: attr.assume_init(),
+ }
}
}
@@ -134,23 +136,25 @@ impl MqAttr {
}
}
-
/// Open a message queue
///
/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
// The mode.bits cast is only lossless on some OSes
#[allow(clippy::cast_lossless)]
-pub fn mq_open(name: &CStr,
- oflag: MQ_OFlag,
- mode: Mode,
- attr: Option<&MqAttr>)
- -> Result<MqdT> {
+pub fn mq_open(
+ name: &CStr,
+ oflag: MQ_OFlag,
+ mode: Mode,
+ attr: Option<&MqAttr>,
+) -> Result<MqdT> {
let res = match attr {
Some(mq_attr) => unsafe {
- libc::mq_open(name.as_ptr(),
- oflag.bits(),
- mode.bits() as libc::c_int,
- &mq_attr.mq_attr as *const libc::mq_attr)
+ libc::mq_open(
+ name.as_ptr(),
+ oflag.bits(),
+ mode.bits() as libc::c_int,
+ &mq_attr.mq_attr as *const libc::mq_attr,
+ )
},
None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
};
@@ -176,13 +180,19 @@ pub fn mq_close(mqdes: MqdT) -> Result<()> {
/// Receive a message from a message queue
///
/// See also [`mq_receive(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
-pub fn mq_receive(mqdes: &MqdT, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
+pub fn mq_receive(
+ mqdes: &MqdT,
+ message: &mut [u8],
+ msg_prio: &mut u32,
+) -> Result<usize> {
let len = message.len() as size_t;
let res = unsafe {
- libc::mq_receive(mqdes.0,
- message.as_mut_ptr() as *mut c_char,
- len,
- msg_prio as *mut u32)
+ libc::mq_receive(
+ mqdes.0,
+ message.as_mut_ptr() as *mut c_char,
+ len,
+ msg_prio as *mut u32,
+ )
};
Errno::result(res).map(|r| r as usize)
}
@@ -192,10 +202,12 @@ pub fn mq_receive(mqdes: &MqdT, message: &mut [u8], msg_prio: &mut u32) -> Resul
/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
pub fn mq_send(mqdes: &MqdT, message: &[u8], msq_prio: u32) -> Result<()> {
let res = unsafe {
- libc::mq_send(mqdes.0,
- message.as_ptr() as *const c_char,
- message.len(),
- msq_prio)
+ libc::mq_send(
+ mqdes.0,
+ message.as_ptr() as *const c_char,
+ message.len(),
+ msq_prio,
+ )
};
Errno::result(res).map(drop)
}
@@ -206,7 +218,11 @@ pub fn mq_send(mqdes: &MqdT, message: &[u8], msq_prio: u32) -> Result<()> {
pub fn mq_getattr(mqd: &MqdT) -> Result<MqAttr> {
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
let res = unsafe { libc::mq_getattr(mqd.0, attr.as_mut_ptr()) };
- Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
+ Errno::result(res).map(|_| unsafe {
+ MqAttr {
+ mq_attr: attr.assume_init(),
+ }
+ })
}
/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
@@ -217,21 +233,31 @@ pub fn mq_getattr(mqd: &MqdT) -> Result<MqAttr> {
pub fn mq_setattr(mqd: &MqdT, newattr: &MqAttr) -> Result<MqAttr> {
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
let res = unsafe {
- libc::mq_setattr(mqd.0, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
+ libc::mq_setattr(
+ mqd.0,
+ &newattr.mq_attr as *const libc::mq_attr,
+ attr.as_mut_ptr(),
+ )
};
- Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
+ Errno::result(res).map(|_| unsafe {
+ MqAttr {
+ mq_attr: attr.assume_init(),
+ }
+ })
}
/// Convenience function.
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
/// Returns the old attributes
-#[allow(clippy::useless_conversion)] // Not useless on all OSes
+#[allow(clippy::useless_conversion)] // Not useless on all OSes
pub fn mq_set_nonblock(mqd: &MqdT) -> Result<MqAttr> {
let oldattr = mq_getattr(mqd)?;
- let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
- oldattr.mq_attr.mq_maxmsg,
- oldattr.mq_attr.mq_msgsize,
- oldattr.mq_attr.mq_curmsgs);
+ let newattr = MqAttr::new(
+ mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
+ oldattr.mq_attr.mq_maxmsg,
+ oldattr.mq_attr.mq_msgsize,
+ oldattr.mq_attr.mq_curmsgs,
+ );
mq_setattr(mqd, &newattr)
}
@@ -240,9 +266,11 @@ pub fn mq_set_nonblock(mqd: &MqdT) -> Result<MqAttr> {
/// Returns the old attributes
pub fn mq_remove_nonblock(mqd: &MqdT) -> Result<MqAttr> {
let oldattr = mq_getattr(mqd)?;
- let newattr = MqAttr::new(0,
- oldattr.mq_attr.mq_maxmsg,
- oldattr.mq_attr.mq_msgsize,
- oldattr.mq_attr.mq_curmsgs);
+ let newattr = MqAttr::new(
+ 0,
+ oldattr.mq_attr.mq_maxmsg,
+ oldattr.mq_attr.mq_msgsize,
+ oldattr.mq_attr.mq_curmsgs,
+ );
mq_setattr(mqd, &newattr)
}
diff --git a/src/net/if_.rs b/src/net/if_.rs
index 045efad..b2423bc 100644
--- a/src/net/if_.rs
+++ b/src/net/if_.rs
@@ -8,7 +8,8 @@ use libc::c_uint;
/// Resolve an interface into a interface number.
pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
- let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
+ let if_index = name
+ .with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
if if_index == 0 {
Err(Error::last())
diff --git a/src/poll.rs b/src/poll.rs
index 3004d24..6f227fe 100644
--- a/src/poll.rs
+++ b/src/poll.rs
@@ -1,8 +1,8 @@
//! Wait for events to trigger on specific file descriptors
use std::os::unix::io::{AsRawFd, RawFd};
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
/// This is a wrapper around `libc::pollfd`.
///
@@ -37,6 +37,26 @@ impl PollFd {
PollFlags::from_bits(self.pollfd.revents)
}
+ /// Returns if any of the events of interest occured in the last call to `poll` or `ppoll`. Will
+ /// only return `None` if the kernel provides status flags that Nix does not know about.
+ ///
+ /// Equivalent to `x.revents()? != PollFlags::empty()`.
+ ///
+ /// This is marginally more efficient than [`PollFd::all`].
+ pub fn any(self) -> Option<bool> {
+ Some(self.revents()? != PollFlags::empty())
+ }
+
+ /// Returns if all the events of interest occured in the last call to `poll` or `ppoll`. Will
+ /// only return `None` if the kernel provides status flags that Nix does not know about.
+ ///
+ /// Equivalent to `x.revents()? & x.events() == x.events()`.
+ ///
+ /// This is marginally less efficient than [`PollFd::any`].
+ 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 {
PollFlags::from_bits(self.pollfd.events).unwrap()
@@ -134,9 +154,11 @@ libc_bitflags! {
/// ready.
pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
let res = unsafe {
- libc::poll(fds.as_mut_ptr() as *mut libc::pollfd,
- fds.len() as libc::nfds_t,
- timeout)
+ libc::poll(
+ fds.as_mut_ptr() as *mut libc::pollfd,
+ fds.len() as libc::nfds_t,
+ timeout,
+ )
};
Errno::result(res)
diff --git a/src/pty.rs b/src/pty.rs
index bb266a6..28ae5e9 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -8,11 +8,11 @@ use std::io;
use std::mem;
use std::os::unix::prelude::*;
+use crate::errno::Errno;
use crate::sys::termios::Termios;
#[cfg(feature = "process")]
use crate::unistd::{ForkResult, Pid};
-use crate::{Result, fcntl, unistd};
-use crate::errno::Errno;
+use crate::{fcntl, unistd, Result};
/// Representation of a master/slave pty pair
///
@@ -41,7 +41,6 @@ pub struct ForkptyResult {
}
}
-
/// Representation of the Master device in a master/slave pty pair
///
/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
@@ -159,9 +158,7 @@ pub fn grantpt(fd: &PtyMaster) -> Result<()> {
/// ```
#[inline]
pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
- let fd = unsafe {
- libc::posix_openpt(flags.bits())
- };
+ let fd = unsafe { libc::posix_openpt(flags.bits()) };
if fd < 0 {
return Err(Errno::last());
@@ -239,7 +236,6 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
Ok(())
}
-
/// Create a new pseudoterminal, returning the slave and master file descriptors
/// in `OpenptyResult`
/// (see [`openpty`](https://man7.org/linux/man-pages/man3/openpty.3.html)).
@@ -248,7 +244,15 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
-pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
+pub fn openpty<
+ 'a,
+ 'b,
+ T: Into<Option<&'a Winsize>>,
+ U: Into<Option<&'b Termios>>,
+>(
+ winsize: T,
+ termios: U,
+) -> Result<OpenptyResult> {
use std::ptr;
let mut slave = mem::MaybeUninit::<libc::c_int>::uninit();
@@ -267,17 +271,15 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
)
}
}
- (None, Some(winsize)) => {
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- ptr::null_mut(),
- winsize as *const Winsize as *mut _,
- )
- }
- }
+ (None, Some(winsize)) => unsafe {
+ libc::openpty(
+ master.as_mut_ptr(),
+ slave.as_mut_ptr(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ winsize as *const Winsize as *mut _,
+ )
+ },
(Some(termios), None) => {
let inner_termios = termios.get_libc_termios();
unsafe {
@@ -290,17 +292,15 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
)
}
}
- (None, None) => {
- unsafe {
- libc::openpty(
- master.as_mut_ptr(),
- slave.as_mut_ptr(),
- ptr::null_mut(),
- ptr::null_mut(),
- ptr::null_mut(),
- )
- }
- }
+ (None, None) => unsafe {
+ libc::openpty(
+ master.as_mut_ptr(),
+ slave.as_mut_ptr(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ )
+ },
}
};
diff --git a/src/sched.rs b/src/sched.rs
index e9a326e..d5b1233 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -11,12 +11,12 @@ pub use self::sched_linux_like::*;
#[cfg_attr(docsrs, doc(cfg(all())))]
mod sched_linux_like {
use crate::errno::Errno;
+ use crate::unistd::Pid;
+ use crate::Result;
use libc::{self, c_int, c_void};
use std::mem;
use std::option::Option;
use std::os::unix::io::RawFd;
- use crate::unistd::Pid;
- use crate::Result;
// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
@@ -112,7 +112,8 @@ mod sched_linux_like {
let ptr_aligned = ptr.sub(ptr as usize % 16);
libc::clone(
mem::transmute(
- callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
+ callback
+ as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
),
ptr_aligned as *mut c_void,
combined,
@@ -142,25 +143,38 @@ mod sched_linux_like {
}
}
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux"))]
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux"
+))]
pub use self::sched_affinity::*;
-#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux"))]
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux"
+))]
mod sched_affinity {
use crate::errno::Errno;
- use std::mem;
use crate::unistd::Pid;
use crate::Result;
+ use std::mem;
/// CpuSet represent a bit-mask of CPUs.
/// CpuSets are used by sched_setaffinity and
/// sched_getaffinity for example.
///
/// This is a wrapper around `libc::cpu_set_t`.
- #[repr(C)]
+ #[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct CpuSet {
+ #[cfg(not(target_os = "freebsd"))]
cpu_set: libc::cpu_set_t,
+ #[cfg(target_os = "freebsd")]
+ cpu_set: libc::cpuset_t,
}
impl CpuSet {
@@ -187,7 +201,9 @@ mod sched_affinity {
if field >= CpuSet::count() {
Err(Errno::EINVAL)
} else {
- unsafe { libc::CPU_SET(field, &mut self.cpu_set); }
+ unsafe {
+ libc::CPU_SET(field, &mut self.cpu_set);
+ }
Ok(())
}
}
@@ -198,14 +214,21 @@ mod sched_affinity {
if field >= CpuSet::count() {
Err(Errno::EINVAL)
} else {
- unsafe { libc::CPU_CLR(field, &mut self.cpu_set);}
+ unsafe {
+ libc::CPU_CLR(field, &mut self.cpu_set);
+ }
Ok(())
}
}
/// Return the maximum number of CPU in CpuSet
pub const fn count() -> usize {
- 8 * mem::size_of::<libc::cpu_set_t>()
+ #[cfg(not(target_os = "freebsd"))]
+ let bytes = mem::size_of::<libc::cpu_set_t>();
+ #[cfg(target_os = "freebsd")]
+ let bytes = mem::size_of::<libc::cpuset_t>();
+
+ 8 * bytes
}
}
@@ -282,6 +305,13 @@ mod sched_affinity {
Errno::result(res).and(Ok(cpuset))
}
+
+ /// Determines the CPU on which the calling thread is running.
+ pub fn sched_getcpu() -> Result<usize> {
+ let res = unsafe { libc::sched_getcpu() };
+
+ Errno::result(res).map(|int| int as usize)
+ }
}
/// Explicitly yield the processor to other threads.
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index 6ff8846..e2ce19b 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -32,8 +32,7 @@ use std::{
mem,
os::unix::io::RawFd,
pin::Pin,
- ptr,
- thread,
+ ptr, thread,
};
use libc::{c_void, off_t};
@@ -107,7 +106,7 @@ unsafe impl Sync for LibcAiocb {}
// polymorphism is at the level of `Futures`.
#[repr(C)]
struct AioCb {
- aiocb: LibcAiocb,
+ aiocb: LibcAiocb,
/// Could this `AioCb` potentially have any in-kernel state?
// It would be really nice to perform the in-progress check entirely at
// compile time. But I can't figure out how, because:
@@ -153,7 +152,7 @@ impl AioCb {
a.aio_reqprio = prio;
a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
AioCb {
- aiocb: LibcAiocb(a),
+ aiocb: LibcAiocb(a),
in_progress: false,
}
}
@@ -432,7 +431,7 @@ macro_rules! aio_methods {
#[repr(transparent)]
pub struct AioFsync {
aiocb: AioCb,
- _pin: PhantomPinned,
+ _pin: PhantomPinned,
}
impl AioFsync {
@@ -546,7 +545,7 @@ impl AsRef<libc::aiocb> for AioFsync {
pub struct AioRead<'a> {
aiocb: AioCb,
_data: PhantomData<&'a [u8]>,
- _pin: PhantomPinned,
+ _pin: PhantomPinned,
}
impl<'a> AioRead<'a> {
@@ -667,7 +666,7 @@ impl<'a> AsRef<libc::aiocb> for AioRead<'a> {
pub struct AioReadv<'a> {
aiocb: AioCb,
_data: PhantomData<&'a [&'a [u8]]>,
- _pin: PhantomPinned,
+ _pin: PhantomPinned,
}
#[cfg(target_os = "freebsd")]
@@ -778,7 +777,7 @@ impl<'a> AsRef<libc::aiocb> for AioReadv<'a> {
pub struct AioWrite<'a> {
aiocb: AioCb,
_data: PhantomData<&'a [u8]>,
- _pin: PhantomPinned,
+ _pin: PhantomPinned,
}
impl<'a> AioWrite<'a> {
@@ -896,7 +895,7 @@ impl<'a> AsRef<libc::aiocb> for AioWrite<'a> {
pub struct AioWritev<'a> {
aiocb: AioCb,
_data: PhantomData<&'a [&'a [u8]]>,
- _pin: PhantomPinned,
+ _pin: PhantomPinned,
}
#[cfg(target_os = "freebsd")]
@@ -1053,8 +1052,7 @@ pub fn aio_suspend(
timeout: Option<TimeSpec>,
) -> Result<()> {
let p = list as *const [&dyn AsRef<libc::aiocb>]
- as *const [*const libc::aiocb]
- as *const *const libc::aiocb;
+ as *const [*const libc::aiocb] as *const *const libc::aiocb;
let timep = match timeout {
None => ptr::null::<libc::timespec>(),
Some(x) => x.as_ref() as *const libc::timespec,
@@ -1180,8 +1178,7 @@ pub fn lio_listio(
sigev_notify: SigevNotify,
) -> Result<()> {
let p = list as *mut [Pin<&mut dyn AsMut<libc::aiocb>>]
- as *mut [*mut libc::aiocb]
- as *mut *mut libc::aiocb;
+ as *mut [*mut libc::aiocb] as *mut *mut libc::aiocb;
let sigev = SigEvent::new(sigev_notify);
let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
Errno::result(unsafe {
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index 8141ff5..58def2e 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -1,9 +1,9 @@
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
use libc::{self, c_int};
+use std::mem;
use std::os::unix::io::RawFd;
use std::ptr;
-use std::mem;
libc_bitflags!(
pub struct EpollFlags: c_int {
@@ -35,7 +35,7 @@ pub enum EpollOp {
EpollCtlMod = libc::EPOLL_CTL_MOD,
}
-libc_bitflags!{
+libc_bitflags! {
pub struct EpollCreateFlags: c_int {
EPOLL_CLOEXEC;
}
@@ -49,7 +49,12 @@ pub struct EpollEvent {
impl EpollEvent {
pub fn new(events: EpollFlags, data: u64) -> Self {
- EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
+ EpollEvent {
+ event: libc::epoll_event {
+ events: events.bits() as u32,
+ u64: data,
+ },
+ }
}
pub fn empty() -> Self {
@@ -80,8 +85,14 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
}
#[inline]
-pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
- where T: Into<Option<&'a mut EpollEvent>>
+pub fn epoll_ctl<'a, T>(
+ epfd: RawFd,
+ op: EpollOp,
+ fd: RawFd,
+ event: T,
+) -> Result<()>
+where
+ T: Into<Option<&'a mut EpollEvent>>,
{
let mut event: Option<&mut EpollEvent> = event.into();
if event.is_none() && op != EpollOp::EpollCtlDel {
@@ -99,9 +110,18 @@ pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result
}
#[inline]
-pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
+pub fn epoll_wait(
+ epfd: RawFd,
+ events: &mut [EpollEvent],
+ timeout_ms: isize,
+) -> Result<usize> {
let res = unsafe {
- libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
+ libc::epoll_wait(
+ epfd,
+ events.as_mut_ptr() as *mut libc::epoll_event,
+ events.len() as c_int,
+ timeout_ms as c_int,
+ )
};
Errno::result(res).map(|r| r as usize)
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 0d0d23a..d8ad628 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -3,9 +3,9 @@
use crate::{Errno, Result};
#[cfg(not(target_os = "netbsd"))]
-use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
+use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t};
#[cfg(target_os = "netbsd")]
-use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
+use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t};
use std::convert::TryInto;
use std::mem;
use std::os::unix::io::RawFd;
@@ -18,9 +18,13 @@ pub struct KEvent {
kevent: libc::kevent,
}
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd"
+))]
type type_of_udata = *mut libc::c_void;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;
@@ -75,13 +79,17 @@ libc_enum! {
impl TryFrom<type_of_event_filter>
}
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd"
+))]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd"))]
pub type type_of_event_flag = u32;
-libc_bitflags!{
+libc_bitflags! {
pub struct EventFlag: type_of_event_flag {
EV_ADD;
EV_CLEAR;
@@ -205,27 +213,33 @@ pub fn kqueue() -> Result<RawFd> {
Errno::result(res)
}
-
// KEvent can't derive Send because on some operating systems, udata is defined
// as a void*. However, KEvent's public API always treats udata as an intptr_t,
// which is safe to Send.
-unsafe impl Send for KEvent {
-}
+unsafe impl Send for KEvent {}
impl KEvent {
- #[allow(clippy::needless_update)] // Not needless on all platforms.
- pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
- fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
- KEvent { kevent: libc::kevent {
- ident,
- filter: filter as type_of_event_filter,
- flags: flags.bits(),
- fflags: fflags.bits(),
- // data can be either i64 or intptr_t, depending on platform
- data: data as _,
- udata: udata as type_of_udata,
- .. unsafe { mem::zeroed() }
- } }
+ #[allow(clippy::needless_update)] // Not needless on all platforms.
+ pub fn new(
+ ident: uintptr_t,
+ filter: EventFilter,
+ flags: EventFlag,
+ fflags: FilterFlag,
+ data: intptr_t,
+ udata: intptr_t,
+ ) -> KEvent {
+ KEvent {
+ kevent: libc::kevent {
+ ident,
+ filter: filter as type_of_event_filter,
+ flags: flags.bits(),
+ fflags: fflags.bits(),
+ // data can be either i64 or intptr_t, depending on platform
+ data: data as _,
+ udata: udata as type_of_udata,
+ ..unsafe { mem::zeroed() }
+ },
+ }
}
pub fn ident(&self) -> uintptr_t {
@@ -253,34 +267,38 @@ impl KEvent {
}
}
-pub fn kevent(kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_ms: usize) -> Result<usize> {
-
+pub fn kevent(
+ kq: RawFd,
+ changelist: &[KEvent],
+ eventlist: &mut [KEvent],
+ timeout_ms: usize,
+) -> Result<usize> {
// Convert ms to timespec
let timeout = timespec {
tv_sec: (timeout_ms / 1000) as time_t,
- tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
+ tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long,
};
kevent_ts(kq, changelist, eventlist, Some(timeout))
}
-#[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "openbsd"
+))]
type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;
-pub fn kevent_ts(kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_opt: Option<timespec>) -> Result<usize> {
-
+pub fn kevent_ts(
+ kq: RawFd,
+ changelist: &[KEvent],
+ eventlist: &mut [KEvent],
+ timeout_opt: Option<timespec>,
+) -> Result<usize> {
let res = unsafe {
libc::kevent(
kq,
@@ -288,40 +306,48 @@ pub fn kevent_ts(kq: RawFd,
changelist.len() as type_of_nchanges,
eventlist.as_mut_ptr() as *mut libc::kevent,
eventlist.len() as type_of_nchanges,
- if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
+ if let Some(ref timeout) = timeout_opt {
+ timeout as *const timespec
+ } else {
+ ptr::null()
+ },
+ )
};
Errno::result(res).map(|r| r as usize)
}
#[inline]
-pub fn ev_set(ev: &mut KEvent,
- ident: usize,
- filter: EventFilter,
- flags: EventFlag,
- fflags: FilterFlag,
- udata: intptr_t) {
-
- ev.kevent.ident = ident as uintptr_t;
+pub fn ev_set(
+ ev: &mut KEvent,
+ ident: usize,
+ filter: EventFilter,
+ flags: EventFlag,
+ fflags: FilterFlag,
+ udata: intptr_t,
+) {
+ ev.kevent.ident = ident as uintptr_t;
ev.kevent.filter = filter as type_of_event_filter;
- ev.kevent.flags = flags.bits();
+ ev.kevent.flags = flags.bits();
ev.kevent.fflags = fflags.bits();
- ev.kevent.data = 0;
- ev.kevent.udata = udata as type_of_udata;
+ ev.kevent.data = 0;
+ ev.kevent.udata = udata as type_of_udata;
}
#[test]
fn test_struct_kevent() {
use std::mem;
- let udata : intptr_t = 12345;
+ let udata: intptr_t = 12345;
- let actual = KEvent::new(0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata);
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata,
+ );
assert_eq!(0xdead_beef, actual.ident());
let filter = actual.kevent.filter;
assert_eq!(libc::EVFILT_READ, filter);
@@ -334,13 +360,15 @@ fn test_struct_kevent() {
#[test]
fn test_kevent_filter() {
- let udata : intptr_t = 12345;
+ let udata: intptr_t = 12345;
- let actual = KEvent::new(0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata);
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata,
+ );
assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
}
diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs
index c54f952..cd90672 100644
--- a/src/sys/eventfd.rs
+++ b/src/sys/eventfd.rs
@@ -1,6 +1,6 @@
-use std::os::unix::io::RawFd;
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
+use std::os::unix::io::RawFd;
libc_bitflags! {
pub struct EfdFlags: libc::c_int {
diff --git a/src/sys/inotify.rs b/src/sys/inotify.rs
index b19dbe1..84356ec 100644
--- a/src/sys/inotify.rs
+++ b/src/sys/inotify.rs
@@ -23,20 +23,17 @@
//! }
//! ```
-use libc::{
- c_char,
- c_int,
-};
-use std::ffi::{OsString,OsStr,CStr};
-use std::os::unix::ffi::OsStrExt;
-use std::mem::{MaybeUninit, size_of};
-use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
-use std::ptr;
+use crate::errno::Errno;
use crate::unistd::read;
-use crate::Result;
use crate::NixPath;
-use crate::errno::Errno;
+use crate::Result;
use cfg_if::cfg_if;
+use libc::{c_char, c_int};
+use std::ffi::{CStr, OsStr, OsString};
+use std::mem::{size_of, MaybeUninit};
+use std::os::unix::ffi::OsStrExt;
+use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::ptr;
libc_bitflags! {
/// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
@@ -106,7 +103,7 @@ libc_bitflags! {
/// other interfaces consuming file descriptors, epoll for example.
#[derive(Debug, Clone, Copy)]
pub struct Inotify {
- fd: RawFd
+ fd: RawFd,
}
/// This object is returned when you create a new watch on an inotify instance.
@@ -114,7 +111,7 @@ pub struct Inotify {
/// know which watch triggered which event.
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct WatchDescriptor {
- wd: i32
+ wd: i32,
}
/// A single inotify event.
@@ -134,7 +131,7 @@ pub struct InotifyEvent {
pub cookie: u32,
/// Filename. This field exists only if the event was triggered for a file
/// inside the watched directory.
- pub name: Option<OsString>
+ pub name: Option<OsString>,
}
impl Inotify {
@@ -144,9 +141,7 @@ impl Inotify {
///
/// For more information see, [inotify_init(2)](https://man7.org/linux/man-pages/man2/inotify_init.2.html).
pub fn init(flags: InitFlags) -> Result<Inotify> {
- let res = Errno::result(unsafe {
- libc::inotify_init1(flags.bits())
- });
+ let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) });
res.map(|fd| Inotify { fd })
}
@@ -156,15 +151,13 @@ impl Inotify {
/// Returns a watch descriptor. This is not a File Descriptor!
///
/// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
- pub fn add_watch<P: ?Sized + NixPath>(self,
- path: &P,
- mask: AddWatchFlags)
- -> Result<WatchDescriptor>
- {
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
- }
+ pub fn add_watch<P: ?Sized + NixPath>(
+ self,
+ path: &P,
+ mask: AddWatchFlags,
+ ) -> Result<WatchDescriptor> {
+ let res = path.with_nix_path(|cstr| unsafe {
+ libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
})?;
Errno::result(res).map(|wd| WatchDescriptor { wd })
@@ -210,7 +203,7 @@ impl Inotify {
ptr::copy_nonoverlapping(
buffer.as_ptr().add(offset),
event.as_mut_ptr() as *mut u8,
- (BUFSIZ - offset).min(header_size)
+ (BUFSIZ - offset).min(header_size),
);
event.assume_init()
};
@@ -219,9 +212,7 @@ impl Inotify {
0 => None,
_ => {
let ptr = unsafe {
- buffer
- .as_ptr()
- .add(offset + header_size)
+ buffer.as_ptr().add(offset + header_size)
as *const c_char
};
let cstr = unsafe { CStr::from_ptr(ptr) };
@@ -234,7 +225,7 @@ impl Inotify {
wd: WatchDescriptor { wd: event.wd },
mask: AddWatchFlags::from_bits_truncate(event.mask),
cookie: event.cookie,
- name
+ name,
});
offset += header_size + event.len as usize;
diff --git a/src/sys/memfd.rs b/src/sys/memfd.rs
index 642676b..ad9345e 100644
--- a/src/sys/memfd.rs
+++ b/src/sys/memfd.rs
@@ -1,8 +1,10 @@
//! Interfaces for managing memory-backed files.
+use cfg_if::cfg_if;
use std::os::unix::io::RawFd;
-use crate::Result;
+
use crate::errno::Errno;
+use crate::Result;
use std::ffi::CStr;
libc_bitflags!(
@@ -40,7 +42,22 @@ libc_bitflags!(
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
let res = unsafe {
- libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
+ 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
+ target_env = "gnu",
+ target_env = "musl",
+ )))]
+ {
+ libc::memfd_create(name.as_ptr(), flags.bits())
+ } else {
+ libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
+ }
+ }
};
Errno::result(res).map(|r| r as RawFd)
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index 700e231..2bee091 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -1,16 +1,16 @@
//! Memory management declarations.
-use crate::Result;
+use crate::errno::Errno;
#[cfg(not(target_os = "android"))]
use crate::NixPath;
-use crate::errno::Errno;
+use crate::Result;
#[cfg(not(target_os = "android"))]
#[cfg(feature = "fs")]
use crate::{fcntl::OFlag, sys::stat::Mode};
-use libc::{self, c_int, c_void, size_t, off_t};
-use std::os::unix::io::RawFd;
+use libc::{self, c_int, c_void, off_t, size_t};
+use std::{os::unix::io::RawFd, num::NonZeroUsize};
-libc_bitflags!{
+libc_bitflags! {
/// Desired memory protection of a memory mapping.
pub struct ProtFlags: c_int {
/// Pages cannot be accessed.
@@ -32,7 +32,7 @@ libc_bitflags!{
}
}
-libc_bitflags!{
+libc_bitflags! {
/// Additional parameters for [`mmap`].
pub struct MapFlags: c_int {
/// Compatibility flag. Ignored.
@@ -188,7 +188,7 @@ libc_bitflags!{
}
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
-libc_bitflags!{
+libc_bitflags! {
/// Options for [`mremap`].
pub struct MRemapFlags: c_int {
/// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
@@ -210,7 +210,7 @@ libc_bitflags!{
}
}
-libc_enum!{
+libc_enum! {
/// Usage information for a range of memory to allow for performance optimizations by the kernel.
///
/// Used by [`madvise`].
@@ -331,7 +331,7 @@ libc_enum!{
}
}
-libc_bitflags!{
+libc_bitflags! {
/// Configuration flags for [`msync`].
pub struct MsFlags: c_int {
/// Schedule an update but return immediately.
@@ -352,7 +352,7 @@ libc_bitflags!{
}
#[cfg(not(target_os = "haiku"))]
-libc_bitflags!{
+libc_bitflags! {
/// Flags for [`mlockall`].
pub struct MlockAllFlags: c_int {
/// Lock pages that are currently mapped into the address space of the process.
@@ -416,8 +416,20 @@ pub fn munlockall() -> Result<()> {
/// See the [`mmap(2)`] man page for detailed requirements.
///
/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
-pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
- let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
+pub unsafe fn mmap(
+ addr: Option<NonZeroUsize>,
+ length: NonZeroUsize,
+ prot: ProtFlags,
+ flags: MapFlags,
+ fd: RawFd,
+ offset: off_t,
+) -> Result<*mut c_void> {
+ let ptr = addr.map_or(
+ std::ptr::null_mut(),
+ |a| usize::from(a) as *mut c_void
+ );
+
+ let ret = libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset);
if ret == libc::MAP_FAILED {
Err(Errno::last())
@@ -439,10 +451,16 @@ pub unsafe fn mremap(
old_size: size_t,
new_size: size_t,
flags: MRemapFlags,
- new_address: Option<* mut c_void>,
+ new_address: Option<*mut c_void>,
) -> Result<*mut c_void> {
#[cfg(target_os = "linux")]
- let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
+ let ret = libc::mremap(
+ addr,
+ old_size,
+ new_size,
+ flags.bits(),
+ new_address.unwrap_or(std::ptr::null_mut()),
+ );
#[cfg(target_os = "netbsd")]
let ret = libc::mremap(
addr,
@@ -450,7 +468,7 @@ pub unsafe fn mremap(
new_address.unwrap_or(std::ptr::null_mut()),
new_size,
flags.bits(),
- );
+ );
if ret == libc::MAP_FAILED {
Err(Errno::last())
@@ -479,7 +497,11 @@ pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
/// [`MmapAdvise::MADV_FREE`].
///
/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
-pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
+pub unsafe fn madvise(
+ addr: *mut c_void,
+ length: size_t,
+ advise: MmapAdvise,
+) -> Result<()> {
Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
}
@@ -498,8 +520,9 @@ pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) ->
/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
/// # use std::ptr;
/// const ONE_K: size_t = 1024;
+/// let one_k_non_zero = std::num::NonZeroUsize::new(ONE_K).unwrap();
/// let mut slice: &mut [u8] = unsafe {
-/// let mem = mmap(ptr::null_mut(), ONE_K, ProtFlags::PROT_NONE,
+/// let mem = mmap(None, one_k_non_zero, ProtFlags::PROT_NONE,
/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
@@ -508,7 +531,11 @@ pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) ->
/// slice[0] = 0xFF;
/// assert_eq!(slice[0], 0xFF);
/// ```
-pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> {
+pub unsafe fn mprotect(
+ addr: *mut c_void,
+ length: size_t,
+ prot: ProtFlags,
+) -> Result<()> {
Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
}
@@ -520,7 +547,11 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Re
/// page.
///
/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
-pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
+pub unsafe fn msync(
+ addr: *mut c_void,
+ length: size_t,
+ flags: MsFlags,
+) -> Result<()> {
Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
}
@@ -561,9 +592,8 @@ pub fn shm_open<P>(
/// [`shm_unlink(3)`]: https://man7.org/linux/man-pages/man3/shm_unlink.3.html
#[cfg(not(target_os = "android"))]
pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
- let ret = name.with_nix_path(|cstr| {
- unsafe { libc::shm_unlink(cstr.as_ptr()) }
- })?;
+ let ret =
+ name.with_nix_path(|cstr| unsafe { libc::shm_unlink(cstr.as_ptr()) })?;
Errno::result(ret).map(drop)
}
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 979d623..2065059 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -50,7 +50,7 @@ feature! {
#[macro_use]
pub mod ioctl;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
feature! {
#![feature = "fs"]
pub mod memfd;
diff --git a/src/sys/personality.rs b/src/sys/personality.rs
index 9e285ae..f295a05 100644
--- a/src/sys/personality.rs
+++ b/src/sys/personality.rs
@@ -1,6 +1,6 @@
//! Process execution domains
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
use libc::{self, c_int, c_ulong};
@@ -62,9 +62,7 @@ libc_bitflags! {
/// assert!(!pers.contains(Persona::WHOLE_SECONDS));
/// ```
pub fn get() -> Result<Persona> {
- let res = unsafe {
- libc::personality(0xFFFFFFFF)
- };
+ let res = unsafe { libc::personality(0xFFFFFFFF) };
Errno::result(res).map(Persona::from_bits_truncate)
}
@@ -89,9 +87,7 @@ pub fn get() -> Result<Persona> {
/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE).unwrap();
/// ```
pub fn set(persona: Persona) -> Result<Persona> {
- let res = unsafe {
- libc::personality(persona.bits() as c_ulong)
- };
+ let res = unsafe { libc::personality(persona.bits() as c_ulong) };
Errno::result(res).map(Persona::from_bits_truncate)
}
diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs
index fd81f3e..6bad03a 100644
--- a/src/sys/pthread.rs
+++ b/src/sys/pthread.rs
@@ -28,6 +28,7 @@ feature! {
/// won't send any signal.
///
/// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[cfg(not(target_os = "redox"))]
pub fn pthread_kill<T>(thread: Pthread, signal: T) -> Result<()>
where T: Into<Option<crate::sys::signal::Signal>>
diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs
index c4cc740..ba267c6 100644
--- a/src/sys/ptrace/bsd.rs
+++ b/src/sys/ptrace/bsd.rs
@@ -1,16 +1,16 @@
-use cfg_if::cfg_if;
use crate::errno::Errno;
-use libc::{self, c_int};
-use std::ptr;
use crate::sys::signal::Signal;
use crate::unistd::Pid;
use crate::Result;
+use cfg_if::cfg_if;
+use libc::{self, c_int};
+use std::ptr;
pub type RequestType = c_int;
cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
+ if #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
target_os = "macos",
target_os = "openbsd"))] {
#[doc(hidden)]
@@ -71,7 +71,8 @@ unsafe fn ptrace_other(
libc::pid_t::from(pid),
addr,
data,
- )).map(|_| 0)
+ ))
+ .map(|_| 0)
}
/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
@@ -79,14 +80,19 @@ unsafe fn ptrace_other(
/// Indicates that this process is to be traced by its parent.
/// This is the only ptrace request to be issued by the tracee.
pub fn traceme() -> Result<()> {
- unsafe { ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0).map(drop) }
+ unsafe {
+ ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0)
+ .map(drop)
+ }
}
/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
///
/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
pub fn attach(pid: Pid) -> Result<()> {
- unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
+ unsafe {
+ ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop)
+ }
}
/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
@@ -114,13 +120,14 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
};
unsafe {
// Ignore the useless return value
- ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data).map(drop)
+ ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data)
+ .map(drop)
}
}
/// Issues a kill request as with `ptrace(PT_KILL, ...)`
///
-/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);`
+/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);`
pub fn kill(pid: Pid) -> Result<()> {
unsafe {
ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop)
@@ -149,21 +156,22 @@ pub fn kill(pid: Pid) -> Result<()> {
/// _ => {},
/// }
/// ```
-#[cfg(
- any(
- any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
- all(target_os = "openbsd", target_arch = "x86_64"),
- all(target_os = "netbsd",
- any(target_arch = "x86_64", target_arch = "powerpc")
- )
+#[cfg(any(
+ any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
+ all(target_os = "openbsd", target_arch = "x86_64"),
+ all(
+ target_os = "netbsd",
+ any(target_arch = "x86_64", target_arch = "powerpc")
)
-)]
+))]
pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
let data = match sig.into() {
Some(s) => s as c_int,
None => 0,
};
- unsafe { ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop) }
+ unsafe {
+ ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop)
+ }
}
/// Reads a word from a processes memory at the given address
diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs
index 1d9b241..9687e05 100644
--- a/src/sys/ptrace/linux.rs
+++ b/src/sys/ptrace/linux.rs
@@ -1,20 +1,24 @@
//! For detailed description of the ptrace requests, consult `man ptrace`.
-use cfg_if::cfg_if;
-use std::{mem, ptr};
-use crate::Result;
use crate::errno::Errno;
-use libc::{self, c_void, c_long, siginfo_t};
-use crate::unistd::Pid;
use crate::sys::signal::Signal;
+use crate::unistd::Pid;
+use crate::Result;
+use cfg_if::cfg_if;
+use libc::{self, c_long, c_void, siginfo_t};
+use std::{mem, ptr};
pub type AddressType = *mut ::libc::c_void;
#[cfg(all(
target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
+ any(
+ all(
+ target_arch = "x86_64",
+ any(target_env = "gnu", target_env = "musl")
+ ),
+ all(target_arch = "x86", target_env = "gnu")
+ )
))]
use libc::user_regs_struct;
@@ -30,7 +34,7 @@ cfg_if! {
}
}
-libc_enum!{
+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))]
/// Ptrace Request enum defining the action to be taken.
@@ -120,7 +124,7 @@ libc_enum!{
}
}
-libc_enum!{
+libc_enum! {
#[repr(i32)]
/// Using the ptrace options the tracer can configure the tracee to stop
/// at certain events. This enum is used to define those events as defined
@@ -178,7 +182,12 @@ libc_bitflags! {
}
}
-fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
+fn ptrace_peek(
+ request: Request,
+ pid: Pid,
+ addr: AddressType,
+ data: *mut c_void,
+) -> Result<c_long> {
let ret = unsafe {
Errno::clear();
libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
@@ -192,9 +201,13 @@ fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void)
/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
#[cfg(all(
target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
+ any(
+ all(
+ target_arch = "x86_64",
+ any(target_env = "gnu", target_env = "musl")
+ ),
+ all(target_arch = "x86", target_env = "gnu")
+ )
))]
pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
@@ -203,16 +216,22 @@ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
#[cfg(all(
target_os = "linux",
- any(all(target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")),
- all(target_arch = "x86", target_env = "gnu"))
+ any(
+ all(
+ target_arch = "x86_64",
+ any(target_env = "gnu", target_env = "musl")
+ ),
+ all(target_arch = "x86", target_env = "gnu")
+ )
))]
pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
let res = unsafe {
- libc::ptrace(Request::PTRACE_SETREGS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- &regs as *const _ as *const c_void)
+ libc::ptrace(
+ Request::PTRACE_SETREGS as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<c_void>(),
+ &regs as *const _ as *const c_void,
+ )
};
Errno::result(res).map(drop)
}
@@ -224,26 +243,41 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
let mut data = mem::MaybeUninit::uninit();
let res = unsafe {
- libc::ptrace(request as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<T>(),
- data.as_mut_ptr() as *const _ as *const c_void)
+ libc::ptrace(
+ request as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<T>(),
+ data.as_mut_ptr() as *const _ as *const c_void,
+ )
};
Errno::result(res)?;
- Ok(unsafe{ data.assume_init() })
+ Ok(unsafe { data.assume_init() })
}
-unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
- Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
+unsafe fn ptrace_other(
+ request: Request,
+ pid: Pid,
+ addr: AddressType,
+ data: *mut c_void,
+) -> Result<c_long> {
+ Errno::result(libc::ptrace(
+ request as RequestType,
+ libc::pid_t::from(pid),
+ addr,
+ data,
+ ))
+ .map(|_| 0)
}
/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
let res = unsafe {
- libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- options.bits() as *mut c_void)
+ libc::ptrace(
+ Request::PTRACE_SETOPTIONS as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<c_void>(),
+ options.bits() as *mut c_void,
+ )
};
Errno::result(res).map(drop)
}
@@ -260,12 +294,14 @@ pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
- let ret = unsafe{
+ let ret = unsafe {
Errno::clear();
- libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- sig as *const _ as *const c_void)
+ libc::ptrace(
+ Request::PTRACE_SETSIGINFO as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<c_void>(),
+ sig as *const _ as *const c_void,
+ )
};
match Errno::result(ret) {
Ok(_) => Ok(()),
@@ -284,7 +320,8 @@ pub fn traceme() -> Result<()> {
Pid::from_raw(0),
ptr::null_mut(),
ptr::null_mut(),
- ).map(drop) // ignore the useless return value
+ )
+ .map(drop) // ignore the useless return value
}
}
@@ -298,12 +335,8 @@ pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(
- Request::PTRACE_SYSCALL,
- pid,
- ptr::null_mut(),
- data,
- ).map(drop) // ignore the useless return value
+ ptrace_other(Request::PTRACE_SYSCALL, pid, ptr::null_mut(), data)
+ .map(drop) // ignore the useless return value
}
}
@@ -312,14 +345,19 @@ pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
/// Thus the the tracee will only be stopped once per syscall,
/// optionally delivering a signal specified by `sig`.
-#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
+#[cfg(all(
+ target_os = "linux",
+ target_env = "gnu",
+ any(target_arch = "x86", target_arch = "x86_64")
+))]
pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
let data = match sig.into() {
Some(s) => s as i32 as *mut c_void,
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
+ ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data)
+ .map(drop)
// ignore the useless return value
}
}
@@ -334,7 +372,8 @@ pub fn attach(pid: Pid) -> Result<()> {
pid,
ptr::null_mut(),
ptr::null_mut(),
- ).map(drop) // ignore the useless return value
+ )
+ .map(drop) // ignore the useless return value
}
}
@@ -350,7 +389,8 @@ pub fn seize(pid: Pid, options: Options) -> Result<()> {
pid,
ptr::null_mut(),
options.bits() as *mut c_void,
- ).map(drop) // ignore the useless return value
+ )
+ .map(drop) // ignore the useless return value
}
}
@@ -364,12 +404,8 @@ pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(
- Request::PTRACE_DETACH,
- pid,
- ptr::null_mut(),
- data
- ).map(drop)
+ ptrace_other(Request::PTRACE_DETACH, pid, ptr::null_mut(), data)
+ .map(drop)
}
}
@@ -383,7 +419,8 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop) // ignore the useless return value
+ ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop)
+ // ignore the useless return value
}
}
@@ -394,7 +431,13 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn interrupt(pid: Pid) -> Result<()> {
unsafe {
- ptrace_other(Request::PTRACE_INTERRUPT, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
+ ptrace_other(
+ Request::PTRACE_INTERRUPT,
+ pid,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ )
+ .map(drop)
}
}
@@ -403,7 +446,13 @@ pub fn interrupt(pid: Pid) -> Result<()> {
/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
pub fn kill(pid: Pid) -> Result<()> {
unsafe {
- ptrace_other(Request::PTRACE_KILL, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
+ ptrace_other(
+ Request::PTRACE_KILL,
+ pid,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ )
+ .map(drop)
}
}
@@ -436,7 +485,8 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(drop)
+ ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data)
+ .map(drop)
}
}
@@ -446,7 +496,11 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
/// Advances the execution by a single step or until the next syscall.
/// In case the tracee is stopped at a syscall, the syscall will not be executed.
/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
-#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
+#[cfg(all(
+ target_os = "linux",
+ target_env = "gnu",
+ any(target_arch = "x86", target_arch = "x86_64")
+))]
pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
let data = match sig.into() {
Some(s) => s as i32 as *mut c_void,
@@ -477,8 +531,8 @@ pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
pub unsafe fn write(
pid: Pid,
addr: AddressType,
- data: *mut c_void) -> Result<()>
-{
+ data: *mut c_void,
+) -> Result<()> {
ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
}
@@ -498,7 +552,7 @@ pub fn read_user(pid: Pid, offset: AddressType) -> Result<c_long> {
pub unsafe fn write_user(
pid: Pid,
offset: AddressType,
- data: *mut c_void) -> Result<()>
-{
+ data: *mut c_void,
+) -> Result<()> {
ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop)
}
diff --git a/src/sys/ptrace/mod.rs b/src/sys/ptrace/mod.rs
index 782c304..2b121c0 100644
--- a/src/sys/ptrace/mod.rs
+++ b/src/sys/ptrace/mod.rs
@@ -1,4 +1,4 @@
-///! Provides helpers for making ptrace system calls
+///! Provides helpers for making ptrace system calls
#[cfg(any(target_os = "android", target_os = "linux"))]
mod linux;
@@ -6,17 +6,20 @@ mod linux;
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use self::linux::*;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
mod bsd;
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
pub use self::bsd::*;
diff --git a/src/sys/quota.rs b/src/sys/quota.rs
index f3b4c02..b3c44ca 100644
--- a/src/sys/quota.rs
+++ b/src/sys/quota.rs
@@ -12,11 +12,11 @@
//! dqblk.set_blocks_soft_limit(8000);
//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS).unwrap();
//! ```
+use crate::errno::Errno;
+use crate::{NixPath, Result};
+use libc::{self, c_char, c_int};
use std::default::Default;
use std::{mem, ptr};
-use libc::{self, c_int, c_char};
-use crate::{Result, NixPath};
-use crate::errno::Errno;
struct QuotaCmd(QuotaSubCmd, QuotaType);
@@ -28,7 +28,7 @@ impl QuotaCmd {
}
// linux quota version >= 2
-libc_enum!{
+libc_enum! {
#[repr(i32)]
enum QuotaSubCmd {
Q_SYNC,
@@ -39,7 +39,7 @@ libc_enum!{
}
}
-libc_enum!{
+libc_enum! {
/// The scope of the quota.
#[repr(i32)]
#[non_exhaustive]
@@ -51,7 +51,7 @@ libc_enum!{
}
}
-libc_enum!{
+libc_enum! {
/// The type of quota format to use.
#[repr(i32)]
#[non_exhaustive]
@@ -120,7 +120,8 @@ impl Default for Dqblk {
impl Dqblk {
/// The absolute limit on disk quota blocks allocated.
pub fn blocks_hard_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
Some(self.0.dqb_bhardlimit)
} else {
@@ -135,7 +136,8 @@ impl Dqblk {
/// Preferred limit on disk quota blocks
pub fn blocks_soft_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
Some(self.0.dqb_bsoftlimit)
} else {
@@ -150,7 +152,8 @@ impl Dqblk {
/// Current occupied space (bytes).
pub fn occupied_space(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_SPACE) {
Some(self.0.dqb_curspace)
} else {
@@ -160,7 +163,8 @@ impl Dqblk {
/// Maximum number of allocated inodes.
pub fn inodes_hard_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
Some(self.0.dqb_ihardlimit)
} else {
@@ -175,7 +179,8 @@ impl Dqblk {
/// Preferred inode limit
pub fn inodes_soft_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
Some(self.0.dqb_isoftlimit)
} else {
@@ -190,7 +195,8 @@ impl Dqblk {
/// Current number of allocated inodes.
pub fn allocated_inodes(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_INODES) {
Some(self.0.dqb_curinodes)
} else {
@@ -200,7 +206,8 @@ impl Dqblk {
/// Time limit for excessive disk use.
pub fn block_time_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_BTIME) {
Some(self.0.dqb_btime)
} else {
@@ -215,7 +222,8 @@ impl Dqblk {
/// Time limit for excessive files.
pub fn inode_time_limit(&self) -> Option<u64> {
- let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ let valid_fields =
+ QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
if valid_fields.contains(QuotaValidFlags::QIF_ITIME) {
Some(self.0.dqb_itime)
} else {
@@ -229,11 +237,18 @@ impl Dqblk {
}
}
-fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
+fn quotactl<P: ?Sized + NixPath>(
+ cmd: QuotaCmd,
+ special: Option<&P>,
+ id: c_int,
+ addr: *mut c_char,
+) -> Result<()> {
unsafe {
Errno::clear();
let res = match special {
- Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)),
+ Some(dev) => dev.with_nix_path(|path| {
+ libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)
+ }),
None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)),
}?;
@@ -242,36 +257,82 @@ fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int,
}
/// Turn on disk quotas for a block device.
-pub fn quotactl_on<P: ?Sized + NixPath>(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> {
+pub fn quotactl_on<P: ?Sized + NixPath>(
+ which: QuotaType,
+ special: &P,
+ format: QuotaFmt,
+ quota_file: &P,
+) -> Result<()> {
quota_file.with_nix_path(|path| {
let mut path_copy = path.to_bytes_with_nul().to_owned();
let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
- quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p)
+ quotactl(
+ QuotaCmd(QuotaSubCmd::Q_QUOTAON, which),
+ Some(special),
+ format as c_int,
+ p,
+ )
})?
}
/// Disable disk quotas for a block device.
-pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Result<()> {
- quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
+pub fn quotactl_off<P: ?Sized + NixPath>(
+ which: QuotaType,
+ special: &P,
+) -> Result<()> {
+ quotactl(
+ QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which),
+ Some(special),
+ 0,
+ ptr::null_mut(),
+ )
}
/// Update the on-disk copy of quota usages for a filesystem.
///
/// If `special` is `None`, then all file systems with active quotas are sync'd.
-pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
- quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
+pub fn quotactl_sync<P: ?Sized + NixPath>(
+ which: QuotaType,
+ special: Option<&P>,
+) -> Result<()> {
+ quotactl(
+ QuotaCmd(QuotaSubCmd::Q_SYNC, which),
+ special,
+ 0,
+ ptr::null_mut(),
+ )
}
/// Get disk quota limits and current usage for the given user/group id.
-pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
+pub fn quotactl_get<P: ?Sized + NixPath>(
+ which: QuotaType,
+ special: &P,
+ id: c_int,
+) -> Result<Dqblk> {
let mut dqblk = mem::MaybeUninit::uninit();
- quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?;
- Ok(unsafe{ Dqblk(dqblk.assume_init())})
+ quotactl(
+ QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which),
+ Some(special),
+ id,
+ dqblk.as_mut_ptr() as *mut c_char,
+ )?;
+ Ok(unsafe { Dqblk(dqblk.assume_init()) })
}
/// Configure quota values for the specified fields for a given user/group id.
-pub fn quotactl_set<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> {
+pub fn quotactl_set<P: ?Sized + NixPath>(
+ which: QuotaType,
+ special: &P,
+ id: c_int,
+ dqblk: &Dqblk,
+ fields: QuotaValidFlags,
+) -> Result<()> {
let mut dqblk_copy = *dqblk;
dqblk_copy.0.dqb_valid = fields.bits();
- quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
+ quotactl(
+ QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which),
+ Some(special),
+ id,
+ &mut dqblk_copy as *mut _ as *mut c_char,
+ )
}
diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs
index 2a8009e..02d9816 100644
--- a/src/sys/reboot.rs
+++ b/src/sys/reboot.rs
@@ -1,7 +1,7 @@
//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
use std::convert::Infallible;
use std::mem::drop;
@@ -30,9 +30,7 @@ libc_enum! {
/// Reboots or shuts down the system.
pub fn reboot(how: RebootMode) -> Result<Infallible> {
- unsafe {
- libc::reboot(how as libc::c_int)
- };
+ unsafe { libc::reboot(how as libc::c_int) };
Err(Errno::last())
}
@@ -45,8 +43,6 @@ pub fn set_cad_enabled(enable: bool) -> Result<()> {
} else {
libc::RB_DISABLE_CAD
};
- let res = unsafe {
- libc::reboot(cmd)
- };
+ let res = unsafe { libc::reboot(cmd) };
Errno::result(res).map(drop)
}
diff --git a/src/sys/resource.rs b/src/sys/resource.rs
index e9a11d9..8927737 100644
--- a/src/sys/resource.rs
+++ b/src/sys/resource.rs
@@ -6,6 +6,7 @@ use crate::errno::Errno;
use crate::sys::time::TimeVal;
use crate::Result;
pub use libc::rlim_t;
+pub use libc::RLIM_INFINITY;
use std::mem;
cfg_if! {
@@ -175,7 +176,7 @@ libc_enum! {
/// Get the current processes resource limits
///
-/// The special value `RLIM_INFINITY` indicates that no limit will be
+/// The special value [`RLIM_INFINITY`] indicates that no limit will be
/// enforced.
///
/// # Parameters
@@ -224,7 +225,7 @@ pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
/// the current hard limit for non-root users.
///
-/// The special value `RLIM_INFINITY` indicates that no limit will be
+/// The special value [`RLIM_INFINITY`] indicates that no limit will be
/// enforced.
///
/// # Examples
@@ -244,7 +245,11 @@ pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
/// [`Resource`]: enum.Resource.html
///
/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
-pub fn setrlimit(resource: Resource, soft_limit: rlim_t, hard_limit: rlim_t) -> Result<()> {
+pub fn setrlimit(
+ resource: Resource,
+ soft_limit: rlim_t,
+ hard_limit: rlim_t,
+) -> Result<()> {
let new_rlim = rlimit {
rlim_cur: soft_limit,
rlim_max: hard_limit,
@@ -426,7 +431,8 @@ mod test {
// thing away. Replace the assert with test::black_box once stabilized.
assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100);
- let usage = getrusage(UsageWho::RUSAGE_SELF).expect("Failed to call getrusage for SELF");
+ let usage = getrusage(UsageWho::RUSAGE_SELF)
+ .expect("Failed to call getrusage for SELF");
let rusage = usage.as_ref();
let user = usage.user_time();
diff --git a/src/sys/select.rs b/src/sys/select.rs
index ab4f68f..7a94cff 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -1,14 +1,14 @@
//! Portably monitor a group of file descriptors for readiness.
+use crate::errno::Errno;
+use crate::sys::time::{TimeSpec, TimeVal};
+use crate::Result;
+use libc::{self, c_int};
use std::convert::TryFrom;
use std::iter::FusedIterator;
use std::mem;
use std::ops::Range;
use std::os::unix::io::RawFd;
use std::ptr::{null, null_mut};
-use libc::{self, c_int};
-use crate::Result;
-use crate::errno::Errno;
-use crate::sys::time::{TimeSpec, TimeVal};
pub use libc::FD_SETSIZE;
@@ -173,11 +173,13 @@ impl<'a> FusedIterator for Fds<'a> {}
/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
///
/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-pub fn select<'a, N, R, W, E, T>(nfds: N,
+pub fn select<'a, N, R, W, E, T>(
+ nfds: N,
readfds: R,
writefds: W,
errorfds: E,
- timeout: T) -> Result<c_int>
+ timeout: T,
+) -> Result<c_int>
where
N: Into<Option<c_int>>,
R: Into<Option<&'a mut FdSet>>,
@@ -191,23 +193,31 @@ where
let timeout = timeout.into();
let nfds = nfds.into().unwrap_or_else(|| {
- readfds.iter_mut()
+ readfds
+ .iter_mut()
.chain(writefds.iter_mut())
.chain(errorfds.iter_mut())
.map(|set| set.highest().unwrap_or(-1))
.max()
- .unwrap_or(-1) + 1
+ .unwrap_or(-1)
+ + 1
});
- let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
+ let readfds = readfds
+ .map(|set| set as *mut _ as *mut libc::fd_set)
+ .unwrap_or(null_mut());
+ let writefds = writefds
+ .map(|set| set as *mut _ as *mut libc::fd_set)
+ .unwrap_or(null_mut());
+ let errorfds = errorfds
+ .map(|set| set as *mut _ as *mut libc::fd_set)
+ .unwrap_or(null_mut());
+ let timeout = timeout
+ .map(|tv| tv as *mut _ as *mut libc::timeval)
.unwrap_or(null_mut());
- let res = unsafe {
- libc::select(nfds, readfds, writefds, errorfds, timeout)
- };
+ let res =
+ unsafe { libc::select(nfds, readfds, writefds, errorfds, timeout) };
Errno::result(res)
}
@@ -292,9 +302,9 @@ where
#[cfg(test)]
mod tests {
use super::*;
- use std::os::unix::io::RawFd;
use crate::sys::time::{TimeVal, TimeValLike};
- use crate::unistd::{write, pipe};
+ use crate::unistd::{pipe, write};
+ use std::os::unix::io::RawFd;
#[test]
fn fdset_insert() {
@@ -383,11 +393,10 @@ mod tests {
fd_set.insert(r2);
let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(None,
- &mut fd_set,
- None,
- None,
- &mut timeout).unwrap());
+ assert_eq!(
+ 1,
+ select(None, &mut fd_set, None, None, &mut timeout).unwrap()
+ );
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
}
@@ -403,11 +412,17 @@ mod tests {
fd_set.insert(r2);
let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
+ assert_eq!(
+ 1,
+ select(
+ Some(fd_set.highest().unwrap() + 1),
&mut fd_set,
None,
None,
- &mut timeout).unwrap());
+ &mut timeout
+ )
+ .unwrap()
+ );
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
}
@@ -423,11 +438,17 @@ mod tests {
fd_set.insert(r2);
let mut timeout = TimeVal::seconds(10);
- assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
+ assert_eq!(
+ 1,
+ select(
+ ::std::cmp::max(r1, r2) + 1,
&mut fd_set,
None,
None,
- &mut timeout).unwrap());
+ &mut timeout
+ )
+ .unwrap()
+ );
assert!(fd_set.contains(r1));
assert!(!fd_set.contains(r2));
}
diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs
index 2ebcdf4..fb293a4 100644
--- a/src/sys/sendfile.rs
+++ b/src/sys/sendfile.rs
@@ -6,8 +6,8 @@ use std::ptr;
use libc::{self, off_t};
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
///
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 0da9c74..d3746e6 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -475,7 +475,7 @@ pub struct SigSet {
impl SigSet {
/// Initialize to include all signals.
- #[cfg_attr(has_doc_alias, doc(alias("sigfillset")))]
+ #[doc(alias("sigfillset"))]
pub fn all() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
@@ -484,7 +484,7 @@ impl SigSet {
}
/// Initialize to include nothing.
- #[cfg_attr(has_doc_alias, doc(alias("sigemptyset")))]
+ #[doc(alias("sigemptyset"))]
pub fn empty() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
@@ -493,25 +493,25 @@ impl SigSet {
}
/// Add the specified signal to the set.
- #[cfg_attr(has_doc_alias, doc(alias("sigaddset")))]
+ #[doc(alias("sigaddset"))]
pub fn add(&mut self, signal: Signal) {
unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
/// Remove all signals from this set.
- #[cfg_attr(has_doc_alias, doc(alias("sigemptyset")))]
+ #[doc(alias("sigemptyset"))]
pub fn clear(&mut self) {
unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
}
/// Remove the specified signal from this set.
- #[cfg_attr(has_doc_alias, doc(alias("sigdelset")))]
+ #[doc(alias("sigdelset"))]
pub fn remove(&mut self, signal: Signal) {
unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
/// Return whether this set includes the specified signal.
- #[cfg_attr(has_doc_alias, doc(alias("sigismember")))]
+ #[doc(alias("sigismember"))]
pub fn contains(&self, signal: Signal) -> bool {
let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
@@ -911,10 +911,11 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si
/// # Arguments
///
/// * `pid` - Specifies which processes should receive the signal.
-/// - If positive, specifies an individual process
+/// - If positive, specifies an individual process.
/// - If zero, the signal will be sent to all processes whose group
/// ID is equal to the process group ID of the sender. This is a
-/// variant of [`killpg`].
+#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
+#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
/// - If `-1` and the process has super-user privileges, the signal
/// is sent to all processes exclusing system processes.
/// - If less than `-1`, the signal is sent to all processes whose
diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs
index 166bb9d..095e590 100644
--- a/src/sys/signalfd.rs
+++ b/src/sys/signalfd.rs
@@ -15,17 +15,16 @@
//!
//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
//! signal handlers.
-use crate::unistd;
-use crate::Result;
use crate::errno::Errno;
pub use crate::sys::signal::{self, SigSet};
+use crate::unistd;
+use crate::Result;
pub use libc::signalfd_siginfo as siginfo;
-use std::os::unix::io::{RawFd, AsRawFd};
use std::mem;
+use std::os::unix::io::{AsRawFd, RawFd};
-
-libc_bitflags!{
+libc_bitflags! {
pub struct SfdFlags: libc::c_int {
SFD_NONBLOCK;
SFD_CLOEXEC;
@@ -49,7 +48,11 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
unsafe {
- Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits()))
+ Errno::result(libc::signalfd(
+ fd as libc::c_int,
+ mask.as_ref(),
+ flags.bits(),
+ ))
}
}
@@ -103,12 +106,13 @@ impl SignalFd {
let size = mem::size_of_val(&buffer);
let res = Errno::result(unsafe {
libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size)
- }).map(|r| r as usize);
+ })
+ .map(|r| r as usize);
match res {
Ok(x) if x == size => Ok(Some(unsafe { buffer.assume_init() })),
Ok(_) => unreachable!("partial read on signalfd"),
Err(Errno::EAGAIN) => Ok(None),
- Err(error) => Err(error)
+ Err(error) => Err(error),
}
}
}
@@ -139,7 +143,6 @@ impl Iterator for SignalFd {
}
}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -163,7 +166,8 @@ mod tests {
#[test]
fn read_empty_signalfd() {
let mask = SigSet::empty();
- let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
+ let mut fd =
+ SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
let res = fd.read_signal();
assert!(res.unwrap().is_none());
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index ad917cd..8b23b10 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -1,55 +1,61 @@
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "haiku",
+ target_os = "fuchsia"
+))]
+#[cfg(feature = "net")]
+pub use self::datalink::LinkAddr;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use self::vsock::VsockAddr;
use super::sa_family_t;
-use cfg_if::cfg_if;
-use crate::{Result, NixPath};
use crate::errno::Errno;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::sys::socket::addr::alg::AlgAddr;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::sys::socket::addr::netlink::NetlinkAddr;
+#[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+))]
+use crate::sys::socket::addr::sys_control::SysControlAddr;
+use crate::{NixPath, Result};
+use cfg_if::cfg_if;
use memoffset::offset_of;
-use std::{fmt, mem, net, ptr, slice};
use std::convert::TryInto;
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
-use std::path::Path;
use std::os::unix::ffi::OsStrExt;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::alg::AlgAddr;
#[cfg(any(target_os = "ios", target_os = "macos"))]
use std::os::unix::io::RawFd;
-#[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
-use crate::sys::socket::addr::sys_control::SysControlAddr;
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "haiku",
- target_os = "fuchsia"))]
-#[cfg(feature = "net")]
-pub use self::datalink::LinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::vsock::VsockAddr;
+use std::path::Path;
+use std::{fmt, mem, net, ptr, slice};
/// Convert a std::net::Ipv4Addr into the libc form.
#[cfg(feature = "net")]
-pub(crate) fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
- let octets = addr.octets();
- libc::in_addr {
- s_addr: u32::to_be(((octets[0] as u32) << 24) |
- ((octets[1] as u32) << 16) |
- ((octets[2] as u32) << 8) |
- (octets[3] as u32))
+pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
+ static_assertions::assert_eq_size!(net::Ipv4Addr, libc::in_addr);
+ // Safe because both types have the same memory layout, and no fancy Drop
+ // impls.
+ unsafe {
+ mem::transmute(addr)
}
}
/// Convert a std::net::Ipv6Addr into the libc form.
#[cfg(feature = "net")]
pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
- libc::in6_addr {
- s6_addr: addr.octets()
+ static_assertions::assert_eq_size!(net::Ipv6Addr, libc::in6_addr);
+ // Safe because both are Newtype wrappers around the same libc type
+ unsafe {
+ mem::transmute(*addr)
}
}
@@ -75,11 +81,13 @@ pub enum AddressFamily {
#[cfg_attr(docsrs, doc(cfg(all())))]
Netlink = libc::AF_NETLINK,
/// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
- #[cfg(any(target_os = "android",
- target_os = "linux",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "solaris"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "illumos",
+ target_os = "fuchsia",
+ target_os = "solaris"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Packet = libc::AF_PACKET,
/// KEXT Controls and Notifications
@@ -136,7 +144,7 @@ pub enum AddressFamily {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Key = libc::AF_KEY,
- #[allow(missing_docs)] // Not documented anywhere that I can find
+ #[allow(missing_docs)] // Not documented anywhere that I can find
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ash = libc::AF_ASH,
@@ -172,7 +180,7 @@ pub enum AddressFamily {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Llc = libc::AF_LLC,
- /// InfiniBand native addressing
+ /// InfiniBand native addressing
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ib = libc::AF_IB,
@@ -189,10 +197,12 @@ pub enum AddressFamily {
#[cfg_attr(docsrs, doc(cfg(all())))]
Tipc = libc::AF_TIPC,
/// Bluetooth low-level socket protocol
- #[cfg(not(any(target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "solaris")))]
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "solaris"
+ )))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Bluetooth = libc::AF_BLUETOOTH,
/// IUCV (inter-user communication vehicle) z/VM protocol for
@@ -205,7 +215,11 @@ pub enum AddressFamily {
#[cfg_attr(docsrs, doc(cfg(all())))]
RxRpc = libc::AF_RXRPC,
/// New "modular ISDN" driver interface protocol
- #[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))]
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "solaris",
+ target_os = "haiku"
+ )))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Isdn = libc::AF_ISDN,
/// Nokia cellular modem IPC/RPC interface
@@ -234,128 +248,156 @@ pub enum AddressFamily {
#[cfg_attr(docsrs, doc(cfg(all())))]
Vsock = libc::AF_VSOCK,
/// ARPANet IMP addresses
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
ImpLink = libc::AF_IMPLINK,
/// PUP protocols, e.g. BSP
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Pup = libc::AF_PUP,
/// MIT CHAOS protocols
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Chaos = libc::AF_CHAOS,
/// Novell and Xerox protocol
- #[cfg(any(target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ns = libc::AF_NS,
- #[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[allow(missing_docs)] // Not documented anywhere that I can find
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Iso = libc::AF_ISO,
/// Bell Labs virtual circuit switch ?
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Datakit = libc::AF_DATAKIT,
/// CCITT protocols, X.25 etc
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ccitt = libc::AF_CCITT,
/// DEC Direct data link interface
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Dli = libc::AF_DLI,
- #[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[allow(missing_docs)] // Not documented anywhere that I can find
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Lat = libc::AF_LAT,
/// NSC Hyperchannel
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Hylink = libc::AF_HYLINK,
/// Link layer interface
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Link = libc::AF_LINK,
/// connection-oriented IP, aka ST II
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Coip = libc::AF_COIP,
/// Computer Network Technology
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Cnt = libc::AF_CNT,
/// Native ATM access
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Natm = libc::AF_NATM,
/// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
@@ -381,17 +423,19 @@ impl AddressFamily {
libc::AF_SYSTEM => Some(AddressFamily::System),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_PACKET => Some(AddressFamily::Packet),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd"
+ ))]
libc::AF_LINK => Some(AddressFamily::Link),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_VSOCK => Some(AddressFamily::Vsock),
- _ => None
+ _ => None,
}
}
}
@@ -707,12 +751,13 @@ pub struct UnixAddr {
/// The length of the valid part of `sun`, including the sun_family field
/// but excluding any trailing nul.
// On the BSDs, this field is built into sun
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
))]
- sun_len: u8
+ sun_len: u8,
}
// linux man page unix(7) says there are 3 kinds of unix socket:
@@ -732,17 +777,21 @@ impl<'a> UnixAddrKind<'a> {
/// Safety: sun & sun_len must be valid
unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
- let path_len = sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
+ let path_len =
+ sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
if path_len == 0 {
return Self::Unnamed;
}
#[cfg(any(target_os = "android", target_os = "linux"))]
if sun.sun_path[0] == 0 {
- let name =
- slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
+ let name = slice::from_raw_parts(
+ sun.sun_path.as_ptr().add(1) as *const u8,
+ path_len - 1,
+ );
return Self::Abstract(name);
}
- let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
+ let pathname =
+ slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
if pathname.last() == Some(&0) {
// A trailing NUL is not considered part of the path, and it does
// not need to be included in the addrlen passed to functions like
@@ -751,7 +800,9 @@ impl<'a> UnixAddrKind<'a> {
// getsockname() (the BSDs do not do that). So we need to filter
// out any trailing NUL here, so sockaddrs can round-trip through
// the kernel and still compare equal.
- Self::Pathname(Path::new(OsStr::from_bytes(&pathname[0..pathname.len() - 1])))
+ Self::Pathname(Path::new(OsStr::from_bytes(
+ &pathname[0..pathname.len() - 1],
+ )))
} else {
Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
}
@@ -761,38 +812,41 @@ impl<'a> UnixAddrKind<'a> {
impl UnixAddr {
/// Create a new sockaddr_un representing a filesystem path.
pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
- path.with_nix_path(|cstr| {
- unsafe {
- let mut ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- .. mem::zeroed()
- };
-
- let bytes = cstr.to_bytes();
+ path.with_nix_path(|cstr| unsafe {
+ let mut ret = libc::sockaddr_un {
+ sun_family: AddressFamily::Unix as sa_family_t,
+ ..mem::zeroed()
+ };
- if bytes.len() >= ret.sun_path.len() {
- return Err(Errno::ENAMETOOLONG);
- }
+ let bytes = cstr.to_bytes();
- let sun_len = (bytes.len() +
- offset_of!(libc::sockaddr_un, sun_path)).try_into()
- .unwrap();
+ if bytes.len() >= ret.sun_path.len() {
+ return Err(Errno::ENAMETOOLONG);
+ }
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- {
- ret.sun_len = sun_len;
- }
- ptr::copy_nonoverlapping(bytes.as_ptr(),
- ret.sun_path.as_mut_ptr() as *mut u8,
- bytes.len());
+ let sun_len = (bytes.len()
+ + offset_of!(libc::sockaddr_un, sun_path))
+ .try_into()
+ .unwrap();
- Ok(UnixAddr::from_raw_parts(ret, sun_len))
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
+ {
+ ret.sun_len = sun_len;
}
+ ptr::copy_nonoverlapping(
+ bytes.as_ptr(),
+ ret.sun_path.as_mut_ptr() as *mut u8,
+ bytes.len(),
+ );
+
+ Ok(UnixAddr::from_raw_parts(ret, sun_len))
})?
}
@@ -808,27 +862,43 @@ impl UnixAddr {
unsafe {
let mut ret = libc::sockaddr_un {
sun_family: AddressFamily::Unix as sa_family_t,
- .. mem::zeroed()
+ ..mem::zeroed()
};
if path.len() >= ret.sun_path.len() {
return Err(Errno::ENAMETOOLONG);
}
- let sun_len = (path.len() +
- 1 +
- offset_of!(libc::sockaddr_un, sun_path)).try_into()
- .unwrap();
+ let sun_len =
+ (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
+ .try_into()
+ .unwrap();
// Abstract addresses are represented by sun_path[0] ==
// b'\0', so copy starting one byte in.
- ptr::copy_nonoverlapping(path.as_ptr(),
- ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
- path.len());
+ ptr::copy_nonoverlapping(
+ path.as_ptr(),
+ ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
+ path.len(),
+ );
Ok(UnixAddr::from_raw_parts(ret, sun_len))
}
}
+ /// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ pub fn new_unnamed() -> UnixAddr {
+ let ret = libc::sockaddr_un {
+ sun_family: AddressFamily::Unix as sa_family_t,
+ .. unsafe { mem::zeroed() }
+ };
+
+ let sun_len: u8 = offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
+
+ unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
+ }
+
/// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len`
/// is the size of the valid portion of the struct, excluding any trailing
/// NUL.
@@ -840,8 +910,11 @@ impl UnixAddr {
/// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path)
/// - if this is a unix addr with a pathname, sun.sun_path is a
/// fs path, not necessarily nul-terminated.
- pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, sun_len: u8) -> UnixAddr {
- cfg_if!{
+ pub(crate) unsafe fn from_raw_parts(
+ sun: libc::sockaddr_un,
+ sun_len: u8,
+ ) -> UnixAddr {
+ cfg_if! {
if #[cfg(any(target_os = "android",
target_os = "fuchsia",
target_os = "illumos",
@@ -882,6 +955,14 @@ impl UnixAddr {
}
}
+ /// Check if this address is an "unnamed" unix socket address.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[inline]
+ pub fn is_unnamed(&self) -> bool {
+ matches!(self.kind(), UnixAddrKind::Unnamed)
+ }
+
/// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
#[inline]
pub fn path_len(&self) -> usize {
@@ -898,8 +979,8 @@ impl UnixAddr {
&mut self.sun
}
- fn sun_len(&self)-> u8 {
- cfg_if!{
+ fn sun_len(&self) -> u8 {
+ cfg_if! {
if #[cfg(any(target_os = "android",
target_os = "fuchsia",
target_os = "illumos",
@@ -916,31 +997,36 @@ impl UnixAddr {
impl private::SockaddrLikePriv for UnixAddr {}
impl SockaddrLike for UnixAddr {
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
))]
fn len(&self) -> libc::socklen_t {
self.sun_len.into()
}
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = len {
- if (l as usize) < offset_of!(libc::sockaddr_un, sun_path) ||
- l > u8::MAX as libc::socklen_t
+ if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
+ || l > u8::MAX as libc::socklen_t
{
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_UNIX as i32 {
+ if (*addr).sa_family as i32 != libc::AF_UNIX {
return None;
}
let mut su: libc::sockaddr_un = mem::zeroed();
let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
- cfg_if!{
+ cfg_if! {
if #[cfg(any(target_os = "android",
target_os = "fuchsia",
target_os = "illumos",
@@ -957,7 +1043,10 @@ impl SockaddrLike for UnixAddr {
Some(Self::from_raw_parts(su, su_len as u8))
}
- fn size() -> libc::socklen_t where Self: Sized {
+ fn size() -> libc::socklen_t
+ where
+ Self: Sized,
+ {
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
}
}
@@ -1037,8 +1126,12 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
///
/// `addr` must be valid for the specific type of sockaddr. `len`, if
/// present, must not exceed the length of valid data in `addr`.
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized;
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized;
/// Return the address family of this socket
///
@@ -1058,11 +1151,9 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
fn family(&self) -> Option<AddressFamily> {
// Safe since all implementors have a sa_family field at the same
// address, and they're all repr(C)
- AddressFamily::from_i32(
- unsafe {
- (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
- }
- )
+ AddressFamily::from_i32(unsafe {
+ (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
+ })
}
cfg_if! {
@@ -1101,7 +1192,10 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
}
/// Return the available space in the structure
- fn size() -> libc::socklen_t where Self: Sized {
+ fn size() -> libc::socklen_t
+ where
+ Self: Sized,
+ {
mem::size_of::<Self>() as libc::socklen_t
}
}
@@ -1121,8 +1215,12 @@ impl SockaddrLike for () {
ptr::null()
}
- unsafe fn from_raw(_: *const libc::sockaddr, _: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ _: *const libc::sockaddr,
+ _: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
None
}
@@ -1156,20 +1254,22 @@ impl SockaddrIn {
/// Creates a new socket address from IPv4 octets and a port number.
pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
Self(libc::sockaddr_in {
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "haiku",
+ target_os = "openbsd"
+ ))]
sin_len: Self::size() as u8,
sin_family: AddressFamily::Inet as sa_family_t,
sin_port: u16::to_be(port),
sin_addr: libc::in_addr {
- s_addr: u32::from_ne_bytes([a, b, c, d])
+ s_addr: u32::from_ne_bytes([a, b, c, d]),
},
- sin_zero: unsafe{mem::zeroed()}
+ sin_zero: unsafe { mem::zeroed() },
})
}
@@ -1184,15 +1284,19 @@ impl SockaddrIn {
impl private::SockaddrLikePriv for SockaddrIn {}
#[cfg(feature = "net")]
impl SockaddrLike for SockaddrIn {
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = len {
if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_INET as i32 {
+ if (*addr).sa_family as i32 != libc::AF_INET {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -1211,28 +1315,37 @@ impl fmt::Display for SockaddrIn {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ne = u32::from_be(self.0.sin_addr.s_addr);
let port = u16::from_be(self.0.sin_port);
- write!(f, "{}.{}.{}.{}:{}",
- ne >> 24,
- (ne >> 16) & 0xFF,
- (ne >> 8) & 0xFF,
- ne & 0xFF,
- port)
+ write!(
+ f,
+ "{}.{}.{}.{}:{}",
+ ne >> 24,
+ (ne >> 16) & 0xFF,
+ (ne >> 8) & 0xFF,
+ ne & 0xFF,
+ port
+ )
}
}
#[cfg(feature = "net")]
impl From<net::SocketAddrV4> for SockaddrIn {
fn from(addr: net::SocketAddrV4) -> Self {
- Self(libc::sockaddr_in{
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "haiku", target_os = "hermit",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
+ Self(libc::sockaddr_in {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "hermit",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: addr.port().to_be(), // network byte order
+ sin_port: addr.port().to_be(), // network byte order
sin_addr: ipv4addr_to_libc(*addr.ip()),
- .. unsafe { mem::zeroed() }
+ ..unsafe { mem::zeroed() }
})
}
}
@@ -1242,7 +1355,7 @@ impl From<SockaddrIn> for net::SocketAddrV4 {
fn from(addr: SockaddrIn) -> Self {
net::SocketAddrV4::new(
net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
- u16::from_be(addr.0.sin_port)
+ u16::from_be(addr.0.sin_port),
)
}
}
@@ -1290,15 +1403,19 @@ impl SockaddrIn6 {
impl private::SockaddrLikePriv for SockaddrIn6 {}
#[cfg(feature = "net")]
impl SockaddrLike for SockaddrIn6 {
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = len {
if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_INET6 as i32 {
+ if (*addr).sa_family as i32 != libc::AF_INET6 {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -1317,8 +1434,12 @@ impl fmt::Display for SockaddrIn6 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// These things are really hard to display properly. Easier to let std
// do it.
- let std = net::SocketAddrV6::new(self.ip(), self.port(),
- self.flowinfo(), self.scope_id());
+ let std = net::SocketAddrV6::new(
+ self.ip(),
+ self.port(),
+ self.flowinfo(),
+ self.scope_id(),
+ );
std.fmt(f)
}
}
@@ -1326,19 +1447,25 @@ impl fmt::Display for SockaddrIn6 {
#[cfg(feature = "net")]
impl From<net::SocketAddrV6> for SockaddrIn6 {
fn from(addr: net::SocketAddrV6) -> Self {
- #[allow(clippy::needless_update)] // It isn't needless on Illumos
- Self(libc::sockaddr_in6{
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "haiku", target_os = "hermit",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
+ #[allow(clippy::needless_update)] // It isn't needless on Illumos
+ Self(libc::sockaddr_in6 {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "hermit",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: addr.port().to_be(), // network byte order
+ sin6_port: addr.port().to_be(), // network byte order
sin6_addr: ipv6addr_to_libc(addr.ip()),
- sin6_flowinfo: addr.flowinfo(), // host byte order
- sin6_scope_id: addr.scope_id(), // host byte order
- .. unsafe { mem::zeroed() }
+ sin6_flowinfo: addr.flowinfo(), // host byte order
+ sin6_scope_id: addr.scope_id(), // host byte order
+ ..unsafe { mem::zeroed() }
})
}
}
@@ -1350,7 +1477,7 @@ impl From<SockaddrIn6> for net::SocketAddrV6 {
net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
u16::from_be(addr.0.sin6_port),
u32::from_be(addr.0.sin6_flowinfo),
- u32::from_be(addr.0.sin6_scope_id)
+ u32::from_be(addr.0.sin6_scope_id),
)
}
}
@@ -1364,7 +1491,6 @@ impl std::str::FromStr for SockaddrIn6 {
}
}
-
/// A container for any sockaddr type
///
/// Just like C's `sockaddr_storage`, this type is large enough to hold any type
@@ -1394,7 +1520,10 @@ pub union SockaddrStorage {
dl: LinkAddr,
#[cfg(any(target_os = "android", target_os = "linux"))]
nl: NetlinkAddr,
- #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
sctl: SysControlAddr,
#[cfg(feature = "net")]
@@ -1405,26 +1534,42 @@ pub union SockaddrStorage {
su: UnixAddr,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- vsock: VsockAddr
+ vsock: VsockAddr,
}
impl private::SockaddrLikePriv for SockaddrStorage {}
impl SockaddrLike for SockaddrStorage {
- unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ l: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if addr.is_null() {
return None;
}
if let Some(len) = l {
let ulen = len as usize;
- if ulen < offset_of!(libc::sockaddr, sa_data) ||
- ulen > mem::size_of::<libc::sockaddr_storage>() {
+ if ulen < offset_of!(libc::sockaddr, sa_data)
+ || ulen > mem::size_of::<libc::sockaddr_storage>()
+ {
None
- } else{
+ } else {
let mut ss: libc::sockaddr_storage = mem::zeroed();
let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
ptr::copy(addr as *const u8, ssp, len as usize);
- Some(Self{ss})
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))]
+ if i32::from(ss.ss_family) == libc::AF_UNIX {
+ // Safe because we UnixAddr is strictly smaller than
+ // SockaddrStorage, and we just initialized the structure.
+ (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
+ }
+ Some(Self { ss })
}
} else {
// If length is not available and addr is of a fixed-length type,
@@ -1432,46 +1577,74 @@ impl SockaddrLike for SockaddrStorage {
// available, then there's nothing we can do.
match (*addr).sa_family as i32 {
#[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => AlgAddr::from_raw(addr, l)
- .map(|alg| Self { alg}),
+ libc::AF_ALG => {
+ AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
+ }
#[cfg(feature = "net")]
- libc::AF_INET => SockaddrIn::from_raw(addr, l)
- .map(|sin| Self{ sin}),
+ libc::AF_INET => {
+ SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
+ }
#[cfg(feature = "net")]
- libc::AF_INET6 => SockaddrIn6::from_raw(addr, l)
- .map(|sin6| Self{ sin6}),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"))]
+ libc::AF_INET6 => {
+ SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
+ }
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "haiku",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
- libc::AF_LINK => LinkAddr::from_raw(addr, l)
- .map(|dl| Self{ dl}),
+ libc::AF_LINK => {
+ LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
+ }
#[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => NetlinkAddr::from_raw(addr, l)
- .map(|nl| Self{ nl }),
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
+ libc::AF_NETLINK => {
+ NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
+ }
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
))]
#[cfg(feature = "net")]
- libc::AF_PACKET => LinkAddr::from_raw(addr, l)
- .map(|dl| Self{ dl}),
- #[cfg(all(feature = "ioctl",
- any(target_os = "ios", target_os = "macos")))]
- libc::AF_SYSTEM => SysControlAddr::from_raw(addr, l)
- .map(|sctl| Self {sctl}),
+ libc::AF_PACKET => {
+ LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
+ }
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
+ libc::AF_SYSTEM => {
+ SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
+ }
#[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => VsockAddr::from_raw(addr, l)
- .map(|vsock| Self{vsock}),
- _ => None
+ libc::AF_VSOCK => {
+ VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
+ }
+ _ => None,
}
}
}
+
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))]
+ fn len(&self) -> libc::socklen_t {
+ match self.as_unix_addr() {
+ // The UnixAddr type knows its own length
+ Some(ua) => ua.len(),
+ // For all else, we're just a boring SockaddrStorage
+ None => mem::size_of_val(self) as libc::socklen_t
+ }
+ }
}
macro_rules! accessors {
@@ -1481,15 +1654,14 @@ macro_rules! accessors {
$sockty:ty,
$family:expr,
$libc_ty:ty,
- $field:ident) =>
- {
+ $field:ident) => {
/// Safely and falliably downcast to an immutable reference
pub fn $fname(&self) -> Option<&$sockty> {
- if self.family() == Some($family) &&
- self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
+ if self.family() == Some($family)
+ && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
{
// Safe because family and len are validated
- Some(unsafe{&self.$field})
+ Some(unsafe { &self.$field })
} else {
None
}
@@ -1497,66 +1669,128 @@ macro_rules! accessors {
/// Safely and falliably downcast to a mutable reference
pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
- if self.family() == Some($family) &&
- self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
+ if self.family() == Some($family)
+ && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
{
// Safe because family and len are validated
- Some(unsafe{&mut self.$field})
+ Some(unsafe { &mut self.$field })
} else {
None
}
}
- }
+ };
}
impl SockaddrStorage {
+ /// Downcast to an immutable `[UnixAddr]` reference.
+ pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
+ cfg_if! {
+ if #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))]
+ {
+ let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
+ // Safe because UnixAddr is strictly smaller than
+ // sockaddr_storage, and we're fully initialized
+ let len = unsafe {
+ (*(p as *const UnixAddr )).sun_len as usize
+ };
+ } else {
+ let len = self.len() as usize;
+ }
+ }
+ // Sanity checks
+ if self.family() != Some(AddressFamily::Unix) ||
+ len < offset_of!(libc::sockaddr_un, sun_path) ||
+ len > mem::size_of::<libc::sockaddr_un>() {
+ None
+ } else {
+ Some(unsafe{&self.su})
+ }
+ }
+
+ /// Downcast to a mutable `[UnixAddr]` reference.
+ pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
+ cfg_if! {
+ if #[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux"
+ ))]
+ {
+ let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
+ // Safe because UnixAddr is strictly smaller than
+ // sockaddr_storage, and we're fully initialized
+ let len = unsafe {
+ (*(p as *const UnixAddr )).sun_len as usize
+ };
+ } else {
+ let len = self.len() as usize;
+ }
+ }
+ // Sanity checks
+ if self.family() != Some(AddressFamily::Unix) ||
+ len < offset_of!(libc::sockaddr_un, sun_path) ||
+ len > mem::size_of::<libc::sockaddr_un>() {
+ None
+ } else {
+ Some(unsafe{&mut self.su})
+ }
+ }
+
#[cfg(any(target_os = "android", target_os = "linux"))]
- accessors!{as_alg_addr, as_alg_addr_mut, AlgAddr,
- AddressFamily::Alg, libc::sockaddr_alg, alg}
+ accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
+ AddressFamily::Alg, libc::sockaddr_alg, alg}
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
#[cfg(feature = "net")]
- accessors!{
- as_link_addr, as_link_addr_mut, LinkAddr,
- AddressFamily::Packet, libc::sockaddr_ll, dl}
-
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ accessors! {
+ as_link_addr, as_link_addr_mut, LinkAddr,
+ AddressFamily::Packet, libc::sockaddr_ll, dl}
+
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
- accessors!{
- as_link_addr, as_link_addr_mut, LinkAddr,
- AddressFamily::Link, libc::sockaddr_dl, dl}
+ accessors! {
+ as_link_addr, as_link_addr_mut, LinkAddr,
+ AddressFamily::Link, libc::sockaddr_dl, dl}
#[cfg(feature = "net")]
- accessors!{
- as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
- AddressFamily::Inet, libc::sockaddr_in, sin}
+ accessors! {
+ as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
+ AddressFamily::Inet, libc::sockaddr_in, sin}
#[cfg(feature = "net")]
- accessors!{
- as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
- AddressFamily::Inet6, libc::sockaddr_in6, sin6}
+ accessors! {
+ as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
+ AddressFamily::Inet6, libc::sockaddr_in6, sin6}
#[cfg(any(target_os = "android", target_os = "linux"))]
- accessors!{as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
- AddressFamily::Netlink, libc::sockaddr_nl, nl}
+ accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
+ AddressFamily::Netlink, libc::sockaddr_nl, nl}
#[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
- accessors!{as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
- AddressFamily::System, libc::sockaddr_ctl, sctl}
+ accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
+ AddressFamily::System, libc::sockaddr_ctl, sctl}
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- accessors!{as_vsock_addr, as_vsock_addr_mut, VsockAddr,
- AddressFamily::Vsock, libc::sockaddr_vm, vsock}
+ accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
+ AddressFamily::Vsock, libc::sockaddr_vm, vsock}
}
impl fmt::Debug for SockaddrStorage {
@@ -1564,7 +1798,7 @@ impl fmt::Debug for SockaddrStorage {
f.debug_struct("SockaddrStorage")
// Safe because sockaddr_storage has the least specific
// field types
- .field("ss", unsafe{&self.ss})
+ .field("ss", unsafe { &self.ss })
.finish()
}
}
@@ -1579,20 +1813,23 @@ impl fmt::Display for SockaddrStorage {
libc::AF_INET => self.sin.fmt(f),
#[cfg(feature = "net")]
libc::AF_INET6 => self.sin6.fmt(f),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
libc::AF_LINK => self.dl.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_NETLINK => self.nl.fmt(f),
- #[cfg(any(target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
+ #[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "fuchsia"
))]
#[cfg(feature = "net")]
libc::AF_PACKET => self.dl.fmt(f),
@@ -1602,7 +1839,7 @@ impl fmt::Display for SockaddrStorage {
libc::AF_UNIX => self.su.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_VSOCK => self.vsock.fmt(f),
- _ => "<Address family unspecified>".fmt(f)
+ _ => "<Address family unspecified>".fmt(f),
}
}
}
@@ -1650,20 +1887,23 @@ impl Hash for SockaddrStorage {
libc::AF_INET => self.sin.hash(s),
#[cfg(feature = "net")]
libc::AF_INET6 => self.sin6.hash(s),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
libc::AF_LINK => self.dl.hash(s),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_NETLINK => self.nl.hash(s),
- #[cfg(any(target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
+ #[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "fuchsia"
))]
#[cfg(feature = "net")]
libc::AF_PACKET => self.dl.hash(s),
@@ -1673,7 +1913,7 @@ impl Hash for SockaddrStorage {
libc::AF_UNIX => self.su.hash(s),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_VSOCK => self.vsock.hash(s),
- _ => self.ss.hash(s)
+ _ => self.ss.hash(s),
}
}
}
@@ -1689,20 +1929,23 @@ impl PartialEq for SockaddrStorage {
(libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
#[cfg(feature = "net")]
(libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
(libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
#[cfg(any(target_os = "android", target_os = "linux"))]
(libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
- #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
))]
#[cfg(feature = "net")]
(libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
@@ -1740,7 +1983,7 @@ mod private {
since = "0.24.0",
note = "use SockaddrLike or SockaddrStorage instead"
)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
+#[allow(missing_docs)] // Since they're all deprecated anyway
#[allow(deprecated)]
#[non_exhaustive]
pub enum SockAddr {
@@ -1754,19 +1997,24 @@ pub enum SockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Alg(AlgAddr),
- #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
SysControl(SysControlAddr),
/// Datalink address (MAC)
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
Link(LinkAddr),
@@ -1775,7 +2023,7 @@ pub enum SockAddr {
Vsock(VsockAddr),
}
-#[allow(missing_docs)] // Since they're all deprecated anyway
+#[allow(missing_docs)] // Since they're all deprecated anyway
#[allow(deprecated)]
impl SockAddr {
feature! {
@@ -1826,19 +2074,23 @@ impl SockAddr {
SockAddr::Netlink(..) => AddressFamily::Netlink,
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Alg(..) => AddressFamily::Alg,
- #[cfg(all(feature = "ioctl",
- any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
SockAddr::SysControl(..) => AddressFamily::System,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
SockAddr::Link(..) => AddressFamily::Packet,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
SockAddr::Link(..) => AddressFamily::Link,
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -1862,7 +2114,9 @@ impl SockAddr {
/// ensure that the pointer is valid.
#[cfg(not(target_os = "fuchsia"))]
#[cfg(feature = "net")]
- pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
+ pub(crate) unsafe fn from_libc_sockaddr(
+ addr: *const libc::sockaddr,
+ ) -> Option<SockAddr> {
if addr.is_null() {
None
} else {
@@ -1870,40 +2124,51 @@ impl SockAddr {
Some(AddressFamily::Unix) => None,
#[cfg(feature = "net")]
Some(AddressFamily::Inet) => Some(SockAddr::Inet(
- InetAddr::V4(ptr::read_unaligned(addr as *const _)))),
+ InetAddr::V4(ptr::read_unaligned(addr as *const _)),
+ )),
#[cfg(feature = "net")]
Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
- InetAddr::V6(ptr::read_unaligned(addr as *const _)))),
+ InetAddr::V6(ptr::read_unaligned(addr as *const _)),
+ )),
#[cfg(any(target_os = "android", target_os = "linux"))]
Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
- NetlinkAddr(ptr::read_unaligned(addr as *const _)))),
- #[cfg(all(feature = "ioctl",
- any(target_os = "ios", target_os = "macos")))]
+ NetlinkAddr(ptr::read_unaligned(addr as *const _)),
+ )),
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
Some(AddressFamily::System) => Some(SockAddr::SysControl(
- SysControlAddr(ptr::read_unaligned(addr as *const _)))),
+ SysControlAddr(ptr::read_unaligned(addr as *const _)),
+ )),
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
- Some(AddressFamily::Packet) => Some(SockAddr::Link(
- LinkAddr(ptr::read_unaligned(addr as *const _)))),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
+ Some(AddressFamily::Packet) => Some(SockAddr::Link(LinkAddr(
+ ptr::read_unaligned(addr as *const _),
+ ))),
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
Some(AddressFamily::Link) => {
- let ether_addr = LinkAddr(ptr::read_unaligned(addr as *const _));
+ let ether_addr =
+ LinkAddr(ptr::read_unaligned(addr as *const _));
if ether_addr.is_empty() {
None
} else {
Some(SockAddr::Link(ether_addr))
}
- },
+ }
#[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
- VsockAddr(ptr::read_unaligned(addr as *const _)))),
+ Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(VsockAddr(
+ ptr::read_unaligned(addr as *const _),
+ ))),
// Other address families are currently not supported and simply yield a None
// entry instead of a proper conversion to a `SockAddr`.
Some(_) | None => None,
@@ -1924,24 +2189,27 @@ impl SockAddr {
SockAddr::Inet(InetAddr::V4(ref addr)) => (
// This cast is always allowed in C
unsafe {
- &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
+ &*(addr as *const libc::sockaddr_in
+ as *const libc::sockaddr)
},
- mem::size_of_val(addr) as libc::socklen_t
+ mem::size_of_val(addr) as libc::socklen_t,
),
#[cfg(feature = "net")]
SockAddr::Inet(InetAddr::V6(ref addr)) => (
// This cast is always allowed in C
unsafe {
- &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
+ &*(addr as *const libc::sockaddr_in6
+ as *const libc::sockaddr)
},
- mem::size_of_val(addr) as libc::socklen_t
+ mem::size_of_val(addr) as libc::socklen_t,
),
SockAddr::Unix(ref unix_addr) => (
// This cast is always allowed in C
unsafe {
- &*(&unix_addr.sun as *const libc::sockaddr_un as *const libc::sockaddr)
+ &*(&unix_addr.sun as *const libc::sockaddr_un
+ as *const libc::sockaddr)
},
- unix_addr.sun_len() as libc::socklen_t
+ unix_addr.sun_len() as libc::socklen_t,
),
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Netlink(NetlinkAddr(ref sa)) => (
@@ -1949,7 +2217,7 @@ impl SockAddr {
unsafe {
&*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
},
- mem::size_of_val(sa) as libc::socklen_t
+ mem::size_of_val(sa) as libc::socklen_t,
),
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Alg(AlgAddr(ref sa)) => (
@@ -1957,41 +2225,46 @@ impl SockAddr {
unsafe {
&*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
},
- mem::size_of_val(sa) as libc::socklen_t
+ mem::size_of_val(sa) as libc::socklen_t,
),
- #[cfg(all(feature = "ioctl",
- any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
SockAddr::SysControl(SysControlAddr(ref sa)) => (
// This cast is always allowed in C
unsafe {
&*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
},
- mem::size_of_val(sa) as libc::socklen_t
-
+ mem::size_of_val(sa) as libc::socklen_t,
),
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
SockAddr::Link(LinkAddr(ref addr)) => (
// This cast is always allowed in C
unsafe {
- &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
+ &*(addr as *const libc::sockaddr_ll
+ as *const libc::sockaddr)
},
- mem::size_of_val(addr) as libc::socklen_t
+ mem::size_of_val(addr) as libc::socklen_t,
),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
SockAddr::Link(LinkAddr(ref addr)) => (
// This cast is always allowed in C
unsafe {
- &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
+ &*(addr as *const libc::sockaddr_dl
+ as *const libc::sockaddr)
},
- mem::size_of_val(addr) as libc::socklen_t
+ mem::size_of_val(addr) as libc::socklen_t,
),
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Vsock(VsockAddr(ref sa)) => (
@@ -1999,7 +2272,7 @@ impl SockAddr {
unsafe {
&*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
},
- mem::size_of_val(sa) as libc::socklen_t
+ mem::size_of_val(sa) as libc::socklen_t,
),
}
}
@@ -2016,18 +2289,22 @@ impl fmt::Display for SockAddr {
SockAddr::Netlink(ref nl) => nl.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Alg(ref nl) => nl.fmt(f),
- #[cfg(all(feature = "ioctl",
- any(target_os = "ios", target_os = "macos")))]
+ #[cfg(all(
+ feature = "ioctl",
+ any(target_os = "ios", target_os = "macos")
+ ))]
SockAddr::SysControl(ref sc) => sc.fmt(f),
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd"
+ ))]
#[cfg(feature = "net")]
SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -2044,9 +2321,10 @@ impl private::SockaddrLikePriv for SockAddr {}
#[cfg(feature = "net")]
#[allow(deprecated)]
impl SockaddrLike for SockAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr, _len: Option<libc::socklen_t>)
- -> Option<Self>
- {
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ _len: Option<libc::socklen_t>,
+ ) -> Option<Self> {
Self::from_libc_sockaddr(addr)
}
}
@@ -2054,10 +2332,10 @@ impl SockaddrLike for SockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub mod netlink {
+ use super::*;
use crate::sys::socket::addr::AddressFamily;
use libc::{sa_family_t, sockaddr_nl};
use std::{fmt, mem};
- use super::*;
/// Address for the Linux kernel user interface device.
///
@@ -2093,15 +2371,19 @@ pub mod netlink {
impl private::SockaddrLikePriv for NetlinkAddr {}
impl SockaddrLike for NetlinkAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = len {
if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_NETLINK as i32 {
+ if (*addr).sa_family as i32 != libc::AF_NETLINK {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2124,11 +2406,11 @@ pub mod netlink {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub mod alg {
- use libc::{AF_ALG, sockaddr_alg, c_char};
- use std::{fmt, mem, str};
- use std::hash::{Hash, Hasher};
- use std::ffi::CStr;
use super::*;
+ use libc::{c_char, sockaddr_alg, AF_ALG};
+ use std::ffi::CStr;
+ use std::hash::{Hash, Hasher};
+ use std::{fmt, mem, str};
/// Socket address for the Linux kernel crypto API
#[derive(Copy, Clone)]
@@ -2137,15 +2419,20 @@ pub mod alg {
impl private::SockaddrLikePriv for AlgAddr {}
impl SockaddrLike for AlgAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr, l: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ l: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = l {
- if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t {
+ if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
+ {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_ALG as i32 {
+ if (*addr).sa_family as i32 != libc::AF_ALG {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2162,8 +2449,19 @@ pub mod alg {
impl PartialEq for AlgAddr {
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
- (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
- (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
+ (
+ inner.salg_family,
+ &inner.salg_type[..],
+ inner.salg_feat,
+ inner.salg_mask,
+ &inner.salg_name[..],
+ ) == (
+ other.salg_family,
+ &other.salg_type[..],
+ other.salg_feat,
+ other.salg_mask,
+ &other.salg_name[..],
+ )
}
}
@@ -2172,7 +2470,14 @@ pub mod alg {
impl Hash for AlgAddr {
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
- (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
+ (
+ inner.salg_family,
+ &inner.salg_type[..],
+ inner.salg_feat,
+ inner.salg_mask,
+ &inner.salg_name[..],
+ )
+ .hash(s);
}
}
@@ -2181,29 +2486,37 @@ pub mod alg {
pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
addr.salg_family = AF_ALG as u16;
- addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
- addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
+ addr.salg_type[..alg_type.len()]
+ .copy_from_slice(alg_type.to_string().as_bytes());
+ addr.salg_name[..alg_name.len()]
+ .copy_from_slice(alg_name.to_string().as_bytes());
AlgAddr(addr)
}
-
/// Return the socket's cipher type, for example `hash` or `aead`.
pub fn alg_type(&self) -> &CStr {
- unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
+ unsafe {
+ CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char)
+ }
}
/// Return the socket's cipher name, for example `sha1`.
pub fn alg_name(&self) -> &CStr {
- unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
+ unsafe {
+ CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char)
+ }
}
}
impl fmt::Display for AlgAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "type: {} alg: {}",
- self.alg_name().to_string_lossy(),
- self.alg_type().to_string_lossy())
+ write!(
+ f,
+ "type: {} alg: {}",
+ self.alg_name().to_string_lossy(),
+ self.alg_type().to_string_lossy()
+ )
}
}
@@ -2244,7 +2557,7 @@ pub mod sys_control {
///
/// # References
///
- /// https://developer.apple.com/documentation/kernel/sockaddr_ctl
+ /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl>
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
@@ -2259,7 +2572,7 @@ pub mod sys_control {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_SYSTEM as i32 {
+ if (*addr).sa_family as i32 != libc::AF_SYSTEM {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2323,7 +2636,6 @@ pub mod sys_control {
}
}
-
#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod datalink {
@@ -2366,12 +2678,12 @@ mod datalink {
// Returns an Option just for cross-platform compatibility
pub fn addr(&self) -> Option<[u8; 6]> {
Some([
- self.0.sll_addr[0] as u8,
- self.0.sll_addr[1] as u8,
- self.0.sll_addr[2] as u8,
- self.0.sll_addr[3] as u8,
- self.0.sll_addr[4] as u8,
- self.0.sll_addr[5] as u8,
+ self.0.sll_addr[0],
+ self.0.sll_addr[1],
+ self.0.sll_addr[2],
+ self.0.sll_addr[3],
+ self.0.sll_addr[4],
+ self.0.sll_addr[5],
])
}
}
@@ -2402,7 +2714,7 @@ mod datalink {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_PACKET as i32 {
+ if (*addr).sa_family as i32 != libc::AF_PACKET {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2418,14 +2730,16 @@ mod datalink {
}
}
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "haiku",
+ target_os = "openbsd"
+))]
#[cfg_attr(docsrs, doc(cfg(all())))]
mod datalink {
feature! {
@@ -2477,6 +2791,8 @@ mod datalink {
}
/// Physical-layer address (MAC)
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
pub fn addr(&self) -> Option<[u8; 6]> {
let nlen = self.nlen();
let data = self.0.sdl_data;
@@ -2522,7 +2838,7 @@ mod datalink {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_LINK as i32 {
+ if (*addr).sa_family as i32 != libc::AF_LINK {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2541,11 +2857,11 @@ mod datalink {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub mod vsock {
+ use super::*;
use crate::sys::socket::addr::AddressFamily;
use libc::{sa_family_t, sockaddr_vm};
- use std::{fmt, mem};
use std::hash::{Hash, Hasher};
- use super::*;
+ use std::{fmt, mem};
/// Socket address for VMWare VSockets protocol
///
@@ -2558,15 +2874,19 @@ pub mod vsock {
impl private::SockaddrLikePriv for VsockAddr {}
impl SockaddrLike for VsockAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
+ unsafe fn from_raw(
+ addr: *const libc::sockaddr,
+ len: Option<libc::socklen_t>,
+ ) -> Option<Self>
+ where
+ Self: Sized,
{
if let Some(l) = len {
if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
return None;
}
}
- if (*addr).sa_family as i32 != libc::AF_VSOCK as i32 {
+ if (*addr).sa_family as i32 != libc::AF_VSOCK {
return None;
}
Some(Self(ptr::read_unaligned(addr as *const _)))
@@ -2582,8 +2902,8 @@ pub mod vsock {
impl PartialEq for VsockAddr {
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
- (inner.svm_family, inner.svm_cid, inner.svm_port) ==
- (other.svm_family, other.svm_cid, other.svm_port)
+ (inner.svm_family, inner.svm_cid, inner.svm_port)
+ == (other.svm_family, other.svm_cid, other.svm_port)
}
}
@@ -2653,33 +2973,39 @@ mod tests {
fn test_ipv6addr_to_libc() {
let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
let l = ipv6addr_to_libc(&s);
- assert_eq!(l.s6_addr, [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]);
+ assert_eq!(
+ l.s6_addr,
+ [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
+ );
}
}
mod link {
#![allow(clippy::cast_ptr_alignment)]
- use super::*;
- #[cfg(any(target_os = "ios",
- target_os = "macos",
- target_os = "illumos"
- ))]
+ #[cfg(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "illumos"
+ ))]
use super::super::super::socklen_t;
+ use super::*;
/// Don't panic when trying to display an empty datalink address
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
#[test]
fn test_datalink_display() {
use super::super::LinkAddr;
use std::mem;
- let la = LinkAddr(libc::sockaddr_dl{
+ let la = LinkAddr(libc::sockaddr_dl {
sdl_len: 56,
sdl_family: 18,
sdl_index: 5,
@@ -2687,67 +3013,75 @@ mod tests {
sdl_nlen: 3,
sdl_alen: 0,
sdl_slen: 0,
- .. unsafe{mem::zeroed()}
+ ..unsafe { mem::zeroed() }
});
format!("{}", la);
}
#[cfg(all(
- any(target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"),
- target_endian = "little"
+ any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ),
+ target_endian = "little"
))]
#[test]
fn linux_loopback() {
#[repr(align(2))]
struct Raw([u8; 20]);
- let bytes = Raw([17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0]);
+ let bytes = Raw([
+ 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
+ ]);
let sa = bytes.0.as_ptr() as *const libc::sockaddr;
let len = None;
- let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
+ let sock_addr =
+ unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
match sock_addr.as_link_addr() {
Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
- None => panic!("Can't unwrap sockaddr storage")
+ None => panic!("Can't unwrap sockaddr storage"),
}
}
- #[cfg(any(target_os = "ios",
- target_os = "macos"
- ))]
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
#[test]
fn macos_loopback() {
- let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
+ let bytes =
+ [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
let sa = bytes.as_ptr() as *const libc::sockaddr;
let len = Some(bytes.len() as socklen_t);
- let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
+ let sock_addr =
+ unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
match sock_addr.as_link_addr() {
Some(dl) => {
assert!(dl.addr().is_none());
- },
- None => panic!("Can't unwrap sockaddr storage")
+ }
+ None => panic!("Can't unwrap sockaddr storage"),
}
}
- #[cfg(any(target_os = "ios",
- target_os = "macos"
- ))]
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
#[test]
fn macos_tap() {
- let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
+ let bytes = [
+ 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
+ 76, -80,
+ ];
let ptr = bytes.as_ptr();
let sa = ptr as *const libc::sockaddr;
let len = Some(bytes.len() as socklen_t);
- let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
+ let sock_addr =
+ unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
match sock_addr.as_link_addr() {
- Some(dl) => assert_eq!(dl.addr(),
- Some([24u8, 101, 144, 221, 76, 176])),
- None => panic!("Can't unwrap sockaddr storage")
+ Some(dl) => {
+ assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
+ }
+ None => panic!("Can't unwrap sockaddr storage"),
}
}
@@ -2766,27 +3100,32 @@ mod tests {
assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
- assert_eq!(sock_addr.as_link_addr().unwrap().addr(),
- Some([24u8, 101, 144, 221, 76, 176]));
+ assert_eq!(
+ sock_addr.as_link_addr().unwrap().addr(),
+ Some([24u8, 101, 144, 221, 76, 176])
+ );
}
#[test]
fn size() {
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd",
- target_os = "haiku"))]
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd",
+ target_os = "haiku"
+ ))]
let l = mem::size_of::<libc::sockaddr_dl>();
#[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"))]
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
let l = mem::size_of::<libc::sockaddr_ll>();
- assert_eq!( LinkAddr::size() as usize, l);
+ assert_eq!(LinkAddr::size() as usize, l);
}
}
@@ -2803,8 +3142,10 @@ mod tests {
#[test]
fn size() {
- assert_eq!(mem::size_of::<libc::sockaddr_in>(),
- SockaddrIn::size() as usize);
+ assert_eq!(
+ mem::size_of::<libc::sockaddr_in>(),
+ SockaddrIn::size() as usize
+ );
}
}
@@ -2821,8 +3162,47 @@ mod tests {
#[test]
fn size() {
- assert_eq!(mem::size_of::<libc::sockaddr_in6>(),
- SockaddrIn6::size() as usize);
+ assert_eq!(
+ mem::size_of::<libc::sockaddr_in6>(),
+ SockaddrIn6::size() as usize
+ );
+ }
+ }
+
+ mod sockaddr_storage {
+ use super::*;
+
+ #[test]
+ fn from_sockaddr_un_named() {
+ let ua = UnixAddr::new("/var/run/mysock").unwrap();
+ let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ss = unsafe {
+ SockaddrStorage::from_raw(ptr, Some(ua.len()))
+ }.unwrap();
+ assert_eq!(ss.len(), ua.len());
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[test]
+ fn from_sockaddr_un_abstract_named() {
+ let name = String::from("nix\0abstract\0test");
+ let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
+ let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ss = unsafe {
+ SockaddrStorage::from_raw(ptr, Some(ua.len()))
+ }.unwrap();
+ assert_eq!(ss.len(), ua.len());
+ }
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[test]
+ fn from_sockaddr_un_abstract_unnamed() {
+ let ua = UnixAddr::new_unnamed();
+ let ptr = ua.as_ptr() as *const libc::sockaddr;
+ let ss = unsafe {
+ SockaddrStorage::from_raw(ptr, Some(ua.len()))
+ }.unwrap();
+ assert_eq!(ss.len(), ua.len());
}
}
@@ -2835,15 +3215,21 @@ mod tests {
let name = String::from("nix\0abstract\0test");
let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- let sun_path1 = 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];
+ let sun_path1 =
+ 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,
+ ];
assert_eq!(sun_path1, sun_path2);
}
#[test]
fn size() {
- assert_eq!(mem::size_of::<libc::sockaddr_un>(),
- UnixAddr::size() as usize);
+ assert_eq!(
+ mem::size_of::<libc::sockaddr_un>(),
+ UnixAddr::size() as usize
+ );
}
}
}
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index ecbf30a..2d7159a 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -1,21 +1,23 @@
//! Socket interface functions
//!
//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
-use cfg_if::cfg_if;
-use crate::{Result, errno::Errno};
-use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
- CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
-use std::convert::TryInto;
-use std::{mem, ptr, slice};
-use std::os::unix::io::RawFd;
-#[cfg(feature = "net")]
-use std::net;
#[cfg(target_os = "linux")]
#[cfg(feature = "uio")]
use crate::sys::time::TimeSpec;
#[cfg(feature = "uio")]
use crate::sys::time::TimeVal;
+use crate::{errno::Errno, Result};
+use cfg_if::cfg_if;
+use libc::{
+ self, c_int, c_void, iovec, size_t, socklen_t, CMSG_DATA, CMSG_FIRSTHDR,
+ CMSG_LEN, CMSG_NXTHDR,
+};
+use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut};
+#[cfg(feature = "net")]
+use std::net;
+use std::os::unix::io::RawFd;
+use std::{mem, ptr, slice};
#[deny(missing_docs)]
mod addr;
@@ -32,60 +34,44 @@ pub use self::addr::{SockaddrLike, SockaddrStorage};
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
#[allow(deprecated)]
-pub use self::addr::{
- AddressFamily,
- SockAddr,
- UnixAddr,
-};
-#[allow(deprecated)]
-#[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "haiku")))]
-#[cfg(feature = "net")]
-pub use self::addr::{
- InetAddr,
- IpAddr,
- Ipv4Addr,
- Ipv6Addr,
- LinkAddr,
- SockaddrIn,
- SockaddrIn6
-};
+pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[allow(deprecated)]
+pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
+#[allow(deprecated)]
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "solaris",
+ target_os = "haiku"
+)))]
+#[cfg(feature = "net")]
pub use self::addr::{
- AddressFamily,
- SockAddr,
- UnixAddr,
+ InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, LinkAddr, SockaddrIn, SockaddrIn6,
};
#[allow(deprecated)]
-#[cfg(any(target_os = "illumos", target_os = "solaris", target_os = "haiku"))]
+#[cfg(any(
+ target_os = "illumos",
+ target_os = "solaris",
+ target_os = "haiku"
+))]
#[cfg(feature = "net")]
pub use self::addr::{
- InetAddr,
- IpAddr,
- Ipv4Addr,
- Ipv6Addr,
- SockaddrIn,
- SockaddrIn6
+ InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, SockaddrIn, SockaddrIn6,
};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use crate::sys::socket::addr::alg::AlgAddr;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use crate::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(feature = "ioctl")]
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
pub use crate::sys::socket::addr::vsock::VsockAddr;
#[cfg(feature = "uio")]
pub use libc::{cmsghdr, msghdr};
-pub use libc::{
- sa_family_t,
- sockaddr,
- sockaddr_storage,
- sockaddr_un,
-};
+pub use libc::{sa_family_t, sockaddr, sockaddr_storage, sockaddr_un};
#[cfg(feature = "net")]
pub use libc::{sockaddr_in, sockaddr_in6};
@@ -121,6 +107,24 @@ pub enum SockType {
#[cfg(not(any(target_os = "haiku")))]
Rdm = libc::SOCK_RDM,
}
+// The TryFrom impl could've been derived using libc_enum!. But for
+// backwards-compatibility with Nix-0.25.0 we manually implement it, so as to
+// keep the old variant names.
+impl TryFrom<i32> for SockType {
+ type Error = crate::Error;
+
+ fn try_from(x: i32) -> Result<Self> {
+ match x {
+ libc::SOCK_STREAM => Ok(Self::Stream),
+ libc::SOCK_DGRAM => Ok(Self::Datagram),
+ libc::SOCK_SEQPACKET => Ok(Self::SeqPacket),
+ libc::SOCK_RAW => Ok(Self::Raw),
+ #[cfg(not(any(target_os = "haiku")))]
+ libc::SOCK_RDM => Ok(Self::Rdm),
+ _ => Err(Errno::EINVAL)
+ }
+ }
+}
/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
/// to specify the protocol to use.
@@ -132,6 +136,8 @@ pub enum SockProtocol {
Tcp = libc::IPPROTO_TCP,
/// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
Udp = libc::IPPROTO_UDP,
+ /// Raw sockets ([raw(7)](https://man7.org/linux/man-pages/man7/raw.7.html))
+ Raw = libc::IPPROTO_RAW,
/// Allows applications and other KEXTs to be notified when certain kernel events occur
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
#[cfg(any(target_os = "ios", target_os = "macos"))]
@@ -245,7 +251,7 @@ libc_bitflags! {
}
}
-libc_bitflags!{
+libc_bitflags! {
/// Additional socket options
pub struct SockFlag: c_int {
/// Set non-blocking mode on the new socket
@@ -280,20 +286,23 @@ libc_bitflags!{
}
}
-libc_bitflags!{
+libc_bitflags! {
/// Flags for send/recv and their relatives
pub struct MsgFlags: c_int {
/// Sends or requests out-of-band data on sockets that support this notion
/// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
/// support out-of-band data.
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_OOB;
/// Peeks at an incoming message. The data is treated as unread and the next
/// [`recv()`](fn.recv.html)
/// or similar function shall still return this data.
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_PEEK;
/// Receive operation blocks until the full amount of data can be
/// returned. The function may return smaller amount of data if a signal
/// is caught, an error or disconnect occurs.
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_WAITALL;
/// Enables nonblocking operation; if the operation would block,
/// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar
@@ -305,8 +314,10 @@ libc_bitflags!{
/// which will affect all threads in
/// the calling process and as well as other processes that hold
/// file descriptors referring to the same open file description.
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_DONTWAIT;
/// Receive flags: Control Data was discarded (buffer too small)
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_CTRUNC;
/// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
/// (since Linux 2.4.27/2.6.8),
@@ -316,15 +327,18 @@ libc_bitflags!{
/// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
///
/// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_TRUNC;
/// Terminates a record (when this notion is supported, as for
/// sockets of type [`SeqPacket`](enum.SockType.html)).
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_EOR;
/// This flag specifies that queued errors should be received from
/// the socket error queue. (For more details, see
/// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_ERRQUEUE;
/// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
/// file descriptor using the `SCM_RIGHTS` operation (described in
@@ -340,6 +354,7 @@ libc_bitflags!{
target_os = "netbsd",
target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_CMSG_CLOEXEC;
/// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
/// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
@@ -354,6 +369,7 @@ libc_bitflags!{
target_os = "openbsd",
target_os = "solaris"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
+ #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
MSG_NOSIGNAL;
}
}
@@ -462,7 +478,7 @@ cfg_if! {
}
}
-cfg_if!{
+cfg_if! {
if #[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
@@ -581,15 +597,20 @@ macro_rules! cmsg_space {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct RecvMsg<'a, S> {
+/// Contains outcome of sending or receiving a message
+///
+/// Use [`cmsgs`][RecvMsg::cmsgs] to access all the control messages present, and
+/// [`iovs`][RecvMsg::iovs`] to access underlying io slices.
+pub struct RecvMsg<'a, 's, S> {
pub bytes: usize,
cmsghdr: Option<&'a cmsghdr>,
pub address: Option<S>,
pub flags: MsgFlags,
+ iobufs: std::marker::PhantomData<& 's()>,
mhdr: msghdr,
}
-impl<'a, S> RecvMsg<'a, S> {
+impl<'a, S> RecvMsg<'a, '_, S> {
/// Iterate over the valid control messages pointed to by this
/// msghdr.
pub fn cmsgs(&self) -> CmsgIterator {
@@ -839,6 +860,8 @@ impl ControlMessageOwned {
unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
{
let p = CMSG_DATA(header);
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
let len = header as *const _ as usize + header.cmsg_len as usize
- p as usize;
match (header.cmsg_level, header.cmsg_type) {
@@ -1459,31 +1482,13 @@ pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
// because subsequent code will not clear the padding bytes.
let mut cmsg_buffer = vec![0u8; capacity];
- let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr);
+ let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], iov, cmsgs, addr);
let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
Errno::result(ret).map(|r| r as usize)
}
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
-pub struct SendMmsgData<'a, I, C, S>
- where
- I: AsRef<[IoSlice<'a>]>,
- C: AsRef<[ControlMessage<'a>]>,
- S: SockaddrLike + 'a
-{
- pub iov: I,
- pub cmsgs: C,
- pub addr: Option<S>,
- pub _lt: std::marker::PhantomData<&'a I>,
-}
/// An extension of `sendmsg` that allows the caller to transmit multiple
/// messages on a socket using a single system call. This has performance
@@ -1508,51 +1513,66 @@ pub struct SendMmsgData<'a, I, C, S>
target_os = "freebsd",
target_os = "netbsd",
))]
-pub fn sendmmsg<'a, I, C, S>(
+pub fn sendmmsg<'a, XS, AS, C, I, S>(
fd: RawFd,
- data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C, S>>,
+ data: &'a mut MultiHeaders<S>,
+ slices: XS,
+ // one address per group of slices
+ addrs: AS,
+ // shared across all the messages
+ cmsgs: C,
flags: MsgFlags
-) -> Result<Vec<usize>>
+) -> crate::Result<MultiResults<'a, S>>
where
+ XS: IntoIterator<Item = &'a I>,
+ AS: AsRef<[Option<S>]>,
I: AsRef<[IoSlice<'a>]> + 'a,
C: AsRef<[ControlMessage<'a>]> + 'a,
S: SockaddrLike + 'a
{
- let iter = data.into_iter();
- let size_hint = iter.size_hint();
- let reserve_items = size_hint.1.unwrap_or(size_hint.0);
+ let mut count = 0;
- let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
- let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);
+ for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
+ let mut p = &mut mmsghdr.msg_hdr;
+ p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
+ p.msg_iovlen = slice.as_ref().len() as _;
- for d in iter {
- let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
- let mut cmsgs_buffer = vec![0u8; capacity];
+ p.msg_namelen = addr.as_ref().map_or(0, S::len);
+ p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr) as _;
- output.push(libc::mmsghdr {
- msg_hdr: pack_mhdr_to_send(
- &mut cmsgs_buffer,
- &d.iov,
- &d.cmsgs,
- d.addr.as_ref()
- ),
- msg_len: 0,
- });
- cmsgs_buffers.push(cmsgs_buffer);
- };
+ // Encode each cmsg. This must happen after initializing the header because
+ // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
+ // CMSG_FIRSTHDR is always safe
+ let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(p) };
+ for cmsg in cmsgs.as_ref() {
+ assert_ne!(pmhdr, ptr::null_mut());
+ // Safe because we know that pmhdr is valid, and we initialized it with
+ // sufficient space
+ unsafe { cmsg.encode_into(pmhdr) };
+ // Safe because mhdr is valid
+ pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
+ }
- let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
+ count = i+1;
+ }
- let sent_messages = Errno::result(ret)? as usize;
- let mut sent_bytes = Vec::with_capacity(sent_messages);
+ let sent = Errno::result(unsafe {
+ libc::sendmmsg(
+ fd,
+ data.items.as_mut_ptr(),
+ count as _,
+ flags.bits() as _
+ )
+ })? as usize;
- for item in &output {
- sent_bytes.push(item.msg_len as usize);
- }
+ Ok(MultiResults {
+ rmm: data,
+ current_index: 0,
+ received: sent
+ })
- Ok(sent_bytes)
}
@@ -1563,134 +1583,347 @@ pub fn sendmmsg<'a, I, C, S>(
target_os = "netbsd",
))]
#[derive(Debug)]
-pub struct RecvMmsgData<'a, I>
+/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
+pub struct MultiHeaders<S> {
+ // preallocated boxed slice of mmsghdr
+ items: Box<[libc::mmsghdr]>,
+ addresses: Box<[mem::MaybeUninit<S>]>,
+ // while we are not using it directly - this is used to store control messages
+ // and we retain pointers to them inside items array
+ #[allow(dead_code)]
+ cmsg_buffers: Option<Box<[u8]>>,
+ msg_controllen: usize,
+}
+
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "netbsd",
+))]
+impl<S> MultiHeaders<S> {
+ /// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
+ ///
+ /// `cmsg_buffer` should be created with [`cmsg_space!`] if needed
+ pub fn preallocate(num_slices: usize, cmsg_buffer: Option<Vec<u8>>) -> Self
where
- I: AsRef<[IoSliceMut<'a>]> + 'a,
-{
- pub iov: I,
- pub cmsg_buffer: Option<&'a mut Vec<u8>>,
+ S: Copy + SockaddrLike,
+ {
+ // we will be storing pointers to addresses inside mhdr - convert it into boxed
+ // slice so it can'be changed later by pushing anything into self.addresses
+ let mut addresses = vec![std::mem::MaybeUninit::uninit(); num_slices].into_boxed_slice();
+
+ let msg_controllen = cmsg_buffer.as_ref().map_or(0, |v| v.capacity());
+
+ // we'll need a cmsg_buffer for each slice, we preallocate a vector and split
+ // it into "slices" parts
+ let cmsg_buffers =
+ cmsg_buffer.map(|v| vec![0u8; v.capacity() * num_slices].into_boxed_slice());
+
+ let items = addresses
+ .iter_mut()
+ .enumerate()
+ .map(|(ix, address)| {
+ let (ptr, cap) = match &cmsg_buffers {
+ Some(v) => ((&v[ix * msg_controllen] as *const u8), msg_controllen),
+ None => (std::ptr::null(), 0),
+ };
+ let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null(), 0, ptr, cap, address.as_mut_ptr()) };
+ libc::mmsghdr {
+ msg_hdr,
+ msg_len: 0,
+ }
+ })
+ .collect::<Vec<_>>();
+
+ Self {
+ items: items.into_boxed_slice(),
+ addresses,
+ cmsg_buffers,
+ msg_controllen,
+ }
+ }
}
-/// An extension of `recvmsg` that allows the caller to receive multiple
-/// messages from a socket using a single system call. This has
-/// performance benefits for some applications.
+/// An extension of recvmsg that allows the caller to receive multiple messages from a socket using a single system call.
///
-/// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg`
+/// This has performance benefits for some applications.
///
-/// Multiple allocations are performed
+/// This method performs no allocations.
///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `data`: Struct that implements `IntoIterator` with `RecvMmsgData` items
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # RecvMmsgData
-///
-/// * `iov`: Scatter-gather list of buffers to receive the message
-/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by
-/// [`cmsg_space!`](../../macro.cmsg_space.html)
+/// Returns an iterator producing [`RecvMsg`], one per received messages. Each `RecvMsg` can produce
+/// iterators over [`IoSlice`] with [`iovs`][RecvMsg::iovs`] and
+/// `ControlMessageOwned` with [`cmsgs`][RecvMsg::cmsgs].
///
-/// # Returns
-/// A `Vec` with multiple `RecvMsg`, one per received message
+/// # Bugs (in underlying implementation, at least in Linux)
+/// The timeout argument does not work as intended. The timeout is checked only after the receipt
+/// of each datagram, so that if up to `vlen`-1 datagrams are received before the timeout expires,
+/// but then no further datagrams are received, the call will block forever.
///
-/// # References
-/// - [`recvmsg`](fn.recvmsg.html)
-/// - [`RecvMsg`](struct.RecvMsg.html)
+/// If an error occurs after at least one message has been received, the call succeeds, and returns
+/// the number of messages received. The error code is expected to be returned on a subsequent
+/// 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(
target_os = "linux",
target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
))]
-#[allow(clippy::needless_collect)] // Complicated false positive
-pub fn recvmmsg<'a, I, S>(
+pub fn recvmmsg<'a, XS, S, I>(
fd: RawFd,
- data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
- IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
+ data: &'a mut MultiHeaders<S>,
+ slices: XS,
flags: MsgFlags,
- timeout: Option<crate::sys::time::TimeSpec>
-) -> Result<Vec<RecvMsg<'a, S>>>
- where
- I: AsRef<[IoSliceMut<'a>]> + 'a,
- S: Copy + SockaddrLike + 'a
+ mut timeout: Option<crate::sys::time::TimeSpec>,
+) -> crate::Result<MultiResults<'a, S>>
+where
+ XS: IntoIterator<Item = &'a I>,
+ I: AsRef<[IoSliceMut<'a>]> + 'a,
{
- let iter = data.into_iter();
+ let mut count = 0;
+ for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
+ let mut p = &mut mmsghdr.msg_hdr;
+ p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
+ p.msg_iovlen = slice.as_ref().len() as _;
+ count = i + 1;
+ }
- let num_messages = iter.len();
+ let timeout_ptr = timeout
+ .as_mut()
+ .map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
- let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
+ let received = Errno::result(unsafe {
+ libc::recvmmsg(
+ fd,
+ data.items.as_mut_ptr(),
+ count as _,
+ flags.bits() as _,
+ timeout_ptr,
+ )
+ })? as usize;
- // Addresses should be pre-allocated. pack_mhdr_to_receive will store them
- // as raw pointers, so we may not move them. Turn the vec into a boxed
- // slice so we won't inadvertently reallocate the vec.
- let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages]
- .into_boxed_slice();
+ Ok(MultiResults {
+ rmm: data,
+ current_index: 0,
+ received,
+ })
+}
+
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "netbsd",
+))]
+#[derive(Debug)]
+/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
+///
+///
+pub struct MultiResults<'a, S> {
+ // preallocated structures
+ rmm: &'a MultiHeaders<S>,
+ current_index: usize,
+ received: usize,
+}
+
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "netbsd",
+))]
+impl<'a, S> Iterator for MultiResults<'a, S>
+where
+ S: Copy + SockaddrLike,
+{
+ type Item = RecvMsg<'a, 'a, S>;
- let results: Vec<_> = iter.enumerate().map(|(i, d)| {
- let (msg_controllen, mhdr) = unsafe {
- pack_mhdr_to_receive(
- d.iov.as_ref(),
- &mut d.cmsg_buffer,
- addresses[i].as_mut_ptr(),
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.current_index >= self.received {
+ return None;
+ }
+ let mmsghdr = self.rmm.items[self.current_index];
+
+ // as long as we are not reading past the index writen by recvmmsg - address
+ // will be initialized
+ let address = unsafe { self.rmm.addresses[self.current_index].assume_init() };
+
+ self.current_index += 1;
+ Some(unsafe {
+ read_mhdr(
+ mmsghdr.msg_hdr,
+ mmsghdr.msg_len as isize,
+ self.rmm.msg_controllen,
+ address,
)
+ })
+ }
+}
+
+impl<'a, S> RecvMsg<'_, 'a, S> {
+ /// Iterate over the filled io slices pointed by this msghdr
+ pub fn iovs(&self) -> IoSliceIterator<'a> {
+ IoSliceIterator {
+ index: 0,
+ remaining: self.bytes,
+ slices: unsafe {
+ // safe for as long as mgdr is properly initialized and references are valid.
+ // for multi messages API we initialize it with an empty
+ // slice and replace with a concrete buffer
+ // for single message API we hold a lifetime reference to ioslices
+ std::slice::from_raw_parts(self.mhdr.msg_iov as *const _, self.mhdr.msg_iovlen as _)
+ },
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct IoSliceIterator<'a> {
+ index: usize,
+ remaining: usize,
+ slices: &'a [IoSlice<'a>],
+}
+
+impl<'a> Iterator for IoSliceIterator<'a> {
+ type Item = &'a [u8];
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.index >= self.slices.len() {
+ return None;
+ }
+ let slice = &self.slices[self.index][..self.remaining.min(self.slices[self.index].len())];
+ self.remaining -= slice.len();
+ self.index += 1;
+ if slice.is_empty() {
+ return None;
+ }
+
+ Some(slice)
+ }
+}
+
+// test contains both recvmmsg and timestaping which is linux only
+// there are existing tests for recvmmsg only in tests/
+#[cfg(target_os = "linux")]
+#[cfg(test)]
+mod test {
+ use crate::sys::socket::{AddressFamily, ControlMessageOwned};
+ use crate::*;
+ use std::str::FromStr;
+
+ #[cfg_attr(qemu, ignore)]
+ #[test]
+ fn test_recvmm2() -> crate::Result<()> {
+ use crate::sys::socket::{
+ sendmsg, setsockopt, socket, sockopt::Timestamping, MsgFlags, SockFlag, SockType,
+ SockaddrIn, TimestampingFlag,
};
+ use std::io::{IoSlice, IoSliceMut};
- output.push(
- libc::mmsghdr {
- msg_hdr: mhdr,
- msg_len: 0,
- }
- );
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
- (msg_controllen as usize, &mut d.cmsg_buffer)
- }).collect();
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )?;
- let timeout = if let Some(mut t) = timeout {
- t.as_mut() as *mut libc::timespec
- } else {
- ptr::null_mut()
- };
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::SOCK_NONBLOCK,
+ None,
+ )?;
+
+ crate::sys::socket::bind(rsock, &sock_addr)?;
+
+ setsockopt(rsock, Timestamping, &TimestampingFlag::all())?;
- let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
-
- let _ = Errno::result(ret)?;
-
- Ok(output
- .into_iter()
- .take(ret as usize)
- .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
- .zip(results.into_iter())
- .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
- unsafe {
- read_mhdr(
- mmsghdr.msg_hdr,
- mmsghdr.msg_len as isize,
- msg_controllen,
- address,
- cmsg_buffer
- )
+ let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
+
+ let mut recv_buf = vec![0; 1024];
+
+ let mut recv_iovs = Vec::new();
+ let mut pkt_iovs = Vec::new();
+
+ for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
+ pkt_iovs.push(IoSliceMut::new(chunk));
+ if ix % 2 == 1 {
+ recv_iovs.push(pkt_iovs);
+ pkt_iovs = Vec::new();
}
- })
- .collect())
-}
+ }
+ drop(pkt_iovs);
+
+ let flags = MsgFlags::empty();
+ let iov1 = [IoSlice::new(&sbuf)];
+
+ let cmsg = cmsg_space!(crate::sys::socket::Timestamps);
+ sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
+
+ let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
+
+ let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10));
+
+ let recv = super::recvmmsg(rsock, &mut data, recv_iovs.iter(), flags, Some(t))?;
+
+ for rmsg in recv {
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ let mut saw_time = false;
+ let mut recvd = 0;
+ for cmsg in rmsg.cmsgs() {
+ if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
+ let ts = timestamps.system;
+
+ let sys_time =
+ crate::time::clock_gettime(crate::time::ClockId::CLOCK_REALTIME)?;
+ let diff = if ts > sys_time {
+ ts - sys_time
+ } else {
+ sys_time - ts
+ };
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ {
+ saw_time = true;
+ }
+ }
+ }
+
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ assert!(saw_time);
-unsafe fn read_mhdr<'a, 'b, S>(
+ for iov in rmsg.iovs() {
+ recvd += iov.len();
+ }
+ assert_eq!(recvd, 400);
+ }
+
+ Ok(())
+ }
+}
+unsafe fn read_mhdr<'a, 'i, S>(
mhdr: msghdr,
r: isize,
msg_controllen: usize,
address: S,
- cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
-) -> RecvMsg<'b, S>
+) -> RecvMsg<'a, 'i, S>
where S: SockaddrLike
{
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
let cmsghdr = {
if mhdr.msg_controllen > 0 {
- // got control message(s)
- cmsg_buffer
- .as_mut()
- .unwrap()
- .set_len(mhdr.msg_controllen as usize);
debug_assert!(!mhdr.msg_control.is_null());
debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
CMSG_FIRSTHDR(&mhdr as *const msghdr)
@@ -1705,38 +1938,43 @@ unsafe fn read_mhdr<'a, 'b, S>(
address: Some(address),
flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
mhdr,
+ iobufs: std::marker::PhantomData,
}
}
-unsafe fn pack_mhdr_to_receive<'outer, 'inner, I, S>(
- iov: I,
- cmsg_buffer: &mut Option<&mut Vec<u8>>,
+/// Pack pointers to various structures into into msghdr
+///
+/// # Safety
+/// `iov_buffer` and `iov_buffer_len` must point to a slice
+/// of `IoSliceMut` and number of available elements or be a null pointer and 0
+///
+/// `cmsg_buffer` and `cmsg_capacity` must point to a byte buffer used
+/// to store control headers later or be a null pointer and 0 if control
+/// headers are not used
+///
+/// Buffers must remain valid for the whole lifetime of msghdr
+unsafe fn pack_mhdr_to_receive<S>(
+ iov_buffer: *const IoSliceMut,
+ iov_buffer_len: usize,
+ cmsg_buffer: *const u8,
+ cmsg_capacity: usize,
address: *mut S,
-) -> (usize, msghdr)
+) -> msghdr
where
- I: AsRef<[IoSliceMut<'inner>]> + 'outer,
- S: SockaddrLike + 'outer
+ S: SockaddrLike
{
- let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
- .map(|v| (v.as_mut_ptr(), v.capacity()))
- .unwrap_or((ptr::null_mut(), 0));
-
- let mhdr = {
- // Musl's msghdr has private fields, so this is the only way to
- // initialize it.
- let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
- let p = mhdr.as_mut_ptr();
- (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
- (*p).msg_namelen = S::size();
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
- (*p).msg_iovlen = iov.as_ref().len() as _;
- (*p).msg_control = msg_control as *mut c_void;
- (*p).msg_controllen = msg_controllen as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
- };
-
- (msg_controllen, mhdr)
+ // Musl's msghdr has private fields, so this is the only way to
+ // initialize it.
+ let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
+ let p = mhdr.as_mut_ptr();
+ (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
+ (*p).msg_namelen = S::size();
+ (*p).msg_iov = iov_buffer as *mut iovec;
+ (*p).msg_iovlen = iov_buffer_len as _;
+ (*p).msg_control = cmsg_buffer as *mut c_void;
+ (*p).msg_controllen = cmsg_capacity as _;
+ (*p).msg_flags = 0;
+ mhdr.assume_init()
}
fn pack_mhdr_to_send<'a, I, C, S>(
@@ -1808,24 +2046,27 @@ fn pack_mhdr_to_send<'a, I, C, S>(
/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'inner>],
mut cmsg_buffer: Option<&'a mut Vec<u8>>,
- flags: MsgFlags) -> Result<RecvMsg<'a, S>>
- where S: SockaddrLike + 'a
+ flags: MsgFlags) -> Result<RecvMsg<'a, 'inner, S>>
+ where S: SockaddrLike + 'a,
+ 'inner: 'outer
{
let mut address = mem::MaybeUninit::uninit();
- let (msg_controllen, mut mhdr) = unsafe {
- pack_mhdr_to_receive::<_, S>(iov, &mut cmsg_buffer, address.as_mut_ptr())
+ let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
+ .map(|v| (v.as_mut_ptr(), v.capacity()))
+ .unwrap_or((ptr::null_mut(), 0));
+ let mut mhdr = unsafe {
+ pack_mhdr_to_receive(iov.as_ref().as_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
};
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
let r = Errno::result(ret)?;
- Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) })
+ Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) })
}
}
-
/// Create an endpoint for communication
///
/// The `protocol` specifies a particular protocol to be used with the
@@ -1836,7 +2077,12 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i
/// specified in this manner.
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
-pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
+pub fn socket<T: Into<Option<SockProtocol>>>(
+ domain: AddressFamily,
+ ty: SockType,
+ flags: SockFlag,
+ protocol: T,
+) -> Result<RawFd> {
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
@@ -1856,8 +2102,12 @@ pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType
/// Create a pair of connected sockets
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
-pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
- flags: SockFlag) -> Result<(RawFd, RawFd)> {
+pub fn socketpair<T: Into<Option<SockProtocol>>>(
+ domain: AddressFamily,
+ ty: SockType,
+ protocol: T,
+ flags: SockFlag,
+) -> Result<(RawFd, RawFd)> {
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
@@ -1871,7 +2121,9 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: Sock
let mut fds = [-1, -1];
- let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
+ let res = unsafe {
+ libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
+ };
Errno::result(res)?;
Ok((fds[0], fds[1]))
@@ -1890,9 +2142,7 @@ pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
pub fn bind(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
- let res = unsafe {
- libc::bind(fd, addr.as_ptr(), addr.len())
- };
+ let res = unsafe { libc::bind(fd, addr.as_ptr(), addr.len()) };
Errno::result(res).map(drop)
}
@@ -1909,24 +2159,28 @@ pub fn accept(sockfd: RawFd) -> Result<RawFd> {
/// Accept a connection on a socket
///
/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
-#[cfg(any(all(
- target_os = "android",
- any(
- target_arch = "aarch64",
- target_arch = "x86",
- target_arch = "x86_64"
- )
- ),
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(any(
+ all(
+ target_os = "android",
+ any(
+ target_arch = "aarch64",
+ target_arch = "x86",
+ target_arch = "x86_64"
+ )
+ ),
+ target_os = "dragonfly",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
- let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
+ let res = unsafe {
+ libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits())
+ };
Errno::result(res)
}
@@ -1935,9 +2189,7 @@ pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
pub fn connect(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
- let res = unsafe {
- libc::connect(fd, addr.as_ptr(), addr.len())
- };
+ let res = unsafe { libc::connect(fd, addr.as_ptr(), addr.len()) };
Errno::result(res).map(drop)
}
@@ -1952,7 +2204,8 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
sockfd,
buf.as_ptr() as *mut c_void,
buf.len() as size_t,
- flags.bits());
+ flags.bits(),
+ );
Errno::result(ret).map(|r| r as usize)
}
@@ -1963,9 +2216,10 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
/// address of the sender.
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
-pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
- -> Result<(usize, Option<T>)>
-{
+pub fn recvfrom<T: SockaddrLike>(
+ sockfd: RawFd,
+ buf: &mut [u8],
+) -> Result<(usize, Option<T>)> {
unsafe {
let mut addr = mem::MaybeUninit::<T>::uninit();
let mut len = mem::size_of_val(&addr) as socklen_t;
@@ -1976,11 +2230,15 @@ pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
buf.len() as size_t,
0,
addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len as *mut socklen_t))? as usize;
-
- Ok((ret, T::from_raw(
- addr.assume_init().as_ptr() as *const libc::sockaddr,
- Some(len))
+ &mut len as *mut socklen_t,
+ ))? as usize;
+
+ Ok((
+ ret,
+ T::from_raw(
+ addr.assume_init().as_ptr() as *const libc::sockaddr,
+ Some(len),
+ ),
))
}
}
@@ -1988,7 +2246,12 @@ pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
/// Send a message to a socket
///
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
-pub fn sendto(fd: RawFd, buf: &[u8], addr: &dyn SockaddrLike, flags: MsgFlags) -> Result<usize> {
+pub fn sendto(
+ fd: RawFd,
+ buf: &[u8],
+ addr: &dyn SockaddrLike,
+ flags: MsgFlags,
+) -> Result<usize> {
let ret = unsafe {
libc::sendto(
fd,
@@ -1996,7 +2259,7 @@ pub fn sendto(fd: RawFd, buf: &[u8], addr: &dyn SockaddrLike, flags: MsgFlags) -
buf.len() as size_t,
flags.bits(),
addr.as_ptr(),
- addr.len()
+ addr.len(),
)
};
@@ -2008,7 +2271,12 @@ pub fn sendto(fd: RawFd, buf: &[u8], addr: &dyn SockaddrLike, flags: MsgFlags) -
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
- libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
+ libc::send(
+ fd,
+ buf.as_ptr() as *const c_void,
+ buf.len() as size_t,
+ flags.bits(),
+ )
};
Errno::result(ret).map(|r| r as usize)
@@ -2021,7 +2289,7 @@ pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
*/
/// Represents a socket option that can be retrieved.
-pub trait GetSockOpt : Copy {
+pub trait GetSockOpt: Copy {
type Val;
/// Look up the value of this socket option on the given socket.
@@ -2029,7 +2297,7 @@ pub trait GetSockOpt : Copy {
}
/// Represents a socket option that can be set.
-pub trait SetSockOpt : Clone {
+pub trait SetSockOpt: Clone {
type Val;
/// Set the value of this socket option on the given socket.
@@ -2060,7 +2328,11 @@ pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
/// let res = setsockopt(fd, KeepAlive, &true);
/// assert!(res.is_ok());
/// ```
-pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
+pub fn setsockopt<O: SetSockOpt>(
+ fd: RawFd,
+ opt: O,
+ val: &O::Val,
+) -> Result<()> {
opt.set(fd, val)
}
@@ -2075,13 +2347,12 @@ pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let ret = libc::getpeername(
fd,
addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len
+ &mut len,
);
Errno::result(ret)?;
- T::from_raw(addr.assume_init().as_ptr(), Some(len))
- .ok_or(Errno::EINVAL)
+ T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
}
}
@@ -2096,13 +2367,12 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
let ret = libc::getsockname(
fd,
addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len
+ &mut len,
);
Errno::result(ret)?;
- T::from_raw(addr.assume_init().as_ptr(), Some(len))
- .ok_or(Errno::EINVAL)
+ T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
}
}
@@ -2121,8 +2391,8 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
#[allow(deprecated)]
pub fn sockaddr_storage_to_addr(
addr: &sockaddr_storage,
- len: usize) -> Result<SockAddr> {
-
+ len: usize,
+) -> Result<SockAddr> {
assert!(len <= mem::size_of::<sockaddr_storage>());
if len < mem::size_of_val(&addr.ss_family) {
return Err(Errno::ENOTCONN);
@@ -2131,7 +2401,7 @@ pub fn sockaddr_storage_to_addr(
match c_int::from(addr.ss_family) {
#[cfg(feature = "net")]
libc::AF_INET => {
- assert!(len as usize >= mem::size_of::<sockaddr_in>());
+ assert!(len >= mem::size_of::<sockaddr_in>());
let sin = unsafe {
*(addr as *const sockaddr_storage as *const sockaddr_in)
};
@@ -2139,19 +2409,15 @@ pub fn sockaddr_storage_to_addr(
}
#[cfg(feature = "net")]
libc::AF_INET6 => {
- assert!(len as usize >= mem::size_of::<sockaddr_in6>());
- let sin6 = unsafe {
- *(addr as *const _ as *const sockaddr_in6)
- };
+ assert!(len >= mem::size_of::<sockaddr_in6>());
+ let sin6 = unsafe { *(addr as *const _ as *const sockaddr_in6) };
Ok(SockAddr::Inet(InetAddr::V6(sin6)))
}
- libc::AF_UNIX => {
- unsafe {
- let sun = *(addr as *const _ as *const sockaddr_un);
- let sun_len = len.try_into().unwrap();
- Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, sun_len)))
- }
- }
+ libc::AF_UNIX => unsafe {
+ let sun = *(addr as *const _ as *const sockaddr_un);
+ let sun_len = len.try_into().unwrap();
+ Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, sun_len)))
+ },
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
libc::AF_PACKET => {
@@ -2160,40 +2426,31 @@ pub fn sockaddr_storage_to_addr(
// Apparently the Linux kernel can return smaller sizes when
// the value in the last element of sockaddr_ll (`sll_addr`) is
// smaller than the declared size of that field
- let sll = unsafe {
- *(addr as *const _ as *const sockaddr_ll)
- };
+ let sll = unsafe { *(addr as *const _ as *const sockaddr_ll) };
Ok(SockAddr::Link(LinkAddr(sll)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_NETLINK => {
use libc::sockaddr_nl;
- let snl = unsafe {
- *(addr as *const _ as *const sockaddr_nl)
- };
+ let snl = unsafe { *(addr as *const _ as *const sockaddr_nl) };
Ok(SockAddr::Netlink(NetlinkAddr(snl)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_ALG => {
use libc::sockaddr_alg;
- let salg = unsafe {
- *(addr as *const _ as *const sockaddr_alg)
- };
+ let salg = unsafe { *(addr as *const _ as *const sockaddr_alg) };
Ok(SockAddr::Alg(AlgAddr(salg)))
}
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_VSOCK => {
use libc::sockaddr_vm;
- let svm = unsafe {
- *(addr as *const _ as *const sockaddr_vm)
- };
+ let svm = unsafe { *(addr as *const _ as *const sockaddr_vm) };
Ok(SockAddr::Vsock(VsockAddr(svm)))
}
af => panic!("unexpected address family {}", af),
}
}
-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Shutdown {
/// Further receptions will be disallowed.
@@ -2212,9 +2469,9 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
use libc::shutdown;
let how = match how {
- Shutdown::Read => libc::SHUT_RD,
+ Shutdown::Read => libc::SHUT_RD,
Shutdown::Write => libc::SHUT_WR,
- Shutdown::Both => libc::SHUT_RDWR,
+ Shutdown::Both => libc::SHUT_RDWR,
};
Errno::result(shutdown(df, how)).map(drop)
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 1cbb223..06e9ee4 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -1,18 +1,18 @@
//! Socket options as used by `setsockopt` and `getsockopt`.
-use cfg_if::cfg_if;
use super::{GetSockOpt, SetSockOpt};
-use crate::Result;
use crate::errno::Errno;
use crate::sys::time::TimeVal;
+use crate::Result;
+use cfg_if::cfg_if;
use libc::{self, c_int, c_void, socklen_t};
-use std::mem::{
- self,
- MaybeUninit
-};
-use std::os::unix::io::RawFd;
use std::ffi::{OsStr, OsString};
+use std::{
+ convert::TryFrom,
+ mem::{self, MaybeUninit}
+};
#[cfg(target_family = "unix")]
use std::os::unix::ffi::OsStrExt;
+use std::os::unix::io::RawFd;
// Constants
// TCP_CA_NAME_MAX isn't defined in user space include files
@@ -51,14 +51,18 @@ macro_rules! setsockopt_impl {
unsafe {
let setter: $setter = Set::new(val);
- let res = libc::setsockopt(fd, $level, $flag,
- setter.ffi_ptr(),
- setter.ffi_len());
+ let res = libc::setsockopt(
+ fd,
+ $level,
+ $flag,
+ setter.ffi_ptr(),
+ setter.ffi_len(),
+ );
Errno::result(res).map(drop)
}
}
}
- }
+ };
}
/// Helper for implementing `GetSockOpt` for a given socket option. See
@@ -92,16 +96,23 @@ macro_rules! getsockopt_impl {
unsafe {
let mut getter: $getter = Get::uninit();
- let res = libc::getsockopt(fd, $level, $flag,
- getter.ffi_ptr(),
- getter.ffi_len());
+ let res = libc::getsockopt(
+ fd,
+ $level,
+ $flag,
+ getter.ffi_ptr(),
+ getter.ffi_len(),
+ );
Errno::result(res)?;
- Ok(getter.assume_init())
+ match <$ty>::try_from(getter.assume_init()) {
+ Err(_) => Err(Errno::EINVAL),
+ Ok(r) => Ok(r)
+ }
}
}
}
- }
+ };
}
/// Helper to generate the sockopt accessors. See
@@ -248,13 +259,22 @@ macro_rules! sockopt_impl {
sockopt_impl!(
/// Enables local address reuse
- ReuseAddr, Both, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool
+ ReuseAddr,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_REUSEADDR,
+ bool
);
#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
sockopt_impl!(
/// Permits multiple AF_INET or AF_INET6 sockets to be bound to an
/// identical socket address.
- ReusePort, Both, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
+ ReusePort,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_REUSEPORT,
+ bool
+);
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -265,24 +285,42 @@ sockopt_impl!(
/// send a stream of mouse events which receive no replies, this
/// packetization may cause significant delays. The boolean option
/// TCP_NODELAY defeats this algorithm.
- TcpNoDelay, Both, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
+ TcpNoDelay,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_NODELAY,
+ bool
+);
sockopt_impl!(
/// 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, Both, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
+ Linger,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_LINGER,
+ libc::linger
+);
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Join a multicast group
- IpAddMembership, SetOnly, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP,
- super::IpMembershipRequest);
+ IpAddMembership,
+ SetOnly,
+ libc::IPPROTO_IP,
+ libc::IP_ADD_MEMBERSHIP,
+ super::IpMembershipRequest
+);
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Leave a multicast group.
- IpDropMembership, SetOnly, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP,
- super::IpMembershipRequest);
+ IpDropMembership,
+ SetOnly,
+ libc::IPPROTO_IP,
+ libc::IP_DROP_MEMBERSHIP,
+ super::IpMembershipRequest
+);
cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
#[cfg(feature = "net")]
@@ -322,74 +360,180 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Set or read the time-to-live value of outgoing multicast packets for
/// this socket.
- IpMulticastTtl, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
+ IpMulticastTtl,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_MULTICAST_TTL,
+ u8
+);
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Set or read a boolean integer argument that determines whether sent
/// multicast packets should be looped back to the local sockets.
- IpMulticastLoop, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
+ IpMulticastLoop,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_MULTICAST_LOOP,
+ bool
+);
+#[cfg(target_os = "linux")]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// Set the protocol-defined priority for all packets to be
+ /// sent on this socket
+ Priority,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_PRIORITY,
+ libc::c_int
+);
+#[cfg(target_os = "linux")]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[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
+ IpTos,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_TOS,
+ libc::c_int
+);
+#[cfg(target_os = "linux")]
+#[cfg(feature = "net")]
+sockopt_impl!(
+ #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
+ /// Traffic class associated with outgoing packets
+ Ipv6TClass,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_TCLASS,
+ libc::c_int
+);
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// If enabled, this boolean option allows binding to an IP address that
/// is nonlocal or does not (yet) exist.
- IpFreebind, Both, libc::IPPROTO_IP, libc::IP_FREEBIND, bool);
+ IpFreebind,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_FREEBIND,
+ bool
+);
sockopt_impl!(
/// Specify the receiving timeout until reporting an error.
- ReceiveTimeout, Both, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
+ ReceiveTimeout,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_RCVTIMEO,
+ TimeVal
+);
sockopt_impl!(
/// Specify the sending timeout until reporting an error.
- SendTimeout, Both, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
+ SendTimeout,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_SNDTIMEO,
+ TimeVal
+);
sockopt_impl!(
/// Set or get the broadcast flag.
- Broadcast, Both, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
+ Broadcast,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_BROADCAST,
+ bool
+);
sockopt_impl!(
/// If this option is enabled, out-of-band data is directly placed into
/// the receive data stream.
- OobInline, Both, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
+ OobInline,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_OOBINLINE,
+ bool
+);
sockopt_impl!(
/// Get and clear the pending socket error.
- SocketError, GetOnly, libc::SOL_SOCKET, libc::SO_ERROR, i32);
+ SocketError,
+ GetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_ERROR,
+ i32
+);
sockopt_impl!(
/// Set or get the don't route flag.
- DontRoute, Both, libc::SOL_SOCKET, libc::SO_DONTROUTE, bool);
+ DontRoute,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_DONTROUTE,
+ bool
+);
sockopt_impl!(
/// Enable sending of keep-alive messages on connection-oriented sockets.
- KeepAlive, Both, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
+ KeepAlive,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_KEEPALIVE,
+ bool
+);
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "ios"
))]
sockopt_impl!(
/// Get the credentials of the peer process of a connected unix domain
/// socket.
- LocalPeerCred, GetOnly, 0, libc::LOCAL_PEERCRED, super::XuCred);
+ LocalPeerCred,
+ GetOnly,
+ 0,
+ libc::LOCAL_PEERCRED,
+ super::XuCred
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Return the credentials of the foreign process connected to this socket.
- PeerCredentials, GetOnly, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
-#[cfg(any(target_os = "ios",
- target_os = "macos"))]
+ PeerCredentials,
+ GetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_PEERCRED,
+ super::UnixCredentials
+);
+#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Specify the amount of time, in seconds, that the connection must be idle
/// before keepalive probes (if enabled) are sent.
- TcpKeepAlive, Both, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"))]
+ TcpKeepAlive,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_KEEPALIVE,
+ u32
+);
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux"
+))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The time (in seconds) the connection needs to remain idle before TCP
/// starts sending keepalive probes
- TcpKeepIdle, Both, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
+ TcpKeepIdle,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_KEEPIDLE,
+ u32
+);
cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
sockopt_impl!(
@@ -407,20 +551,33 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The maximum number of keepalive probes TCP should send before
/// dropping the connection.
- TcpKeepCount, Both, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
-#[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"))]
+ TcpKeepCount,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_KEEPCNT,
+ u32
+);
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
- TcpRepair, Both, libc::IPPROTO_TCP, libc::TCP_REPAIR, u32);
+ TcpRepair,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_REPAIR,
+ u32
+);
#[cfg(not(any(target_os = "openbsd", target_os = "haiku")))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The time (in seconds) between individual keepalive probes.
- TcpKeepInterval, Both, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
+ TcpKeepInterval,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_KEEPINTVL,
+ u32
+);
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
@@ -428,98 +585,194 @@ sockopt_impl!(
/// Specifies the maximum amount of time in milliseconds that transmitted
/// data may remain unacknowledged before TCP will forcibly close the
/// corresponding connection
- TcpUserTimeout, Both, libc::IPPROTO_TCP, libc::TCP_USER_TIMEOUT, u32);
+ TcpUserTimeout,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_USER_TIMEOUT,
+ u32
+);
sockopt_impl!(
/// Sets or gets the maximum socket receive buffer in bytes.
- RcvBuf, Both, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
+ RcvBuf,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_RCVBUF,
+ usize
+);
sockopt_impl!(
/// Sets or gets the maximum socket send buffer in bytes.
- SndBuf, Both, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
+ SndBuf,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_SNDBUF,
+ usize
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
/// perform the same task as `SO_RCVBUF`, but the `rmem_max limit` can be
/// overridden.
- RcvBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
+ RcvBufForce,
+ SetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_RCVBUFFORCE,
+ usize
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
/// perform the same task as `SO_SNDBUF`, but the `wmem_max` limit can be
/// overridden.
- SndBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
+ SndBufForce,
+ SetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_SNDBUFFORCE,
+ usize
+);
sockopt_impl!(
/// Gets the socket type as an integer.
- SockType, GetOnly, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
+ SockType,
+ GetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_TYPE,
+ super::SockType,
+ GetStruct<i32>
+);
sockopt_impl!(
/// Returns a value indicating whether or not this socket has been marked to
/// accept connections with `listen(2)`.
- AcceptConn, GetOnly, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
+ AcceptConn,
+ GetOnly,
+ libc::SOL_SOCKET,
+ libc::SO_ACCEPTCONN,
+ bool
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Bind this socket to a particular device like “eth0”.
- BindToDevice, Both, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
+ BindToDevice,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_BINDTODEVICE,
+ OsString<[u8; libc::IFNAMSIZ]>
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
#[allow(missing_docs)]
// Not documented by Linux!
- OriginalDst, GetOnly, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
+ OriginalDst,
+ GetOnly,
+ libc::SOL_IP,
+ libc::SO_ORIGINAL_DST,
+ libc::sockaddr_in
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
#[allow(missing_docs)]
// Not documented by Linux!
- Ip6tOriginalDst, GetOnly, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6);
+ Ip6tOriginalDst,
+ GetOnly,
+ libc::SOL_IPV6,
+ libc::IP6T_SO_ORIGINAL_DST,
+ libc::sockaddr_in6
+);
#[cfg(any(target_os = "linux"))]
sockopt_impl!(
/// Specifies exact type of timestamping information collected by the kernel
/// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- Timestamping, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMPING, super::TimestampingFlag);
+ Timestamping,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_TIMESTAMPING,
+ super::TimestampingFlag
+);
#[cfg(not(target_os = "haiku"))]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
- ReceiveTimestamp, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
+ ReceiveTimestamp,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_TIMESTAMP,
+ bool
+);
#[cfg(all(target_os = "linux"))]
sockopt_impl!(
/// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message.
- ReceiveTimestampns, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);
+ ReceiveTimestampns,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_TIMESTAMPNS,
+ bool
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Setting this boolean option enables transparent proxying on this socket.
- IpTransparent, Both, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
+ IpTransparent,
+ Both,
+ libc::SOL_IP,
+ libc::IP_TRANSPARENT,
+ bool
+);
#[cfg(target_os = "openbsd")]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Allows the socket to be bound to addresses which are not local to the
/// machine, so it can be used to make a transparent proxy.
- BindAny, Both, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
+ BindAny,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_BINDANY,
+ bool
+);
#[cfg(target_os = "freebsd")]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Can `bind(2)` to any address, even one not bound to any available
/// network interface in the system.
- BindAny, Both, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
+ BindAny,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_BINDANY,
+ bool
+);
#[cfg(target_os = "linux")]
sockopt_impl!(
/// Set the mark for each packet sent through this socket (similar to the
/// netfilter MARK target but socket-based).
- Mark, Both, libc::SOL_SOCKET, libc::SO_MARK, u32);
+ Mark,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_MARK,
+ u32
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Enable or disable the receiving of the `SCM_CREDENTIALS` control
/// message.
- PassCred, Both, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
+ PassCred,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_PASSCRED,
+ bool
+);
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// This option allows the caller to set the TCP congestion control
/// algorithm to be used, on a per-socket basis.
- TcpCongestion, Both, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
+ TcpCongestion,
+ Both,
+ libc::IPPROTO_TCP,
+ libc::TCP_CONGESTION,
+ OsString<[u8; TCP_CA_NAME_MAX]>
+);
#[cfg(any(
target_os = "android",
target_os = "ios",
@@ -532,7 +785,12 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Pass an `IP_PKTINFO` ancillary message that contains a pktinfo
/// structure that supplies some information about the incoming packet.
- Ipv4PacketInfo, Both, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
+ Ipv4PacketInfo,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_PKTINFO,
+ bool
+);
#[cfg(any(
target_os = "android",
target_os = "freebsd",
@@ -547,7 +805,12 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// Set delivery of the `IPV6_PKTINFO` control message on incoming
/// datagrams.
- Ipv6RecvPacketInfo, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
+ Ipv6RecvPacketInfo,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_RECVPKTINFO,
+ bool
+);
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
@@ -560,7 +823,12 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The `recvmsg(2)` call returns a `struct sockaddr_dl` corresponding to
/// the interface on which the packet was received.
- Ipv4RecvIf, Both, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
+ Ipv4RecvIf,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_RECVIF,
+ bool
+);
#[cfg(any(
target_os = "freebsd",
target_os = "ios",
@@ -573,72 +841,146 @@ sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The `recvmsg(2)` call will return the destination IP address for a UDP
/// datagram.
- Ipv4RecvDstAddr, Both, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
+ Ipv4RecvDstAddr,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_RECVDSTADDR,
+ bool
+);
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
#[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
/// datagram.
- Ipv4OrigDstAddr, Both, libc::IPPROTO_IP, libc::IP_ORIGDSTADDR, bool);
+ Ipv4OrigDstAddr,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_ORIGDSTADDR,
+ bool
+);
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
#[allow(missing_docs)]
// Not documented by Linux!
- UdpGsoSegment, Both, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
+ UdpGsoSegment,
+ Both,
+ libc::SOL_UDP,
+ libc::UDP_SEGMENT,
+ libc::c_int
+);
#[cfg(target_os = "linux")]
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
#[allow(missing_docs)]
// Not documented by Linux!
- UdpGroSegment, Both, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
+ UdpGroSegment,
+ Both,
+ libc::IPPROTO_UDP,
+ libc::UDP_GRO,
+ bool
+);
#[cfg(target_os = "linux")]
sockopt_impl!(
/// Configures the behavior of time-based transmission of packets, for use
/// with the `TxTime` control message.
- TxTime, Both, libc::SOL_SOCKET, libc::SO_TXTIME, libc::sock_txtime);
+ TxTime,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_TXTIME,
+ libc::sock_txtime
+);
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
sockopt_impl!(
/// Indicates that an unsigned 32-bit value ancillary message (cmsg) should
/// be attached to received skbs indicating the number of packets dropped by
/// the socket since its creation.
- RxqOvfl, Both, libc::SOL_SOCKET, libc::SO_RXQ_OVFL, libc::c_int);
+ RxqOvfl,
+ Both,
+ libc::SOL_SOCKET,
+ libc::SO_RXQ_OVFL,
+ libc::c_int
+);
#[cfg(feature = "net")]
sockopt_impl!(
#[cfg_attr(docsrs, doc(cfg(feature = "net")))]
/// The socket is restricted to sending and receiving IPv6 packets only.
- Ipv6V6Only, Both, libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, bool);
+ Ipv6V6Only,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_V6ONLY,
+ bool
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Enable extended reliable error message passing.
- Ipv4RecvErr, Both, libc::IPPROTO_IP, libc::IP_RECVERR, bool);
+ Ipv4RecvErr,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_RECVERR,
+ bool
+);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(
/// Control receiving of asynchronous error options.
- Ipv6RecvErr, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVERR, bool);
+ Ipv6RecvErr,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_RECVERR,
+ bool
+);
+#[cfg(any(target_os = "android", target_os = "linux"))]
+sockopt_impl!(
+ /// Fetch the current system-estimated Path MTU.
+ IpMtu,
+ GetOnly,
+ libc::IPPROTO_IP,
+ libc::IP_MTU,
+ libc::c_int
+);
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
sockopt_impl!(
/// Set or retrieve the current time-to-live field that is used in every
/// packet sent from this socket.
- Ipv4Ttl, Both, libc::IPPROTO_IP, libc::IP_TTL, libc::c_int);
+ Ipv4Ttl,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_TTL,
+ libc::c_int
+);
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
sockopt_impl!(
/// Set the unicast hop limit for the socket.
- Ipv6Ttl, Both, libc::IPPROTO_IPV6, libc::IPV6_UNICAST_HOPS, libc::c_int);
+ Ipv6Ttl,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_UNICAST_HOPS,
+ libc::c_int
+);
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
#[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
/// datagram.
- Ipv6OrigDstAddr, Both, libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR, bool);
+ Ipv6OrigDstAddr,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_ORIGDSTADDR,
+ bool
+);
#[cfg(any(target_os = "ios", target_os = "macos"))]
sockopt_impl!(
/// Set "don't fragment packet" flag on the IP packet.
- IpDontFrag, Both, libc::IPPROTO_IP, libc::IP_DONTFRAG, bool);
+ IpDontFrag,
+ Both,
+ libc::IPPROTO_IP,
+ libc::IP_DONTFRAG,
+ bool
+);
#[cfg(any(
target_os = "android",
target_os = "ios",
@@ -647,7 +989,12 @@ sockopt_impl!(
))]
sockopt_impl!(
/// Set "don't fragment packet" flag on the IPv6 packet.
- Ipv6DontFrag, Both, libc::IPPROTO_IPV6, libc::IPV6_DONTFRAG, bool);
+ Ipv6DontFrag,
+ Both,
+ libc::IPPROTO_IPV6,
+ libc::IPV6_DONTFRAG,
+ bool
+);
#[allow(missing_docs)]
// Not documented by Linux!
@@ -663,11 +1010,13 @@ impl SetSockOpt for AlgSetAeadAuthSize {
fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
unsafe {
- let res = libc::setsockopt(fd,
- libc::SOL_ALG,
- libc::ALG_SET_AEAD_AUTHSIZE,
- ::std::ptr::null(),
- *val as libc::socklen_t);
+ let res = libc::setsockopt(
+ fd,
+ libc::SOL_ALG,
+ libc::ALG_SET_AEAD_AUTHSIZE,
+ ::std::ptr::null(),
+ *val as libc::socklen_t,
+ );
Errno::result(res).map(drop)
}
}
@@ -687,16 +1036,21 @@ impl<T> Default for AlgSetKey<T> {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
-impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
+impl<T> SetSockOpt for AlgSetKey<T>
+where
+ T: AsRef<[u8]> + Clone,
+{
type Val = T;
fn set(&self, fd: RawFd, val: &T) -> Result<()> {
unsafe {
- let res = libc::setsockopt(fd,
- libc::SOL_ALG,
- libc::ALG_SET_KEY,
- val.as_ref().as_ptr() as *const _,
- val.as_ref().len() as libc::socklen_t);
+ let res = libc::setsockopt(
+ fd,
+ libc::SOL_ALG,
+ libc::ALG_SET_KEY,
+ val.as_ref().as_ptr() as *const _,
+ val.as_ref().len() as libc::socklen_t,
+ );
Errno::result(res).map(drop)
}
}
@@ -757,7 +1111,11 @@ impl<T> Get<T> for GetStruct<T> {
}
unsafe fn assume_init(self) -> T {
- assert_eq!(self.len as usize, mem::size_of::<T>(), "invalid getsockopt implementation");
+ assert_eq!(
+ self.len as usize,
+ mem::size_of::<T>(),
+ "invalid getsockopt implementation"
+ );
self.val.assume_init()
}
}
@@ -804,7 +1162,11 @@ impl Get<bool> for GetBool {
}
unsafe fn assume_init(self) -> bool {
- assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
+ assert_eq!(
+ self.len as usize,
+ mem::size_of::<c_int>(),
+ "invalid getsockopt implementation"
+ );
self.val.assume_init() != 0
}
}
@@ -816,7 +1178,9 @@ struct SetBool {
impl<'a> Set<'a, bool> for SetBool {
fn new(val: &'a bool) -> SetBool {
- SetBool { val: if *val { 1 } else { 0 } }
+ SetBool {
+ val: i32::from(*val),
+ }
}
fn ffi_ptr(&self) -> *const c_void {
@@ -851,7 +1215,11 @@ impl Get<u8> for GetU8 {
}
unsafe fn assume_init(self) -> u8 {
- assert_eq!(self.len as usize, mem::size_of::<u8>(), "invalid getsockopt implementation");
+ assert_eq!(
+ self.len as usize,
+ mem::size_of::<u8>(),
+ "invalid getsockopt implementation"
+ );
self.val.assume_init()
}
}
@@ -863,7 +1231,7 @@ struct SetU8 {
impl<'a> Set<'a, u8> for SetU8 {
fn new(val: &'a u8) -> SetU8 {
- SetU8 { val: *val as u8 }
+ SetU8 { val: *val }
}
fn ffi_ptr(&self) -> *const c_void {
@@ -898,7 +1266,11 @@ impl Get<usize> for GetUsize {
}
unsafe fn assume_init(self) -> usize {
- assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
+ assert_eq!(
+ self.len as usize,
+ mem::size_of::<c_int>(),
+ "invalid getsockopt implementation"
+ );
self.val.assume_init() as usize
}
}
@@ -958,7 +1330,9 @@ struct SetOsString<'a> {
impl<'a> Set<'a, OsString> for SetOsString<'a> {
fn new(val: &'a OsString) -> SetOsString {
- SetOsString { val: val.as_os_str() }
+ SetOsString {
+ val: val.as_os_str(),
+ }
}
fn ffi_ptr(&self) -> *const c_void {
@@ -970,7 +1344,6 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> {
}
}
-
#[cfg(test)]
mod test {
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -978,7 +1351,13 @@ mod test {
fn can_get_peercred_on_unix_socket() {
use super::super::*;
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
+ let (a, b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
assert_eq!(a_cred, b_cred);
@@ -990,7 +1369,13 @@ mod test {
use super::super::*;
use crate::unistd::close;
- let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
+ let (a, b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
let a_type = getsockopt(a, super::SockType).unwrap();
assert_eq!(a_type, SockType::Stream);
close(a).unwrap();
@@ -1002,20 +1387,31 @@ mod test {
use super::super::*;
use crate::unistd::close;
- let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
let s_type = getsockopt(s, super::SockType).unwrap();
assert_eq!(s_type, SockType::Datagram);
close(s).unwrap();
}
- #[cfg(any(target_os = "freebsd",
- target_os = "linux"))]
+ #[cfg(any(target_os = "freebsd", target_os = "linux"))]
#[test]
fn can_get_listen_on_tcp_socket() {
use super::super::*;
use crate::unistd::close;
- let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
let s_listening = getsockopt(s, super::AcceptConn).unwrap();
assert!(!s_listening);
listen(s, 10).unwrap();
@@ -1023,5 +1419,4 @@ mod test {
assert!(s_listening2);
close(s).unwrap();
}
-
}
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index 8b7627d..78203bf 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -1,4 +1,3 @@
-pub use libc::{dev_t, mode_t};
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
pub use libc::c_uint;
#[cfg(any(
@@ -8,13 +7,14 @@ pub use libc::c_uint;
))]
pub use libc::c_ulong;
pub use libc::stat as FileStat;
+pub use libc::{dev_t, mode_t};
-use crate::{Result, NixPath, errno::Errno};
#[cfg(not(target_os = "redox"))]
-use crate::fcntl::{AtFlags, at_rawfd};
+use crate::fcntl::{at_rawfd, AtFlags};
+use crate::sys::time::{TimeSpec, TimeVal};
+use crate::{errno::Errno, NixPath, Result};
use std::mem;
use std::os::unix::io::RawFd;
-use crate::sys::time::{TimeSpec, TimeVal};
libc_bitflags!(
/// "File type" flags for `mknod` and related functions.
@@ -33,25 +33,39 @@ libc_bitflags!(
libc_bitflags! {
/// "File mode / permissions" flags.
pub struct Mode: mode_t {
+ /// Read, write and execute for owner.
S_IRWXU;
+ /// Read for owner.
S_IRUSR;
+ /// Write for owner.
S_IWUSR;
+ /// Execute for owner.
S_IXUSR;
+ /// Read write and execute for group.
S_IRWXG;
+ /// Read fr group.
S_IRGRP;
+ /// Write for group.
S_IWGRP;
+ /// Execute for group.
S_IXGRP;
+ /// Read, write and execute for other.
S_IRWXO;
+ /// Read for other.
S_IROTH;
+ /// Write for other.
S_IWOTH;
+ /// Execute for other.
S_IXOTH;
+ /// Set user id on execution.
S_ISUID as mode_t;
+ /// Set group id on execution.
S_ISGID as mode_t;
S_ISVTX as mode_t;
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os="openbsd"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
pub type type_of_file_flag = c_uint;
#[cfg(any(
target_os = "netbsd",
@@ -156,7 +170,12 @@ libc_bitflags! {
}
/// Create a special or ordinary file, by pathname.
-pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
+pub fn mknod<P: ?Sized + NixPath>(
+ path: &P,
+ kind: SFlag,
+ perm: Mode,
+ dev: dev_t,
+) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
})?;
@@ -165,7 +184,12 @@ pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t)
}
/// Create a special or ordinary file, relative to a given directory.
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "haiku")))]
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "haiku"
+)))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn mknodat<P: ?Sized + NixPath>(
dirfd: RawFd,
@@ -175,7 +199,12 @@ pub fn mknodat<P: ?Sized + NixPath>(
dev: dev_t,
) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
- libc::mknodat(dirfd, cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
+ libc::mknodat(
+ dirfd,
+ cstr.as_ptr(),
+ kind.bits | perm.bits() as mode_t,
+ dev,
+ )
})?;
Errno::result(res).map(drop)
@@ -184,24 +213,22 @@ pub fn mknodat<P: ?Sized + NixPath>(
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn major(dev: dev_t) -> u64 {
- ((dev >> 32) & 0xffff_f000) |
- ((dev >> 8) & 0x0000_0fff)
+ ((dev >> 32) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn minor(dev: dev_t) -> u64 {
- ((dev >> 12) & 0xffff_ff00) |
- ((dev ) & 0x0000_00ff)
+ ((dev >> 12) & 0xffff_ff00) | ((dev) & 0x0000_00ff)
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const fn makedev(major: u64, minor: u64) -> dev_t {
- ((major & 0xffff_f000) << 32) |
- ((major & 0x0000_0fff) << 8) |
- ((minor & 0xffff_ff00) << 12) |
- (minor & 0x0000_00ff)
+ ((major & 0xffff_f000) << 32)
+ | ((major & 0x0000_0fff) << 8)
+ | ((minor & 0xffff_ff00) << 12)
+ | (minor & 0x0000_00ff)
}
pub fn umask(mode: Mode) -> Mode {
@@ -211,28 +238,24 @@ pub fn umask(mode: Mode) -> Mode {
pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
- }
+ let res = path.with_nix_path(|cstr| unsafe {
+ libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
})?;
Errno::result(res)?;
- Ok(unsafe{dst.assume_init()})
+ Ok(unsafe { dst.assume_init() })
}
pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| {
- unsafe {
- libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
- }
+ let res = path.with_nix_path(|cstr| unsafe {
+ libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
})?;
Errno::result(res)?;
- Ok(unsafe{dst.assume_init()})
+ Ok(unsafe { dst.assume_init() })
}
pub fn fstat(fd: RawFd) -> Result<FileStat> {
@@ -241,20 +264,29 @@ pub fn fstat(fd: RawFd) -> Result<FileStat> {
Errno::result(res)?;
- Ok(unsafe{dst.assume_init()})
+ Ok(unsafe { dst.assume_init() })
}
#[cfg(not(target_os = "redox"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
+pub fn fstatat<P: ?Sized + NixPath>(
+ dirfd: RawFd,
+ pathname: &P,
+ f: AtFlags,
+) -> Result<FileStat> {
let mut dst = mem::MaybeUninit::uninit();
- let res = pathname.with_nix_path(|cstr| {
- unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) }
+ let res = pathname.with_nix_path(|cstr| unsafe {
+ libc::fstatat(
+ dirfd,
+ cstr.as_ptr(),
+ dst.as_mut_ptr(),
+ f.bits() as libc::c_int,
+ )
})?;
Errno::result(res)?;
- Ok(unsafe{dst.assume_init()})
+ Ok(unsafe { dst.assume_init() })
}
/// Change the file permission bits of the file specified by a file descriptor.
@@ -299,11 +331,10 @@ pub fn fchmodat<P: ?Sized + NixPath>(
mode: Mode,
flag: FchmodatFlags,
) -> Result<()> {
- let atflag =
- match flag {
- FchmodatFlags::FollowSymlink => AtFlags::empty(),
- FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
+ 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),
@@ -326,7 +357,11 @@ pub fn fchmodat<P: ?Sized + NixPath>(
/// # References
///
/// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
-pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
+pub fn utimes<P: ?Sized + NixPath>(
+ path: &P,
+ atime: &TimeVal,
+ mtime: &TimeVal,
+) -> Result<()> {
let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
let res = path.with_nix_path(|cstr| unsafe {
libc::utimes(cstr.as_ptr(), &times[0])
@@ -345,14 +380,20 @@ pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -
/// # References
///
/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
-#[cfg(any(target_os = "linux",
- target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd"))]
+#[cfg(any(
+ target_os = "linux",
+ target_os = "haiku",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "freebsd",
+ target_os = "netbsd"
+))]
#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn lutimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
+pub fn lutimes<P: ?Sized + NixPath>(
+ path: &P,
+ atime: &TimeVal,
+ mtime: &TimeVal,
+) -> Result<()> {
let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
let res = path.with_nix_path(|cstr| unsafe {
libc::lutimes(cstr.as_ptr(), &times[0])
@@ -405,13 +446,12 @@ pub fn utimensat<P: ?Sized + NixPath>(
path: &P,
atime: &TimeSpec,
mtime: &TimeSpec,
- flag: UtimensatFlags
+ flag: UtimensatFlags,
) -> Result<()> {
- let atflag =
- match flag {
- UtimensatFlags::FollowSymlink => AtFlags::empty(),
- UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
+ let atflag = match flag {
+ UtimensatFlags::FollowSymlink => AtFlags::empty(),
+ UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
+ };
let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
let res = path.with_nix_path(|cstr| unsafe {
libc::utimensat(
@@ -427,9 +467,13 @@ pub fn utimensat<P: ?Sized + NixPath>(
#[cfg(not(target_os = "redox"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
- let res = path.with_nix_path(|cstr| {
- unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
+pub fn mkdirat<P: ?Sized + NixPath>(
+ fd: RawFd,
+ path: &P,
+ mode: Mode,
+) -> Result<()> {
+ let res = path.with_nix_path(|cstr| unsafe {
+ libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t)
})?;
Errno::result(res).map(drop)
diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs
index e8c06e4..9be8ca6 100644
--- a/src/sys/statfs.rs
+++ b/src/sys/statfs.rs
@@ -1,13 +1,28 @@
//! Get filesystem statistics, non-portably
//!
//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
+#[cfg(not(any(target_os = "linux", target_os = "android")))]
+use std::ffi::CStr;
use std::fmt::{self, Debug};
use std::mem;
use std::os::unix::io::AsRawFd;
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
-use std::ffi::CStr;
-use crate::{NixPath, Result, errno::Errno};
+use cfg_if::cfg_if;
+
+#[cfg(all(
+ feature = "mount",
+ any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )
+))]
+use crate::mount::MntFlags;
+#[cfg(target_os = "linux")]
+use crate::sys::statvfs::FsFlags;
+use crate::{errno::Errno, NixPath, Result};
/// Identifies a mounted file system
#[cfg(target_os = "android")]
@@ -18,10 +33,30 @@ pub type fsid_t = libc::__fsid_t;
#[cfg_attr(docsrs, doc(cfg(all())))]
pub type fsid_t = libc::fsid_t;
+cfg_if! {
+ if #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] {
+ type type_of_statfs = libc::statfs64;
+ const LIBC_FSTATFS: unsafe extern fn
+ (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
+ = libc::fstatfs64;
+ const LIBC_STATFS: unsafe extern 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
+ (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
+ = libc::fstatfs;
+ const LIBC_STATFS: unsafe extern fn
+ (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
+ = libc::statfs;
+ }
+}
+
/// Describes a mounted file system
#[derive(Clone, Copy)]
#[repr(transparent)]
-pub struct Statfs(libc::statfs);
+pub struct Statfs(type_of_statfs);
#[cfg(target_os = "freebsd")]
type fs_type_t = u32;
@@ -33,7 +68,14 @@ type fs_type_t = libc::c_uint;
type fs_type_t = libc::c_ulong;
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
type fs_type_t = libc::c_int;
-#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
+#[cfg(all(
+ target_os = "linux",
+ not(any(
+ target_arch = "s390x",
+ target_env = "musl",
+ target_env = "uclibc"
+ ))
+))]
type fs_type_t = libc::__fsword_t;
/// Describes the file system type as known by the operating system.
@@ -42,7 +84,10 @@ type fs_type_t = libc::__fsword_t;
target_os = "android",
all(target_os = "linux", target_arch = "s390x"),
all(target_os = "linux", target_env = "musl"),
- all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))),
+ all(
+ target_os = "linux",
+ not(any(target_arch = "s390x", target_env = "musl"))
+ ),
))]
#[derive(Eq, Copy, Clone, PartialEq, Debug)]
pub struct FsType(pub fs_type_t);
@@ -51,31 +96,38 @@ pub struct FsType(pub fs_type_t);
// can't very well document them here.
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
+pub const ADFS_SUPER_MAGIC: FsType =
+ FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
+pub const AFFS_SUPER_MAGIC: FsType =
+ FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const AUTOFS_SUPER_MAGIC: FsType = FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
+pub const AUTOFS_SUPER_MAGIC: FsType =
+ FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const BTRFS_SUPER_MAGIC: FsType = FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
+pub const BTRFS_SUPER_MAGIC: FsType =
+ FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
+pub const CGROUP2_SUPER_MAGIC: FsType =
+ FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
+pub const CGROUP_SUPER_MAGIC: FsType =
+ FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
+pub const CODA_SUPER_MAGIC: FsType =
+ FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
@@ -84,64 +136,82 @@ pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const DEVPTS_SUPER_MAGIC: FsType = FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
+pub const DEVPTS_SUPER_MAGIC: FsType =
+ FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const ECRYPTFS_SUPER_MAGIC: FsType = FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
+pub const ECRYPTFS_SUPER_MAGIC: FsType =
+ FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
+pub const EXT2_SUPER_MAGIC: FsType =
+ FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
+pub const EXT3_SUPER_MAGIC: FsType =
+ FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
+pub const EXT4_SUPER_MAGIC: FsType =
+ FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const F2FS_SUPER_MAGIC: FsType = FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
+pub const F2FS_SUPER_MAGIC: FsType =
+ FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const FUSE_SUPER_MAGIC: FsType = FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
+pub const FUSE_SUPER_MAGIC: FsType =
+ FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const FUTEXFS_SUPER_MAGIC: FsType = FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
+pub const FUTEXFS_SUPER_MAGIC: FsType =
+ FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const HOSTFS_SUPER_MAGIC: FsType = FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
+pub const HOSTFS_SUPER_MAGIC: FsType =
+ FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
+pub const HPFS_SUPER_MAGIC: FsType =
+ FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
+pub const ISOFS_SUPER_MAGIC: FsType =
+ FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
+pub const JFFS2_SUPER_MAGIC: FsType =
+ FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
+pub const MINIX2_SUPER_MAGIC2: FsType =
+ FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
+pub const MINIX2_SUPER_MAGIC: FsType =
+ FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MINIX3_SUPER_MAGIC: FsType = FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
+pub const MINIX3_SUPER_MAGIC: FsType =
+ FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
+pub const MINIX_SUPER_MAGIC2: FsType =
+ FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
+pub const MINIX_SUPER_MAGIC: FsType =
+ FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
+pub const MSDOS_SUPER_MAGIC: FsType =
+ FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
@@ -150,34 +220,44 @@ pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const NILFS_SUPER_MAGIC: FsType = FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
+pub const NILFS_SUPER_MAGIC: FsType =
+ FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const OCFS2_SUPER_MAGIC: FsType = FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
+pub const OCFS2_SUPER_MAGIC: FsType =
+ FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
+pub const OPENPROM_SUPER_MAGIC: FsType =
+ FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
+pub const OVERLAYFS_SUPER_MAGIC: FsType =
+ FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
+pub const PROC_SUPER_MAGIC: FsType =
+ FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
+pub const QNX4_SUPER_MAGIC: FsType =
+ FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const QNX6_SUPER_MAGIC: FsType = FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
+pub const QNX6_SUPER_MAGIC: FsType =
+ FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const RDTGROUP_SUPER_MAGIC: FsType = FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
+pub const RDTGROUP_SUPER_MAGIC: FsType =
+ FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
+pub const REISERFS_SUPER_MAGIC: FsType =
+ FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const SECURITYFS_MAGIC: FsType = FsType(libc::SECURITYFS_MAGIC as fs_type_t);
+pub const SECURITYFS_MAGIC: FsType =
+ FsType(libc::SECURITYFS_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t);
@@ -201,11 +281,21 @@ pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t);
pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
+pub const USBDEVICE_SUPER_MAGIC: FsType =
+ FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
#[cfg(any(target_os = "linux", target_os = "android"))]
#[allow(missing_docs)]
-pub const XENFS_SUPER_MAGIC: FsType = FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
-
+pub const XENFS_SUPER_MAGIC: FsType =
+ FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
+#[cfg(any(target_os = "linux", target_os = "android"))]
+#[allow(missing_docs)]
+pub const NSFS_MAGIC: FsType = FsType(libc::NSFS_MAGIC as fs_type_t);
+#[cfg(all(
+ any(target_os = "linux", target_os = "android"),
+ not(target_env = "musl")
+))]
+#[allow(missing_docs)]
+pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t);
impl Statfs {
/// Magic code defining system type
@@ -260,7 +350,14 @@ impl Statfs {
}
/// Optimal transfer block size
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
+ #[cfg(all(
+ target_os = "linux",
+ not(any(
+ target_arch = "s390x",
+ target_env = "musl",
+ target_env = "uclibc"
+ ))
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
self.0.f_bsize
@@ -320,7 +417,14 @@ 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", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
+ #[cfg(all(
+ target_os = "linux",
+ not(any(
+ target_arch = "s390x",
+ target_env = "musl",
+ target_env = "uclibc"
+ ))
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::__fsword_t {
self.0.f_bsize
@@ -347,6 +451,32 @@ impl Statfs {
self.0.f_bsize
}
+ /// Get the mount flags
+ #[cfg(all(
+ feature = "mount",
+ any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )
+ ))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ #[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches
+ pub fn flags(&self) -> MntFlags {
+ MntFlags::from_bits_truncate(self.0.f_flags as i32)
+ }
+
+ /// Get the mount flags
+ // The f_flags field exists on Android and Fuchsia too, but without man
+ // pages I can't tell if it can be cast to FsFlags.
+ #[cfg(target_os = "linux")]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
+ pub fn flags(&self) -> FsFlags {
+ FsFlags::from_bits_truncate(self.0.f_flags as libc::c_ulong)
+ }
+
/// Maximum length of filenames
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
@@ -376,7 +506,14 @@ impl Statfs {
}
/// Maximum length of filenames
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
+ #[cfg(all(
+ target_os = "linux",
+ not(any(
+ target_arch = "s390x",
+ target_env = "musl",
+ target_env = "uclibc"
+ ))
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::__fsword_t {
self.0.f_namelen
@@ -395,7 +532,9 @@ impl Statfs {
target_os = "macos",
target_os = "android",
target_os = "freebsd",
+ target_os = "fuchsia",
target_os = "openbsd",
+ target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks(&self) -> u64 {
@@ -410,24 +549,9 @@ impl Statfs {
}
/// Total data blocks in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+ #[cfg(target_os = "emscripten")]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks(&self) -> u64 {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks(&self) -> libc::c_ulong {
+ pub fn blocks(&self) -> u32 {
self.0.f_blocks
}
@@ -437,7 +561,9 @@ impl Statfs {
target_os = "macos",
target_os = "android",
target_os = "freebsd",
+ target_os = "fuchsia",
target_os = "openbsd",
+ target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_free(&self) -> u64 {
@@ -452,29 +578,20 @@ impl Statfs {
}
/// Free blocks in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+ #[cfg(target_os = "emscripten")]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_free(&self) -> u64 {
+ pub fn blocks_free(&self) -> u32 {
self.0.f_bfree
}
- /// Free blocks in filesystem
- #[cfg(not(any(
+ /// Free blocks available to unprivileged user
+ #[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_free(&self) -> libc::c_ulong {
- self.0.f_bfree
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
+ target_os = "fuchsia",
+ target_os = "linux",
+ ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn blocks_available(&self) -> u64 {
self.0.f_bavail
@@ -495,24 +612,9 @@ impl Statfs {
}
/// Free blocks available to unprivileged user
- #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+ #[cfg(target_os = "emscripten")]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> u64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> libc::c_ulong {
+ pub fn blocks_available(&self) -> u32 {
self.0.f_bavail
}
@@ -522,7 +624,9 @@ impl Statfs {
target_os = "macos",
target_os = "android",
target_os = "freebsd",
+ target_os = "fuchsia",
target_os = "openbsd",
+ target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files(&self) -> u64 {
@@ -537,33 +641,20 @@ impl Statfs {
}
/// Total file nodes in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+ #[cfg(target_os = "emscripten")]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files(&self) -> libc::fsfilcnt_t {
+ pub fn files(&self) -> u32 {
self.0.f_files
}
- /// Total file nodes in filesystem
- #[cfg(not(any(
+ /// Free file nodes in filesystem
+ #[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "android",
- target_os = "freebsd",
+ target_os = "fuchsia",
target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files(&self) -> libc::c_ulong {
- self.0.f_files
- }
-
- /// Free file nodes in filesystem
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
+ target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn files_free(&self) -> u64 {
@@ -585,24 +676,9 @@ impl Statfs {
}
/// Free file nodes in filesystem
- #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> libc::fsfilcnt_t {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
- )))]
+ #[cfg(target_os = "emscripten")]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> libc::c_ulong {
+ pub fn files_free(&self) -> u32 {
self.0.f_ffree
}
@@ -614,16 +690,27 @@ impl Statfs {
impl Debug for Statfs {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Statfs")
- .field("optimal_transfer_size", &self.optimal_transfer_size())
- .field("block_size", &self.block_size())
- .field("blocks", &self.blocks())
- .field("blocks_free", &self.blocks_free())
- .field("blocks_available", &self.blocks_available())
- .field("files", &self.files())
- .field("files_free", &self.files_free())
- .field("filesystem_id", &self.filesystem_id())
- .finish()
+ let mut ds = f.debug_struct("Statfs");
+ ds.field("optimal_transfer_size", &self.optimal_transfer_size());
+ ds.field("block_size", &self.block_size());
+ ds.field("blocks", &self.blocks());
+ ds.field("blocks_free", &self.blocks_free());
+ ds.field("blocks_available", &self.blocks_available());
+ ds.field("files", &self.files());
+ ds.field("files_free", &self.files_free());
+ ds.field("filesystem_id", &self.filesystem_id());
+ #[cfg(all(
+ feature = "mount",
+ any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )
+ ))]
+ ds.field("flags", &self.flags());
+ ds.finish()
}
}
@@ -637,8 +724,10 @@ impl Debug for Statfs {
/// `path` - Path to any file within the file system to describe
pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
unsafe {
- let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
- let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
+ let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
+ let res = path.with_nix_path(|path| {
+ LIBC_STATFS(path.as_ptr(), stat.as_mut_ptr())
+ })?;
Errno::result(res).map(|_| Statfs(stat.assume_init()))
}
}
@@ -653,8 +742,8 @@ pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
/// `fd` - File descriptor of any open file within the file system to describe
pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
unsafe {
- let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
- Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
+ let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
+ Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr()))
.map(|_| Statfs(stat.assume_init()))
}
}
@@ -702,6 +791,8 @@ mod test {
assert_fs_equals(fs, vfs);
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
assert_eq!(fs.files() as u64, vfs.files() as u64);
assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
@@ -749,6 +840,8 @@ mod test {
assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs
index 38b1fdc..8de369f 100644
--- a/src/sys/statvfs.rs
+++ b/src/sys/statvfs.rs
@@ -7,7 +7,7 @@ use std::os::unix::io::AsRawFd;
use libc::{self, c_ulong};
-use crate::{Result, NixPath, errno::Errno};
+use crate::{errno::Errno, NixPath, Result};
#[cfg(not(target_os = "redox"))]
libc_bitflags!(
@@ -130,7 +130,6 @@ impl Statvfs {
pub fn name_max(&self) -> c_ulong {
self.0.f_namemax
}
-
}
/// Return a `Statvfs` object with information about the `path`
@@ -138,9 +137,9 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
unsafe {
Errno::clear();
let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
- let res = path.with_nix_path(|path|
+ let res = path.with_nix_path(|path| {
libc::statvfs(path.as_ptr(), stat.as_mut_ptr())
- )?;
+ })?;
Errno::result(res).map(|_| Statvfs(stat.assume_init()))
}
@@ -158,8 +157,8 @@ pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
#[cfg(test)]
mod test {
- use std::fs::File;
use crate::sys::statvfs::*;
+ use std::fs::File;
#[test]
fn statvfs_call() {
diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs
index 96f0433..e8aa00b 100644
--- a/src/sys/sysinfo.rs
+++ b/src/sys/sysinfo.rs
@@ -30,6 +30,8 @@ impl SysInfo {
}
/// Returns the time since system boot.
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
pub fn uptime(&self) -> Duration {
// Truncate negative values to 0
Duration::from_secs(cmp::max(self.0.uptime, 0) as u64)
@@ -64,6 +66,8 @@ impl SysInfo {
self.scale_mem(self.0.freeram)
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn scale_mem(&self, units: mem_blocks_t) -> u64 {
units as u64 * self.0.mem_unit as u64
}
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index c5b27d2..fba2cd8 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -85,12 +85,28 @@
//!
//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust,ignore")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust")]
+#![cfg_attr(
+ any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ),
+ doc = " ```rust,ignore"
+)]
+#![cfg_attr(
+ not(any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )),
+ doc = " ```rust"
+)]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -102,12 +118,28 @@
//!
//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
+#![cfg_attr(
+ any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ),
+ doc = " ```rust"
+)]
+#![cfg_attr(
+ not(any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )),
+ doc = " ```rust,ignore"
+)]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -119,12 +151,28 @@
//!
//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
+#![cfg_attr(
+ any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ),
+ doc = " ```rust"
+)]
+#![cfg_attr(
+ not(any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )),
+ doc = " ```rust,ignore"
+)]
//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -137,12 +185,28 @@
//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
//! by specifying baud rates directly using `u32`s:
//!
-#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
- doc = " ```rust")]
-#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
- target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
- doc = " ```rust,ignore")]
+#![cfg_attr(
+ any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ),
+ doc = " ```rust"
+)]
+#![cfg_attr(
+ not(any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )),
+ doc = " ```rust,ignore"
+)]
//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
//! # fn main() {
//! # let mut t: Termios = unsafe { std::mem::zeroed() };
@@ -151,9 +215,9 @@
//! cfsetspeed(&mut t, 9600u32);
//! # }
//! ```
-use cfg_if::cfg_if;
-use crate::Result;
use crate::errno::Errno;
+use crate::Result;
+use cfg_if::cfg_if;
use libc::{self, c_int, tcflag_t};
use std::cell::{Ref, RefCell};
use std::convert::From;
@@ -181,6 +245,12 @@ pub struct Termios {
pub local_flags: LocalFlags,
/// Control characters (see `termios.c_cc` documentation)
pub control_chars: [libc::cc_t; NCCS],
+ /// Line discipline (see `termios.c_line` documentation)
+ #[cfg(any(target_os = "linux", target_os = "android",))]
+ pub line_discipline: libc::cc_t,
+ /// Line discipline (see `termios.c_line` documentation)
+ #[cfg(target_os = "haiku")]
+ pub line_discipline: libc::c_char,
}
impl Termios {
@@ -196,6 +266,14 @@ impl Termios {
termios.c_cflag = self.control_flags.bits();
termios.c_lflag = self.local_flags.bits();
termios.c_cc = self.control_chars;
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "haiku",
+ ))]
+ {
+ termios.c_line = self.line_discipline;
+ }
}
self.inner.borrow()
}
@@ -214,6 +292,14 @@ impl Termios {
termios.c_cflag = self.control_flags.bits();
termios.c_lflag = self.local_flags.bits();
termios.c_cc = self.control_chars;
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "haiku",
+ ))]
+ {
+ termios.c_line = self.line_discipline;
+ }
}
self.inner.as_ptr()
}
@@ -226,6 +312,14 @@ impl Termios {
self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
self.control_chars = termios.c_cc;
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "haiku",
+ ))]
+ {
+ self.line_discipline = termios.c_line;
+ }
}
}
@@ -238,6 +332,12 @@ impl From<libc::termios> for Termios {
control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
control_chars: termios.c_cc,
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "haiku",
+ ))]
+ line_discipline: termios.c_line,
}
}
}
@@ -248,7 +348,7 @@ impl From<Termios> for libc::termios {
}
}
-libc_enum!{
+libc_enum! {
/// Baud rates supported by the system.
///
/// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this
@@ -363,12 +463,14 @@ libc_enum!{
impl TryFrom<libc::speed_t>
}
-#[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
impl From<BaudRate> for u32 {
fn from(b: BaudRate) -> u32 {
b as u32
@@ -382,7 +484,6 @@ impl From<BaudRate> for u8 {
}
}
-
// TODO: Add TCSASOFT, which will require treating this as a bitfield.
libc_enum! {
/// Specify when a port configuration change should occur.
@@ -499,21 +600,26 @@ libc_enum! {
}
}
-#[cfg(any(all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos", target_os = "solaris"))]
+#[cfg(any(
+ all(target_os = "linux", target_arch = "sparc64"),
+ target_os = "illumos",
+ target_os = "solaris"
+))]
impl SpecialCharacterIndices {
pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
}
pub use libc::NCCS;
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(any(
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub use libc::_POSIX_VDISABLE;
@@ -883,7 +989,7 @@ libc_bitflags! {
}
}
-cfg_if!{
+cfg_if! {
if #[cfg(any(target_os = "freebsd",
target_os = "dragonfly",
target_os = "ios",
@@ -894,6 +1000,8 @@ cfg_if!{
/// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
///
/// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
pub fn cfgetispeed(termios: &Termios) -> u32 {
let inner_termios = termios.get_libc_termios();
unsafe { libc::cfgetispeed(&*inner_termios) as u32 }
@@ -903,6 +1011,8 @@ cfg_if!{
/// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
///
/// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
pub fn cfgetospeed(termios: &Termios) -> u32 {
let inner_termios = termios.get_libc_termios();
unsafe { libc::cfgetospeed(&*inner_termios) as u32 }
@@ -1051,7 +1161,10 @@ pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
/// *any* of the parameters were successfully set, not only if all were set successfully.
pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
let inner_termios = termios.get_libc_termios();
- Errno::result(unsafe { libc::tcsetattr(fd, actions as c_int, &*inner_termios) }).map(drop)
+ Errno::result(unsafe {
+ libc::tcsetattr(fd, actions as c_int, &*inner_termios)
+ })
+ .map(drop)
}
/// Block until all output data is written (see
diff --git a/src/sys/time.rs b/src/sys/time.rs
index 0cac7e8..0042c45 100644
--- a/src/sys/time.rs
+++ b/src/sys/time.rs
@@ -6,6 +6,13 @@ use std::convert::From;
use std::time::Duration;
use std::{cmp, fmt, ops};
+const fn zero_init_timespec() -> timespec {
+ // `std::mem::MaybeUninit::zeroed()` is not yet a const fn
+ // (https://github.com/rust-lang/rust/issues/91850) so we will instead initialize an array of
+ // the appropriate size to zero and then transmute it to a timespec value.
+ unsafe { std::mem::transmute([0u8; std::mem::size_of::<timespec>()]) }
+}
+
#[cfg(any(
all(feature = "time", any(target_os = "android", target_os = "linux")),
all(
@@ -20,7 +27,7 @@ use std::{cmp, fmt, ops};
)
))]
pub(crate) mod timer {
- use crate::sys::time::TimeSpec;
+ use crate::sys::time::{zero_init_timespec, TimeSpec};
use bitflags::bitflags;
#[derive(Debug, Clone, Copy)]
@@ -29,14 +36,8 @@ pub(crate) mod timer {
impl TimerSpec {
pub const fn none() -> Self {
Self(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
+ it_interval: zero_init_timespec(),
+ it_value: zero_init_timespec(),
})
}
}
@@ -57,10 +58,7 @@ pub(crate) mod timer {
fn from(expiration: Expiration) -> TimerSpec {
match expiration {
Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
+ it_interval: zero_init_timespec(),
it_value: *t.as_ref(),
}),
Expiration::IntervalDelayed(start, interval) => {
@@ -118,6 +116,7 @@ pub(crate) mod timer {
libc::timespec {
tv_sec: 0,
tv_nsec: 0,
+ ..
},
it_value: ts,
}) => Expiration::OneShot(ts.into()),
@@ -257,18 +256,17 @@ impl PartialOrd for TimeSpec {
impl TimeValLike for TimeSpec {
#[inline]
+ #[cfg_attr(target_env = "musl", allow(deprecated))]
+ // https://github.com/rust-lang/libc/issues/1848
fn seconds(seconds: i64) -> TimeSpec {
assert!(
(TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&seconds),
"TimeSpec out of bounds; seconds={}",
seconds
);
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {
- tv_sec: seconds as time_t,
- tv_nsec: 0,
- })
+ let mut ts = zero_init_timespec();
+ ts.tv_sec = seconds as time_t;
+ TimeSpec(ts)
}
#[inline]
@@ -292,20 +290,22 @@ impl TimeValLike for TimeSpec {
/// Makes a new `TimeSpec` with given number of nanoseconds.
#[inline]
+ #[cfg_attr(target_env = "musl", 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);
assert!(
(TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&secs),
"TimeSpec out of bounds"
);
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {
- tv_sec: secs as time_t,
- tv_nsec: nanos as timespec_tv_nsec_t,
- })
+ let mut ts = zero_init_timespec();
+ ts.tv_sec = secs as time_t;
+ ts.tv_nsec = nanos as timespec_tv_nsec_t;
+ TimeSpec(ts)
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn num_seconds(&self) -> i64 {
if self.tv_sec() < 0 && self.tv_nsec() > 0 {
(self.tv_sec() + 1) as i64
@@ -319,9 +319,11 @@ impl TimeValLike for TimeSpec {
}
fn num_microseconds(&self) -> i64 {
- self.num_nanoseconds() / 1_000_000_000
+ self.num_nanoseconds() / 1_000
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn num_nanoseconds(&self) -> i64 {
let secs = self.num_seconds() * 1_000_000_000;
let nsec = self.nanos_mod_sec();
@@ -333,10 +335,10 @@ impl TimeSpec {
/// Construct a new `TimeSpec` from its components
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self {
- Self(timespec {
- tv_sec: seconds,
- tv_nsec: nanoseconds,
- })
+ let mut ts = zero_init_timespec();
+ ts.tv_sec = seconds;
+ ts.tv_nsec = nanoseconds;
+ Self(ts)
}
fn nanos_mod_sec(&self) -> timespec_tv_nsec_t {
@@ -356,13 +358,13 @@ impl TimeSpec {
self.0.tv_nsec
}
+ #[cfg_attr(target_env = "musl", allow(deprecated))]
+ // https://github.com/rust-lang/libc/issues/1848
pub const fn from_duration(duration: Duration) -> Self {
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeSpec(timespec {
- tv_sec: duration.as_secs() as time_t,
- tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t,
- })
+ let mut ts = zero_init_timespec();
+ ts.tv_sec = duration.as_secs() as time_t;
+ ts.tv_nsec = duration.subsec_nanos() as timespec_tv_nsec_t;
+ TimeSpec(ts)
}
pub const fn from_timespec(timespec: timespec) -> Self {
@@ -549,6 +551,8 @@ impl TimeValLike for TimeVal {
})
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn num_seconds(&self) -> i64 {
if self.tv_sec() < 0 && self.tv_usec() > 0 {
(self.tv_sec() + 1) as i64
@@ -561,6 +565,8 @@ impl TimeValLike for TimeVal {
self.num_microseconds() / 1_000
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
fn num_microseconds(&self) -> i64 {
let secs = self.num_seconds() * 1_000_000;
let usec = self.micros_mod_sec();
diff --git a/src/sys/timer.rs b/src/sys/timer.rs
index 45ce0e5..e1a3405 100644
--- a/src/sys/timer.rs
+++ b/src/sys/timer.rs
@@ -70,9 +70,10 @@ pub struct Timer(libc::timer_t);
impl Timer {
/// Creates a new timer based on the clock defined by `clockid`. The details
/// of the signal and its handler are defined by the passed `sigevent`.
- #[cfg_attr(has_doc_alias, doc(alias("timer_create")))]
+ #[doc(alias("timer_create"))]
pub fn new(clockid: ClockId, mut sigevent: SigEvent) -> Result<Self> {
- let mut timer_id: mem::MaybeUninit<libc::timer_t> = mem::MaybeUninit::uninit();
+ let mut timer_id: mem::MaybeUninit<libc::timer_t> =
+ mem::MaybeUninit::uninit();
Errno::result(unsafe {
libc::timer_create(
clockid.as_raw(),
@@ -123,8 +124,12 @@ impl Timer {
///
/// Note: Setting a one shot alarm with a 0s TimeSpec disable the alarm
/// altogether.
- #[cfg_attr(has_doc_alias, doc(alias("timer_settime")))]
- pub fn set(&mut self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> {
+ #[doc(alias("timer_settime"))]
+ pub fn set(
+ &mut self,
+ expiration: Expiration,
+ flags: TimerSetTimeFlags,
+ ) -> Result<()> {
let timerspec: TimerSpec = expiration.into();
Errno::result(unsafe {
libc::timer_settime(
@@ -138,10 +143,13 @@ impl Timer {
}
/// Get the parameters for the alarm currently set, if any.
- #[cfg_attr(has_doc_alias, doc(alias("timer_gettime")))]
+ #[doc(alias("timer_gettime"))]
pub fn get(&self) -> Result<Option<Expiration>> {
let mut timerspec = TimerSpec::none();
- Errno::result(unsafe { libc::timer_gettime(self.0, timerspec.as_mut()) }).map(|_| {
+ Errno::result(unsafe {
+ libc::timer_gettime(self.0, timerspec.as_mut())
+ })
+ .map(|_| {
if timerspec.as_ref().it_interval.tv_sec == 0
&& timerspec.as_ref().it_interval.tv_nsec == 0
&& timerspec.as_ref().it_value.tv_sec == 0
@@ -161,7 +169,7 @@ impl Timer {
/// 'overrun'. This function returns how many times that has happened to
/// this timer, up to `libc::DELAYTIMER_MAX`. If more than the maximum
/// number of overruns have happened the return is capped to the maximum.
- #[cfg_attr(has_doc_alias, doc(alias("timer_getoverrun")))]
+ #[doc(alias("timer_getoverrun"))]
pub fn overruns(&self) -> i32 {
unsafe { libc::timer_getoverrun(self.0) }
}
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index 4286065..a35fc92 100644
--- a/src/sys/timerfd.rs
+++ b/src/sys/timerfd.rs
@@ -92,10 +92,12 @@ impl TimerFd {
/// Creates a new timer based on the clock defined by `clockid`. The
/// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
/// NONBLOCK). The underlying fd will be closed on drop.
- #[cfg_attr(has_doc_alias, doc(alias("timerfd_create")))]
+ #[doc(alias("timerfd_create"))]
pub fn new(clockid: ClockId, flags: TimerFlags) -> Result<Self> {
- Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) })
- .map(|fd| Self { fd })
+ Errno::result(unsafe {
+ libc::timerfd_create(clockid as i32, flags.bits())
+ })
+ .map(|fd| Self { fd })
}
/// Sets a new alarm on the timer.
@@ -134,8 +136,12 @@ impl TimerFd {
///
/// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm
/// altogether.
- #[cfg_attr(has_doc_alias, doc(alias("timerfd_settime")))]
- pub fn set(&self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> {
+ #[doc(alias("timerfd_settime"))]
+ pub fn set(
+ &self,
+ expiration: Expiration,
+ flags: TimerSetTimeFlags,
+ ) -> Result<()> {
let timerspec: TimerSpec = expiration.into();
Errno::result(unsafe {
libc::timerfd_settime(
@@ -149,10 +155,13 @@ impl TimerFd {
}
/// Get the parameters for the alarm currently set, if any.
- #[cfg_attr(has_doc_alias, doc(alias("timerfd_gettime")))]
+ #[doc(alias("timerfd_gettime"))]
pub fn get(&self) -> Result<Option<Expiration>> {
let mut timerspec = TimerSpec::none();
- Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec.as_mut()) }).map(|_| {
+ Errno::result(unsafe {
+ libc::timerfd_gettime(self.fd, timerspec.as_mut())
+ })
+ .map(|_| {
if timerspec.as_ref().it_interval.tv_sec == 0
&& timerspec.as_ref().it_interval.tv_nsec == 0
&& timerspec.as_ref().it_value.tv_sec == 0
@@ -166,7 +175,7 @@ impl TimerFd {
}
/// Remove the alarm if any is set.
- #[cfg_attr(has_doc_alias, doc(alias("timerfd_settime")))]
+ #[doc(alias("timerfd_settime"))]
pub fn unset(&self) -> Result<()> {
Errno::result(unsafe {
libc::timerfd_settime(
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 1908973..b31c306 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -1,8 +1,8 @@
//! Vectored I/O
-use crate::Result;
use crate::errno::Errno;
-use libc::{self, c_int, c_void, size_t, off_t};
+use crate::Result;
+use libc::{self, c_int, c_void, off_t, size_t};
use std::io::{IoSlice, IoSliceMut};
use std::marker::PhantomData;
use std::os::unix::io::RawFd;
@@ -12,13 +12,15 @@ use std::os::unix::io::RawFd;
/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html)
pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
// SAFETY: to quote the documentation for `IoSlice`:
- //
- // [IoSlice] is semantically a wrapper around a &[u8], but is
+ //
+ // [IoSlice] is semantically a wrapper around a &[u8], but is
// guaranteed to be ABI compatible with the iovec type on Unix
// platforms.
//
// Because it is ABI compatible, a pointer cast here is valid
- let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
+ let res = unsafe {
+ libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
+ };
Errno::result(res).map(|r| r as usize)
}
@@ -28,7 +30,9 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html)
pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
// SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec
- let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
+ let res = unsafe {
+ libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
+ };
Errno::result(res).map(|r| r as usize)
}
@@ -41,15 +45,18 @@ pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>],
- offset: off_t) -> Result<usize> {
-
+pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
// SAFETY: same as in writev()
let res = unsafe {
- libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
+ libc::pwritev(
+ fd,
+ iov.as_ptr() as *const libc::iovec,
+ iov.len() as c_int,
+ offset,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -64,14 +71,22 @@ pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>],
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn preadv(fd: RawFd, iov: &mut [IoSliceMut<'_>],
- offset: off_t) -> Result<usize> {
+pub fn preadv(
+ fd: RawFd,
+ iov: &mut [IoSliceMut<'_>],
+ offset: off_t,
+) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
// SAFETY: same as in readv()
let res = unsafe {
- libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
+ libc::preadv(
+ fd,
+ iov.as_ptr() as *const libc::iovec,
+ iov.len() as c_int,
+ offset,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -83,8 +98,12 @@ pub fn preadv(fd: RawFd, iov: &mut [IoSliceMut<'_>],
// TODO: move to unistd
pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
let res = unsafe {
- libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
- offset)
+ libc::pwrite(
+ fd,
+ buf.as_ptr() as *const c_void,
+ buf.len() as size_t,
+ offset,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -94,10 +113,14 @@ pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
///
/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
// TODO: move to unistd
-pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
+pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize> {
let res = unsafe {
- libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
- offset)
+ libc::pread(
+ fd,
+ buf.as_mut_ptr() as *mut c_void,
+ buf.len() as size_t,
+ offset,
+ )
};
Errno::result(res).map(|r| r as usize)
@@ -151,9 +174,7 @@ impl<T> IoVec<T> {
use std::slice;
unsafe {
- slice::from_raw_parts(
- self.0.iov_base as *const u8,
- self.0.iov_len as usize)
+ slice::from_raw_parts(self.0.iov_base as *const u8, self.0.iov_len)
}
}
}
@@ -161,30 +182,30 @@ impl<T> IoVec<T> {
#[allow(deprecated)]
impl<'a> IoVec<&'a [u8]> {
/// Create an `IoVec` from a Rust slice.
- #[deprecated(
- since = "0.24.0",
- note = "Use `IoSlice::new` instead"
- )]
+ #[deprecated(since = "0.24.0", note = "Use `IoSlice::new` instead")]
pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
- IoVec(libc::iovec {
- iov_base: buf.as_ptr() as *mut c_void,
- iov_len: buf.len() as size_t,
- }, PhantomData)
+ IoVec(
+ libc::iovec {
+ iov_base: buf.as_ptr() as *mut c_void,
+ iov_len: buf.len() as size_t,
+ },
+ PhantomData,
+ )
}
}
#[allow(deprecated)]
impl<'a> IoVec<&'a mut [u8]> {
/// Create an `IoVec` from a mutable Rust slice.
- #[deprecated(
- since = "0.24.0",
- note = "Use `IoSliceMut::new` instead"
- )]
+ #[deprecated(since = "0.24.0", note = "Use `IoSliceMut::new` instead")]
pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
- IoVec(libc::iovec {
- iov_base: buf.as_ptr() as *mut c_void,
- iov_len: buf.len() as size_t,
- }, PhantomData)
+ IoVec(
+ libc::iovec {
+ iov_base: buf.as_ptr() as *mut c_void,
+ iov_len: buf.len() as size_t,
+ },
+ PhantomData,
+ )
}
}
diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs
index 5bd3a53..b48ed9f 100644
--- a/src/sys/utsname.rs
+++ b/src/sys/utsname.rs
@@ -1,9 +1,9 @@
//! Get system identification
+use crate::{Errno, Result};
+use libc::c_char;
+use std::ffi::OsStr;
use std::mem;
use std::os::unix::ffi::OsStrExt;
-use std::ffi::OsStr;
-use libc::c_char;
-use crate::{Errno, Result};
/// Describes the running system. Return type of [`uname`].
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -35,6 +35,12 @@ impl UtsName {
pub fn machine(&self) -> &OsStr {
cast_and_trim(&self.0.machine)
}
+
+ /// NIS or YP domain name of this machine.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub fn domainname(&self) -> &OsStr {
+ cast_and_trim(&self.0.domainname)
+ }
}
/// Get system identification
@@ -47,10 +53,12 @@ pub fn uname() -> Result<UtsName> {
}
fn cast_and_trim(slice: &[c_char]) -> &OsStr {
- let length = slice.iter().position(|&byte| byte == 0).unwrap_or(slice.len());
- let bytes = unsafe {
- std::slice::from_raw_parts(slice.as_ptr().cast(), length)
- };
+ let length = slice
+ .iter()
+ .position(|&byte| byte == 0)
+ .unwrap_or(slice.len());
+ let bytes =
+ unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), length) };
OsStr::from_bytes(bytes)
}
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index 5fb2075..b6524e8 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -135,7 +135,9 @@ impl WaitStatus {
pub fn pid(&self) -> Option<Pid> {
use self::WaitStatus::*;
match *self {
- Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p),
+ Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => {
+ Some(p)
+ }
StillAlive => None,
#[cfg(any(target_os = "android", target_os = "linux"))]
PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
@@ -274,7 +276,9 @@ impl WaitStatus {
Signal::try_from(si_status)?,
siginfo.si_code == libc::CLD_DUMPED,
),
- libc::CLD_STOPPED => WaitStatus::Stopped(pid, Signal::try_from(si_status)?),
+ libc::CLD_STOPPED => {
+ WaitStatus::Stopped(pid, Signal::try_from(si_status)?)
+ }
libc::CLD_CONTINUED => WaitStatus::Continued(pid),
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::CLD_TRAPPED => {
@@ -298,7 +302,10 @@ impl WaitStatus {
/// Wait for a process to change status
///
/// See also [waitpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html)
-pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
+pub fn waitpid<P: Into<Option<Pid>>>(
+ pid: P,
+ options: Option<WaitPidFlag>,
+) -> Result<WaitStatus> {
use self::WaitStatus::*;
let mut status: i32 = 0;
diff --git a/src/time.rs b/src/time.rs
index 6a385b9..2e03c46 100644
--- a/src/time.rs
+++ b/src/time.rs
@@ -85,7 +85,8 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_BOOTTIME_ALARM: ClockId = ClockId(libc::CLOCK_BOOTTIME_ALARM);
+ pub const CLOCK_BOOTTIME_ALARM: ClockId =
+ ClockId(libc::CLOCK_BOOTTIME_ALARM);
pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
#[cfg(any(
target_os = "android",
@@ -94,13 +95,16 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE);
+ pub const CLOCK_MONOTONIC_COARSE: ClockId =
+ ClockId(libc::CLOCK_MONOTONIC_COARSE);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST);
+ pub const CLOCK_MONOTONIC_FAST: ClockId =
+ ClockId(libc::CLOCK_MONOTONIC_FAST);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE);
+ pub const CLOCK_MONOTONIC_PRECISE: ClockId =
+ ClockId(libc::CLOCK_MONOTONIC_PRECISE);
#[cfg(any(
target_os = "android",
target_os = "emscripten",
@@ -121,7 +125,8 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
+ pub const CLOCK_PROCESS_CPUTIME_ID: ClockId =
+ ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
@@ -133,7 +138,8 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM);
+ pub const CLOCK_REALTIME_ALARM: ClockId =
+ ClockId(libc::CLOCK_REALTIME_ALARM);
#[cfg(any(
target_os = "android",
target_os = "emscripten",
@@ -141,13 +147,15 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE);
+ pub const CLOCK_REALTIME_COARSE: ClockId =
+ ClockId(libc::CLOCK_REALTIME_COARSE);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE);
+ pub const CLOCK_REALTIME_PRECISE: ClockId =
+ ClockId(libc::CLOCK_REALTIME_PRECISE);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
@@ -177,7 +185,8 @@ impl ClockId {
target_os = "linux"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
+ pub const CLOCK_THREAD_CPUTIME_ID: ClockId =
+ ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
@@ -186,7 +195,8 @@ impl ClockId {
pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
- pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE);
+ pub const CLOCK_UPTIME_PRECISE: ClockId =
+ ClockId(libc::CLOCK_UPTIME_PRECISE);
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
@@ -216,7 +226,8 @@ impl std::fmt::Display for ClockId {
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
+ let ret =
+ unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
Errno::result(ret)?;
let res = unsafe { c_time.assume_init() };
Ok(TimeSpec::from(res))
@@ -226,7 +237,8 @@ pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
/// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)).
pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
+ let ret =
+ unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
Errno::result(ret)?;
let res = unsafe { c_time.assume_init() };
Ok(TimeSpec::from(res))
@@ -242,7 +254,8 @@ pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
)))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
- let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
+ let ret =
+ unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
Errno::result(ret).map(drop)
}
@@ -259,7 +272,8 @@ pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
- let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
+ let ret =
+ unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
if ret == 0 {
let res = unsafe { clk_id.assume_init() };
Ok(ClockId::from(res))
diff --git a/src/ucontext.rs b/src/ucontext.rs
index f2338bd..b2a39f7 100644
--- a/src/ucontext.rs
+++ b/src/ucontext.rs
@@ -1,10 +1,10 @@
#[cfg(not(target_env = "musl"))]
-use crate::Result;
-#[cfg(not(target_env = "musl"))]
use crate::errno::Errno;
+use crate::sys::signal::SigSet;
+#[cfg(not(target_env = "musl"))]
+use crate::Result;
#[cfg(not(target_env = "musl"))]
use std::mem;
-use crate::sys::signal::SigSet;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct UContext {
@@ -17,7 +17,9 @@ impl UContext {
let mut context = mem::MaybeUninit::<libc::ucontext_t>::uninit();
let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
Errno::result(res).map(|_| unsafe {
- UContext { context: context.assume_init()}
+ UContext {
+ context: context.assume_init(),
+ }
})
}
@@ -31,13 +33,15 @@ impl UContext {
pub fn sigmask_mut(&mut self) -> &mut SigSet {
unsafe {
- &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t as *mut SigSet)
+ &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t
+ as *mut SigSet)
}
}
pub fn sigmask(&self) -> &SigSet {
unsafe {
- &*(&self.context.uc_sigmask as *const libc::sigset_t as *const SigSet)
+ &*(&self.context.uc_sigmask as *const libc::sigset_t
+ as *const SigSet)
}
}
}
diff --git a/src/unistd.rs b/src/unistd.rs
index 8cdb54b..ca07b34 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -79,13 +79,13 @@ impl Uid {
}
/// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
- #[cfg_attr(has_doc_alias, doc(alias("getuid")))]
+ #[doc(alias("getuid"))]
pub fn current() -> Self {
getuid()
}
/// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
- #[cfg_attr(has_doc_alias, doc(alias("geteuid")))]
+ #[doc(alias("geteuid"))]
pub fn effective() -> Self {
geteuid()
}
@@ -136,13 +136,13 @@ impl Gid {
}
/// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
- #[cfg_attr(has_doc_alias, doc(alias("getgid")))]
+ #[doc(alias("getgid"))]
pub fn current() -> Self {
getgid()
}
/// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
- #[cfg_attr(has_doc_alias, doc(alias("getegid")))]
+ #[doc(alias("getegid"))]
pub fn effective() -> Self {
getegid()
}
@@ -188,13 +188,13 @@ impl Pid {
}
/// Returns PID of calling process
- #[cfg_attr(has_doc_alias, doc(alias("getpid")))]
+ #[doc(alias("getpid"))]
pub fn this() -> Self {
getpid()
}
/// Returns PID of parent of calling process
- #[cfg_attr(has_doc_alias, doc(alias("getppid")))]
+ #[doc(alias("getppid"))]
pub fn parent() -> Self {
getppid()
}
@@ -417,7 +417,7 @@ feature! {
/// Create a copy of the specified file descriptor (see
/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
///
-/// The new file descriptor will be have a new index but refer to the same
+/// The new file descriptor will have a new index but refer to the same
/// resource as the old file descriptor and the old and new file descriptors may
/// be used interchangeably. The new and old file descriptor share the same
/// underlying resource, offset, and file status flags. The actual index used
@@ -1354,6 +1354,17 @@ pub fn sync() {
unsafe { libc::sync() };
}
+/// Commit filesystem caches containing file referred to by the open file
+/// descriptor `fd` to disk
+///
+/// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html)
+#[cfg(target_os = "linux")]
+pub fn syncfs(fd: RawFd) -> Result<()> {
+ let res = unsafe { libc::syncfs(fd) };
+
+ Errno::result(res).map(drop)
+}
+
/// Synchronize changes to a file
///
/// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
@@ -2196,7 +2207,7 @@ pub enum SysconfVar {
/// Unless otherwise noted, the maximum length, in bytes, of a utility's
/// input line (either standard input or another file), when the utility is
/// described as processing text files. The length includes room for the
- /// trailing <newline>.
+ /// trailing newline.
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
LINE_MAX = libc::_SC_LINE_MAX,
@@ -2910,9 +2921,8 @@ pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
/// # References
///
/// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html)
-// illumos: faccessat(2) appears to be supported, but the libc crate does not provide a binding.
// redox: does not appear to support the *at family of syscalls.
-#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
pub fn faccessat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: AccessFlags, flags: AtFlags) -> Result<()> {
let res = path.with_nix_path(|cstr| {
unsafe {
@@ -2921,6 +2931,27 @@ pub fn faccessat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Acce
})?;
Errno::result(res).map(drop)
}
+
+/// Checks the file named by `path` for accessibility according to the flags given
+/// by `mode` using effective UID, effective GID and supplementary group lists.
+///
+/// # References
+///
+/// * [FreeBSD man page](https://www.freebsd.org/cgi/man.cgi?query=eaccess&sektion=2&n=1)
+/// * [Linux man page](https://man7.org/linux/man-pages/man3/euidaccess.3.html)
+#[cfg(any(
+ all(target_os = "linux", not(target_env = "uclibc")),
+ target_os = "freebsd",
+ target_os = "dragonfly"
+))]
+pub fn eaccess<P: ?Sized + NixPath>(path: &P, mode: AccessFlags) -> Result<()> {
+ let res = path.with_nix_path(|cstr| {
+ unsafe {
+ libc::eaccess(cstr.as_ptr(), mode.bits)
+ }
+ })?;
+ Errno::result(res).map(drop)
+}
}
feature! {
@@ -3143,7 +3174,10 @@ impl User {
/// assert_eq!(res.name, "root");
/// ```
pub fn from_name(name: &str) -> Result<Option<Self>> {
- let name = CString::new(name).unwrap();
+ let name = match CString::new(name) {
+ Ok(c_str) => c_str,
+ Err(_nul_error) => return Ok(None),
+ };
User::from_anything(|pwd, cbuf, cap, res| {
unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
})
@@ -3268,7 +3302,10 @@ impl Group {
/// assert!(res.name == "root");
/// ```
pub fn from_name(name: &str) -> Result<Option<Self>> {
- let name = CString::new(name).unwrap();
+ let name = match CString::new(name) {
+ Ok(c_str) => c_str,
+ Err(_nul_error) => return Ok(None),
+ };
Group::from_anything(|grp, cbuf, cap, res| {
unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
})
diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs
index 6a36f3e..84086f8 100644
--- a/test/sys/test_aio.rs
+++ b/test/sys/test_aio.rs
@@ -1,5 +1,5 @@
use std::{
- io::{Read, Seek, SeekFrom, Write},
+ io::{Read, Seek, Write},
ops::Deref,
os::unix::io::AsRawFd,
pin::Pin,
@@ -371,7 +371,7 @@ mod aio_write {
assert_eq!(err, Ok(()));
assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
- f.seek(SeekFrom::Start(0)).unwrap();
+ f.rewind().unwrap();
let len = f.read_to_end(&mut rbuf).unwrap();
assert_eq!(len, EXPECT.len());
assert_eq!(rbuf, EXPECT);
@@ -402,7 +402,7 @@ mod aio_write {
assert_eq!(err, Ok(()));
assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
- f.seek(SeekFrom::Start(0)).unwrap();
+ f.rewind().unwrap();
let len = f.read_to_end(&mut rbuf).unwrap();
assert_eq!(len, EXPECT.len());
assert_eq!(rbuf, EXPECT);
@@ -487,7 +487,7 @@ mod aio_writev {
assert_eq!(err, Ok(()));
assert_eq!(aiow.as_mut().aio_return().unwrap(), wlen);
- f.seek(SeekFrom::Start(0)).unwrap();
+ f.rewind().unwrap();
let len = f.read_to_end(&mut rbuf).unwrap();
assert_eq!(len, EXPECT.len());
assert_eq!(rbuf, EXPECT);
@@ -537,7 +537,7 @@ fn sigev_signal() {
}
assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
- f.seek(SeekFrom::Start(0)).unwrap();
+ f.rewind().unwrap();
let len = f.read_to_end(&mut rbuf).unwrap();
assert_eq!(len, EXPECT.len());
assert_eq!(rbuf, EXPECT);
diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs
index 7a603c5..40f60cf 100644
--- a/test/sys/test_ioctl.rs
+++ b/test/sys/test_ioctl.rs
@@ -30,6 +30,8 @@ ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
#[test]
fn test_op_none() {
if cfg!(any(
@@ -46,6 +48,8 @@ mod linux {
}
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
#[test]
fn test_op_write() {
if cfg!(any(
@@ -78,6 +82,8 @@ mod linux {
}
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
#[test]
fn test_op_read() {
if cfg!(any(
@@ -110,6 +116,8 @@ mod linux {
}
}
+ // The cast is not unnecessary on all platforms.
+ #[allow(clippy::unnecessary_cast)]
#[test]
fn test_op_read_write() {
assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
diff --git a/test/sys/test_mman.rs b/test/sys/test_mman.rs
index 75cbf6c..e748427 100644
--- a/test/sys/test_mman.rs
+++ b/test/sys/test_mman.rs
@@ -1,11 +1,12 @@
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
+use std::num::NonZeroUsize;
#[test]
fn test_mmap_anonymous() {
unsafe {
let ptr = mmap(
- std::ptr::null_mut(),
- 1,
+ None,
+ NonZeroUsize::new(1).unwrap(),
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
-1,
@@ -25,10 +26,12 @@ fn test_mremap_grow() {
use nix::sys::mman::{mremap, MRemapFlags};
const ONE_K: size_t = 1024;
+ let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
+
let slice: &mut [u8] = unsafe {
let mem = mmap(
- std::ptr::null_mut(),
- ONE_K,
+ None,
+ one_k_non_zero,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
@@ -79,12 +82,14 @@ fn test_mremap_grow() {
fn test_mremap_shrink() {
use nix::libc::{c_void, size_t};
use nix::sys::mman::{mremap, MRemapFlags};
+ 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(
- std::ptr::null_mut(),
- 10 * ONE_K,
+ None,
+ ten_one_k,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
@@ -100,7 +105,7 @@ fn test_mremap_shrink() {
let slice: &mut [u8] = unsafe {
let mem = mremap(
slice.as_mut_ptr() as *mut c_void,
- 10 * ONE_K,
+ ten_one_k.into(),
ONE_K,
MRemapFlags::empty(),
None,
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index b4ca279..5adc77e 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -223,7 +223,7 @@ pub fn test_addr_equality_abstract() {
}
// Test getting/setting abstract addresses (without unix socket creation)
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "android", target_os = "linux"))]
#[test]
pub fn test_abstract_uds_addr() {
let empty = String::new();
@@ -244,6 +244,22 @@ pub fn test_abstract_uds_addr() {
assert_eq!(unsafe { (*addr.as_ptr()).sun_path[0] }, 0);
}
+// Test getting an unnamed address (without unix socket creation)
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+pub fn test_unnamed_uds_addr() {
+ use crate::nix::sys::socket::SockaddrLike;
+
+ let addr = UnixAddr::new_unnamed();
+
+ assert!(addr.is_unnamed());
+ assert_eq!(addr.len(), 2);
+ assert!(addr.path().is_none());
+ assert_eq!(addr.path_len(), 0);
+
+ assert!(addr.as_abstract().is_none());
+}
+
#[test]
pub fn test_getsockname() {
use nix::sys::socket::bind;
@@ -501,31 +517,31 @@ mod recvfrom {
rsock,
ssock,
move |s, m, flags| {
- let iov = [IoSlice::new(m)];
- let mut msgs = vec![SendMmsgData {
- iov: &iov,
- cmsgs: &[],
- addr: Some(sock_addr),
- _lt: Default::default(),
- }];
-
let batch_size = 15;
+ let mut iovs = Vec::with_capacity(1 + batch_size);
+ let mut addrs = Vec::with_capacity(1 + batch_size);
+ let mut data = MultiHeaders::preallocate(1 + batch_size, None);
+ let iov = IoSlice::new(m);
+ // first chunk:
+ iovs.push([iov]);
+ addrs.push(Some(sock_addr));
for _ in 0..batch_size {
- msgs.push(SendMmsgData {
- iov: &iov,
- cmsgs: &[],
- addr: Some(sock_addr2),
- _lt: Default::default(),
- });
+ iovs.push([iov]);
+ addrs.push(Some(sock_addr2));
}
- sendmmsg(s, msgs.iter(), flags).map(move |sent_bytes| {
- assert!(!sent_bytes.is_empty());
- for sent in &sent_bytes {
- assert_eq!(*sent, m.len());
- }
- sent_bytes.len()
- })
+
+ let res = sendmmsg(s, &mut data, &iovs, addrs, [], flags)?;
+ let mut sent_messages = 0;
+ let mut sent_bytes = 0;
+ for item in res {
+ sent_messages += 1;
+ sent_bytes += item.bytes;
+ }
+ //
+ assert_eq!(sent_messages, iovs.len());
+ assert_eq!(sent_bytes, sent_messages * m.len());
+ Ok(sent_messages)
},
|_, _| {},
);
@@ -577,21 +593,19 @@ mod recvfrom {
// Buffers to receive exactly `NUM_MESSAGES_SENT` messages
let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT];
- let iovs: Vec<_> = receive_buffers
- .iter_mut()
- .map(|buf| [IoSliceMut::new(&mut buf[..])])
- .collect();
+ msgs.extend(
+ receive_buffers
+ .iter_mut()
+ .map(|buf| [IoSliceMut::new(&mut buf[..])]),
+ );
- for iov in &iovs {
- msgs.push_back(RecvMmsgData {
- iov,
- cmsg_buffer: None,
- })
- }
+ let mut data =
+ MultiHeaders::<SockaddrIn>::preallocate(msgs.len(), None);
let res: Vec<RecvMsg<SockaddrIn>> =
- recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None)
- .expect("recvmmsg");
+ recvmmsg(rsock, &mut data, msgs.iter(), MsgFlags::empty(), None)
+ .expect("recvmmsg")
+ .collect();
assert_eq!(res.len(), DATA.len());
for RecvMsg { address, bytes, .. } in res.into_iter() {
@@ -655,21 +669,26 @@ mod recvfrom {
// will return when there are fewer than requested messages in the
// kernel buffers when using `MSG_DONTWAIT`.
let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
- let iovs: Vec<_> = receive_buffers
- .iter_mut()
- .map(|buf| [IoSliceMut::new(&mut buf[..])])
- .collect();
+ msgs.extend(
+ receive_buffers
+ .iter_mut()
+ .map(|buf| [IoSliceMut::new(&mut buf[..])]),
+ );
- for iov in &iovs {
- msgs.push_back(RecvMmsgData {
- iov,
- cmsg_buffer: None,
- })
- }
+ let mut data = MultiHeaders::<SockaddrIn>::preallocate(
+ NUM_MESSAGES_SENT + 2,
+ None,
+ );
- let res: Vec<RecvMsg<SockaddrIn>> =
- recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None)
- .expect("recvmmsg");
+ let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
+ rsock,
+ &mut data,
+ msgs.iter(),
+ MsgFlags::MSG_DONTWAIT,
+ None,
+ )
+ .expect("recvmmsg")
+ .collect();
assert_eq!(res.len(), NUM_MESSAGES_SENT);
for RecvMsg { address, bytes, .. } in res.into_iter() {
@@ -1481,7 +1500,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
// Test creating and using named unix domain sockets
#[test]
-pub fn test_unixdomain() {
+pub fn test_named_unixdomain() {
use nix::sys::socket::{accept, bind, connect, listen, socket, UnixAddr};
use nix::sys::socket::{SockFlag, SockType};
use nix::unistd::{close, read, write};
@@ -1524,6 +1543,59 @@ pub fn test_unixdomain() {
assert_eq!(&buf[..], b"hello");
}
+// Test using unnamed unix domain addresses
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+pub fn test_unnamed_unixdomain() {
+ use nix::sys::socket::{getsockname, socketpair};
+ use nix::sys::socket::{SockFlag, SockType};
+ use nix::unistd::close;
+
+ let (fd_1, fd_2) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .expect("socketpair failed");
+
+ let addr_1: UnixAddr = getsockname(fd_1).expect("getsockname failed");
+ assert!(addr_1.is_unnamed());
+
+ close(fd_1).unwrap();
+ close(fd_2).unwrap();
+}
+
+// Test creating and using unnamed unix domain addresses for autobinding sockets
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+pub fn test_unnamed_unixdomain_autobind() {
+ use nix::sys::socket::{bind, getsockname, socket};
+ use nix::sys::socket::{SockFlag, SockType};
+ use nix::unistd::close;
+
+ let fd = socket(
+ AddressFamily::Unix,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .expect("socket failed");
+
+ // unix(7): "If a bind(2) call specifies addrlen as `sizeof(sa_family_t)`, or [...], then the
+ // socket is autobound to an abstract address"
+ bind(fd, &UnixAddr::new_unnamed()).expect("bind failed");
+
+ let addr: UnixAddr = getsockname(fd).expect("getsockname failed");
+ let addr = addr.as_abstract().unwrap();
+
+ // changed from 8 to 5 bytes in Linux 2.3.15, and rust's minimum supported Linux version is 3.2
+ // (as of 2022-11)
+ assert_eq!(addr.len(), 5);
+
+ close(fd).unwrap();
+}
+
// Test creating and using named system control sockets
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[test]
@@ -2205,14 +2277,13 @@ fn test_recvmmsg_timestampns() {
assert_eq!(message.len(), l);
// Receive the message
let mut buffer = vec![0u8; message.len()];
- let mut cmsgspace = nix::cmsg_space!(TimeSpec);
- let iov = [IoSliceMut::new(&mut buffer)];
- let mut data = vec![RecvMmsgData {
- iov,
- cmsg_buffer: Some(&mut cmsgspace),
- }];
+ let cmsgspace = nix::cmsg_space!(TimeSpec);
+ let iov = vec![[IoSliceMut::new(&mut buffer)]];
+ let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
let r: Vec<RecvMsg<()>> =
- recvmmsg(in_socket, &mut data, flags, None).unwrap();
+ recvmmsg(in_socket, &mut data, iov.iter(), flags, None)
+ .unwrap()
+ .collect();
let rtime = match r[0].cmsgs().next() {
Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
Some(_) => panic!("Unexpected control message"),
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 2ddbf77..34bef94 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -151,6 +151,33 @@ fn test_so_tcp_maxseg() {
close(ssock).unwrap();
}
+#[test]
+fn test_so_type() {
+ let sockfd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ assert_eq!(Ok(SockType::Stream), getsockopt(sockfd, sockopt::SockType));
+}
+
+/// getsockopt(_, sockopt::SockType) should gracefully handle unknown socket
+/// types. Regression test for https://github.com/nix-rust/nix/issues/1819
+#[cfg(any(target_os = "android", target_os = "linux",))]
+#[test]
+fn test_so_type_unknown() {
+ use nix::errno::Errno;
+
+ require_capability!("test_so_type", CAP_NET_RAW);
+ let sockfd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
+ assert!(sockfd >= 0, "Error opening socket: {}", nix::Error::last());
+
+ assert_eq!(Err(Errno::EINVAL), getsockopt(sockfd, sockopt::SockType));
+}
+
// 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.
@@ -237,6 +264,33 @@ fn test_so_tcp_keepalive() {
}
#[test]
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg_attr(qemu, ignore)]
+fn test_get_mtu() {
+ use nix::sys::socket::{bind, connect, SockaddrIn};
+ use std::net::SocketAddrV4;
+ use std::str::FromStr;
+
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap();
+ let std_sb = SocketAddrV4::from_str("127.0.0.1:4002").unwrap();
+
+ let usock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ SockProtocol::Udp,
+ )
+ .unwrap();
+
+ // Bind and initiate connection
+ bind(usock, &SockaddrIn::from(std_sa)).unwrap();
+ connect(usock, &SockaddrIn::from(std_sb)).unwrap();
+
+ // Loopback connections have 2^16 - the maximum - MTU
+ assert_eq!(getsockopt(usock, sockopt::IpMtu), Ok(u16::MAX as i32))
+}
+
+#[test]
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
fn test_ttl_opts() {
let fd4 = socket(
@@ -327,3 +381,51 @@ fn test_v6dontfrag_opts() {
"unsetting IPV6_DONTFRAG on an inet6 datagram socket should succeed",
);
}
+
+#[test]
+#[cfg(target_os = "linux")]
+fn test_so_priority() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ let priority = 3;
+ setsockopt(fd, sockopt::Priority, &priority).unwrap();
+ assert_eq!(getsockopt(fd, sockopt::Priority).unwrap(), priority);
+}
+
+#[test]
+#[cfg(target_os = "linux")]
+fn test_ip_tos() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ let tos = 0x80; // CS4
+ setsockopt(fd, sockopt::IpTos, &tos).unwrap();
+ assert_eq!(getsockopt(fd, sockopt::IpTos).unwrap(), tos);
+}
+
+#[test]
+#[cfg(target_os = "linux")]
+// Disable the test under emulation because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
+fn test_ipv6_tclass() {
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ let class = 0x80; // CS4
+ setsockopt(fd, sockopt::Ipv6TClass, &class).unwrap();
+ assert_eq!(getsockopt(fd, sockopt::Ipv6TClass).unwrap(), class);
+}
diff --git a/test/sys/test_stat.rs b/test/sys/test_stat.rs
index 2f26e78..426b4b6 100644
--- a/test/sys/test_stat.rs
+++ b/test/sys/test_stat.rs
@@ -1,3 +1,5 @@
+// The conversion is not useless on all platforms.
+#[allow(clippy::useless_conversion)]
#[cfg(target_os = "freebsd")]
#[test]
fn test_chflags() {
diff --git a/test/sys/test_timerfd.rs b/test/sys/test_timerfd.rs
index 927cc70..08e2921 100644
--- a/test/sys/test_timerfd.rs
+++ b/test/sys/test_timerfd.rs
@@ -65,5 +65,5 @@ pub fn test_timerfd_unset() {
timer.unset().unwrap();
- assert!(timer.get().unwrap() == None);
+ assert!(timer.get().unwrap().is_none());
}
diff --git a/test/test.rs b/test/test.rs
index f725ef9..6b42aad 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -36,6 +36,7 @@ mod test_resource;
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
+ all(target_os = "freebsd", fbsd14),
target_os = "linux"
))]
mod test_sched;
diff --git a/test/test_dir.rs b/test/test_dir.rs
index f662992..2af4aa5 100644
--- a/test/test_dir.rs
+++ b/test/test_dir.rs
@@ -19,7 +19,7 @@ fn flags() -> OFlag {
#[allow(clippy::unnecessary_sort_by)] // False positive
fn read() {
let tmp = tempdir().unwrap();
- File::create(&tmp.path().join("foo")).unwrap();
+ File::create(tmp.path().join("foo")).unwrap();
std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap();
let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap();
let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect();
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index f4adee2..e51044a 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -64,7 +64,7 @@ fn test_renameat() {
let old_dirfd =
open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
let old_path = old_dir.path().join("old");
- File::create(&old_path).unwrap();
+ File::create(old_path).unwrap();
let new_dir = tempfile::tempdir().unwrap();
let new_dirfd =
open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
@@ -94,7 +94,7 @@ fn test_renameat2_behaves_like_renameat_with_no_flags() {
let old_dirfd =
open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
let old_path = old_dir.path().join("old");
- File::create(&old_path).unwrap();
+ File::create(old_path).unwrap();
let new_dir = tempfile::tempdir().unwrap();
let new_dirfd =
open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
@@ -186,12 +186,12 @@ fn test_renameat2_noreplace() {
let old_dirfd =
open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
let old_path = old_dir.path().join("old");
- File::create(&old_path).unwrap();
+ File::create(old_path).unwrap();
let new_dir = tempfile::tempdir().unwrap();
let new_dirfd =
open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
let new_path = new_dir.path().join("new");
- File::create(&new_path).unwrap();
+ File::create(new_path).unwrap();
assert_eq!(
renameat2(
Some(old_dirfd),
@@ -216,7 +216,7 @@ fn test_readlink() {
let src = tempdir.path().join("a");
let dst = tempdir.path().join("b");
println!("a: {:?}, b: {:?}", &src, &dst);
- fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
+ fs::symlink(src.as_path(), dst.as_path()).unwrap();
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
let expected_dir = src.to_str().unwrap();
@@ -231,7 +231,7 @@ fn test_readlink() {
mod linux_android {
use libc::loff_t;
use std::io::prelude::*;
- use std::io::{IoSlice, SeekFrom};
+ use std::io::IoSlice;
use std::os::unix::prelude::*;
use nix::fcntl::*;
@@ -272,7 +272,7 @@ mod linux_android {
.unwrap();
let mut res: String = String::new();
- tmp2.seek(SeekFrom::Start(0)).unwrap();
+ tmp2.rewind().unwrap();
tmp2.read_to_string(&mut res).unwrap();
assert_eq!(res, String::from("bar"));
diff --git a/test/test_kmod/mod.rs b/test/test_kmod/mod.rs
index 5ebc242..6f9aaa8 100644
--- a/test/test_kmod/mod.rs
+++ b/test/test_kmod/mod.rs
@@ -12,12 +12,12 @@ fn compile_kernel_module() -> (PathBuf, String, TempDir) {
copy(
"test/test_kmod/hello_mod/hello.c",
- &tmp_dir.path().join("hello.c"),
+ tmp_dir.path().join("hello.c"),
)
.expect("unable to copy hello.c to temporary build directory");
copy(
"test/test_kmod/hello_mod/Makefile",
- &tmp_dir.path().join("Makefile"),
+ tmp_dir.path().join("Makefile"),
)
.expect("unable to copy Makefile to temporary build directory");
diff --git a/test/test_mount.rs b/test/test_mount.rs
index febcadf..2fd612e 100644
--- a/test/test_mount.rs
+++ b/test/test_mount.rs
@@ -108,7 +108,7 @@ exit 23";
// EROFS: Read-only file system
assert_eq!(
- EROFS as i32,
+ EROFS,
File::create(tempdir.path().join("test"))
.unwrap_err()
.raw_os_error()
@@ -156,7 +156,7 @@ exit 23";
// EACCES: Permission denied
assert_eq!(
- EACCES as i32,
+ EACCES,
Command::new(&test_path)
.status()
.unwrap_err()
diff --git a/test/test_sched.rs b/test/test_sched.rs
index ebf346d..c52616b 100644
--- a/test/test_sched.rs
+++ b/test/test_sched.rs
@@ -1,4 +1,4 @@
-use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet};
+use nix::sched::{sched_getaffinity, sched_getcpu, sched_setaffinity, CpuSet};
use nix::unistd::Pid;
#[test]
@@ -30,6 +30,10 @@ fn test_sched_affinity() {
)
}
+ // Now check that we're also currently running on the CPU in question.
+ let cur_cpu = sched_getcpu().unwrap();
+ assert_eq!(cur_cpu, last_valid_cpu);
+
// Finally, reset the initial CPU set
sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap();
}
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index eee1010..9e20f97 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -903,7 +903,7 @@ fn test_linkat_file() {
let newfilepath = tempdir.path().join(newfilename);
// Create file
- File::create(&oldfilepath).unwrap();
+ File::create(oldfilepath).unwrap();
// Get file descriptor for base directory
let dirfd =
@@ -936,7 +936,7 @@ fn test_linkat_olddirfd_none() {
let newfilepath = tempdir_newfile.path().join(newfilename);
// Create file
- File::create(&oldfilepath).unwrap();
+ File::create(oldfilepath).unwrap();
// Get file descriptor for base directory of new file
let dirfd = fcntl::open(
@@ -973,7 +973,7 @@ fn test_linkat_newdirfd_none() {
let newfilepath = tempdir_newfile.path().join(newfilename);
// Create file
- File::create(&oldfilepath).unwrap();
+ File::create(oldfilepath).unwrap();
// Get file descriptor for base directory of old file
let dirfd = fcntl::open(
@@ -1101,7 +1101,7 @@ fn test_unlinkat_dir_noremovedir() {
let dirpath = tempdir.path().join(dirname);
// Create dir
- DirBuilder::new().recursive(true).create(&dirpath).unwrap();
+ DirBuilder::new().recursive(true).create(dirpath).unwrap();
// Get file descriptor for base directory
let dirfd =
@@ -1310,7 +1310,7 @@ fn test_getpeereid_invalid_fd() {
}
#[test]
-#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
fn test_faccessat_none_not_existing() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
@@ -1324,7 +1324,7 @@ fn test_faccessat_none_not_existing() {
}
#[test]
-#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
fn test_faccessat_not_existing() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
@@ -1344,7 +1344,7 @@ fn test_faccessat_not_existing() {
}
#[test]
-#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
fn test_faccessat_none_file_exists() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
@@ -1360,7 +1360,7 @@ fn test_faccessat_none_file_exists() {
}
#[test]
-#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
fn test_faccessat_file_exists() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
@@ -1376,3 +1376,32 @@ fn test_faccessat_file_exists() {
)
.is_ok());
}
+
+#[test]
+#[cfg(any(
+ all(target_os = "linux", not(target_env = "uclibc")),
+ target_os = "freebsd",
+ target_os = "dragonfly"
+))]
+fn test_eaccess_not_existing() {
+ let tempdir = tempdir().unwrap();
+ let dir = tempdir.path().join("does_not_exist.txt");
+ assert_eq!(
+ eaccess(&dir, AccessFlags::F_OK).err().unwrap(),
+ Errno::ENOENT
+ );
+}
+
+#[test]
+#[cfg(any(
+ all(target_os = "linux", not(target_env = "uclibc")),
+ target_os = "freebsd",
+ target_os = "dragonfly"
+))]
+fn test_eaccess_file_exists() {
+ let tempdir = tempdir().unwrap();
+ let path = tempdir.path().join("does_exist.txt");
+ let _file = File::create(path.clone()).unwrap();
+ eaccess(&path, AccessFlags::R_OK | AccessFlags::W_OK)
+ .expect("assertion failed");
+}