Bug 1825480 - Update crossbeam-epoch to 0.9.14 and minidump-writer to current master. r=gsvelto,supply-chain-reviewers

This updates memoffset to 0.8 and nix to 0.26.

Differential Revision: https://phabricator.services.mozilla.com/D174055
This commit is contained in:
Mike Hommey 2023-03-30 21:08:39 +00:00
parent 93784bacca
commit 1de53ad3c6
92 changed files with 4113 additions and 2265 deletions

View File

@ -105,9 +105,9 @@ git = "https://github.com/mozilla/uniffi-rs.git"
rev = "bc7ff8977bf38d0fdd1a458810b14f434d4dc4de"
replace-with = "vendored-sources"
[source."git+https://github.com/rust-minidump/minidump-writer.git?rev=7d76616d27b9dc87fe3a94639b8b4f947d52a6aa"]
[source."git+https://github.com/rust-minidump/minidump-writer.git?rev=59179c83ba62e4378619c6967c0b8c0c077cac2d"]
git = "https://github.com/rust-minidump/minidump-writer.git"
rev = "7d76616d27b9dc87fe3a94639b8b4f947d52a6aa"
rev = "59179c83ba62e4378619c6967c0b8c0c077cac2d"
replace-with = "vendored-sources"
[source."git+https://github.com/servo/rust-cssparser?rev=45bc47e2bcb846f1efb5aea156be5fe7d18624bf"]

26
Cargo.lock generated
View File

@ -960,14 +960,14 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"crossbeam-utils",
"memoffset 0.7.1",
"memoffset 0.8.0",
"scopeguard",
]
@ -3142,14 +3142,14 @@ dependencies = [
name = "memoffset"
version = "0.6.99"
dependencies = [
"memoffset 0.7.1",
"memoffset 0.8.0",
]
[[package]]
name = "memoffset"
version = "0.7.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
@ -3228,7 +3228,7 @@ dependencies = [
[[package]]
name = "minidump-writer"
version = "0.7.0"
source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=7d76616d27b9dc87fe3a94639b8b4f947d52a6aa#7d76616d27b9dc87fe3a94639b8b4f947d52a6aa"
source = "git+https://github.com/rust-minidump/minidump-writer.git?rev=59179c83ba62e4378619c6967c0b8c0c077cac2d#59179c83ba62e4378619c6967c0b8c0c077cac2d"
dependencies = [
"byteorder",
"cfg-if 1.0.0",
@ -3237,9 +3237,9 @@ dependencies = [
"libc",
"mach2",
"memmap2",
"memoffset 0.7.1",
"memoffset 0.8.0",
"minidump-common",
"nix 0.25.1",
"nix 0.26.2",
"scroll",
"tempfile",
"thiserror",
@ -3618,19 +3618,19 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
name = "nix"
version = "0.24.99"
dependencies = [
"nix 0.25.1",
"nix 0.26.2",
]
[[package]]
name = "nix"
version = "0.25.1"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
dependencies = [
"autocfg",
"bitflags",
"cfg-if 1.0.0",
"libc",
"static_assertions",
]
[[package]]

View File

@ -121,10 +121,10 @@ wasi = { path = "build/rust/wasi" }
# Patch bindgen 0.63 to 0.64
bindgen = { path = "build/rust/bindgen" }
# Patch memoffset 0.6 to 0.7
# Patch memoffset 0.6 to 0.8
memoffset = { path = "build/rust/memoffset" }
# Patch nix 0.24 to 0.25
# Patch nix 0.24 to 0.26
nix = { path = "build/rust/nix" }
# Patch hermit-abi 0.1 to 0.2
@ -157,7 +157,7 @@ firefox-on-glean = { path = "toolkit/components/glean/api" }
libudev-sys = { path = "dom/webauthn/libudev-sys" }
packed_simd = { package = "packed_simd_2", git = "https://github.com/hsivonen/packed_simd", rev="412f9a0aa556611de021bde89dee8fefe6e0fbbd" }
midir = { git = "https://github.com/mozilla/midir.git", rev = "519e651241e867af3391db08f9ae6400bc023e18" }
minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "7d76616d27b9dc87fe3a94639b8b4f947d52a6aa" }
minidump-writer = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "59179c83ba62e4378619c6967c0b8c0c077cac2d" }
# warp 0.3.3 + https://github.com/seanmonstar/warp/pull/1007
warp = { git = "https://github.com/glandium/warp", rev = "4af45fae95bc98b0eba1ef0db17e1dac471bb23d" }

View File

@ -8,4 +8,4 @@ license = "MPL-2.0"
path = "lib.rs"
[dependencies.memoffset]
version = "0.7"
version = "0.8"

View File

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

View File

@ -430,6 +430,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.9.10 -> 0.9.13"
[[audits.crossbeam-epoch]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.9.13 -> 0.9.14"
[[audits.crossbeam-queue]]
who = "Matthew Gregan <kinetik@flim.org>"
criteria = "safe-to-deploy"
@ -1356,6 +1361,11 @@ criteria = "safe-to-deploy"
version = "0.7.0"
notes = "The code in this crate was written or reviewed by Mozilla employees, the crate it evolved from was written specifically for gecko."
[[audits.minidump-writer]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.7.0 -> 0.7.0@git:59179c83ba62e4378619c6967c0b8c0c077cac2d"
[[audits.minidump-writer]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"
@ -1474,6 +1484,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.25.0 -> 0.25.1"
[[audits.nix]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.25.1 -> 0.26.2"
[[audits.nom]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"

View File

@ -142,6 +142,12 @@ criteria = "safe-to-deploy"
version = "0.2.5"
notes = "I am the author of this crate."
[[audits.bytecode-alliance.audits.memoffset]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
delta = "0.7.1 -> 0.8.0"
notes = "This was a small update to the crate which has to do with Rust language features and compiler versions, no substantial changes."
[[audits.bytecode-alliance.audits.peeking_take_while]]
who = "Nick Fitzgerald <fitzgen@gmail.com>"
criteria = "safe-to-deploy"

View File

@ -1 +1 @@
{"files":{"CHANGELOG.md":"89683da081a7830300becd6e52f1996d37f018c60e7bc76902a21462d4e4ec0c","Cargo.lock":"5337104cfd3c43ac5c9c33db0ffdb0fcde7165be3cb5bfd74d2f0ecdc8d3061f","Cargo.toml":"3f6579af3614880f21730bbe8bef41accdca901fa37afb1ae9175df4893c2445","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"d67d0cf57751a019707dd95785345ee181a10ea80237789bc3c19bf28c0d45ca","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","build-common.rs":"502cb7494549bed6fa10ac7bea36e880eeb60290dc69b679ac5c92b376469562","build.rs":"901be3c21843440be5c456ff049f57f72ee5ec365918a772ad2a4751e52f69c5","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","no_atomic.rs":"3314524d2afa0360c947455a6e6566fb54ebf909c99479ca3b7435741fd3293e","src/atomic.rs":"1bd4275c1411852024533e8a70959dfedf72029e3253544d1fbb0cc18b6fd519","src/collector.rs":"29e5911f61510247659b0090517bd1a38d11e1ed86e35811603cb599962d9a58","src/default.rs":"62edf5e1f934eb82d8d7f010d6f25366e6851145a6f0a162372202bb63da1f3a","src/deferred.rs":"0c87df5797212778edd3c2d5fcf0cc04e8b9ed100261ecf9522f74a90804a3d5","src/epoch.rs":"d31e66d8fe62299928e25867336d96391b26a4fe890a1cae0885dfcf36d6835b","src/guard.rs":"f4439909152d38c03b6dfb6eeba6c9f07c39962187d461c92a492c27c258670b","src/internal.rs":"ac40ce276f0ed3dfd561926b78f775592eabb90790e177edde41fe50c13b8256","src/lib.rs":"a036d73230d0574011e67be11d275fe46439a1b5fc3295cb242d9179e5e0a220","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"c03dc9c05a817e087dccf8b682f7307501542805533551da3c2bab442bc40743","src/sync/queue.rs":"06173b2255677d0d39178ceb49876fda2878f491e907c595eb65643dbb43c9ba","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"}
{"files":{"CHANGELOG.md":"41aadd10f28a79ac9a8f8960ed1d9b01b2c637a9c5d16c44632794ea154b195b","Cargo.lock":"6347500366837bb0270a958edbeaf955d148ffe9eaad4a4903cbb078e3d50852","Cargo.toml":"e829a9a24e8c67f588cc33360c98ecee410bb33204eab021d5a29e1c9370c342","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"d67d0cf57751a019707dd95785345ee181a10ea80237789bc3c19bf28c0d45ca","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","build-common.rs":"502cb7494549bed6fa10ac7bea36e880eeb60290dc69b679ac5c92b376469562","build.rs":"901be3c21843440be5c456ff049f57f72ee5ec365918a772ad2a4751e52f69c5","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","no_atomic.rs":"c291992d273abba165579ada7873c34ce4f3674363a7c1ec092be856beac0355","src/atomic.rs":"1bd4275c1411852024533e8a70959dfedf72029e3253544d1fbb0cc18b6fd519","src/collector.rs":"29e5911f61510247659b0090517bd1a38d11e1ed86e35811603cb599962d9a58","src/default.rs":"62edf5e1f934eb82d8d7f010d6f25366e6851145a6f0a162372202bb63da1f3a","src/deferred.rs":"0c87df5797212778edd3c2d5fcf0cc04e8b9ed100261ecf9522f74a90804a3d5","src/epoch.rs":"d31e66d8fe62299928e25867336d96391b26a4fe890a1cae0885dfcf36d6835b","src/guard.rs":"f4439909152d38c03b6dfb6eeba6c9f07c39962187d461c92a492c27c258670b","src/internal.rs":"ac40ce276f0ed3dfd561926b78f775592eabb90790e177edde41fe50c13b8256","src/lib.rs":"a036d73230d0574011e67be11d275fe46439a1b5fc3295cb242d9179e5e0a220","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"c03dc9c05a817e087dccf8b682f7307501542805533551da3c2bab442bc40743","src/sync/queue.rs":"06173b2255677d0d39178ceb49876fda2878f491e907c595eb65643dbb43c9ba","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"}

View File

@ -1,3 +1,7 @@
# Version 0.9.14
- Update `memoffset` to 0.8. (#955)
# Version 0.9.13
- Fix build script bug introduced in 0.9.12. (#932)

View File

@ -10,9 +10,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "cc"
version = "1.0.77"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@ -22,7 +22,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"autocfg",
"cfg-if",
@ -36,9 +36,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
"loom",
@ -46,9 +46,9 @@ dependencies = [
[[package]]
name = "generator"
version = "0.7.1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc184cace1cea8335047a471cc1da80f18acf8a76f3bab2028d499e328948ec7"
checksum = "33a20a288a94683f5f4da0adecdbe095c94a77c295e514cc6484e9394dd8376e"
dependencies = [
"cc",
"libc",
@ -76,9 +76,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.137"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
@ -113,9 +113,9 @@ dependencies = [
[[package]]
name = "memoffset"
version = "0.7.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
@ -132,9 +132,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.16.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "overload"
@ -156,18 +156,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.47"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@ -204,9 +204,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"regex-syntax",
]
@ -228,9 +228,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustversion"
version = "1.0.9"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
[[package]]
name = "scoped-tls"
@ -261,9 +261,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "syn"
version = "1.0.103"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@ -272,10 +272,11 @@ dependencies = [
[[package]]
name = "thread_local"
version = "1.1.4"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if",
"once_cell",
]
@ -343,9 +344,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "valuable"
@ -383,43 +384,66 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.32.0"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec"
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"

View File

@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.38"
name = "crossbeam-epoch"
version = "0.9.13"
version = "0.9.14"
description = "Epoch-based garbage collection"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch"
readme = "README.md"
@ -39,7 +39,7 @@ version = "0.8.5"
default-features = false
[dependencies.memoffset]
version = "0.7"
version = "0.8"
[dependencies.scopeguard]
version = "1.1"

View File

@ -28,6 +28,7 @@ const NO_ATOMIC_64: &[&str] = &[
"armv5te-unknown-linux-musleabi",
"armv5te-unknown-linux-uclibceabi",
"armv6k-nintendo-3ds",
"armv7-sony-vita-newlibeabihf",
"armv7r-none-eabi",
"armv7r-none-eabihf",
"avr-unknown-gnu-atmega328",
@ -74,6 +75,8 @@ const NO_ATOMIC_64: &[&str] = &[
#[allow(dead_code)] // Only crossbeam-utils uses this.
const NO_ATOMIC: &[&str] = &[
"avr-unknown-gnu-atmega328",
"bpfeb-unknown-none",
"bpfel-unknown-none",
"mipsel-sony-psx",
"msp430-none-elf",
"riscv32i-unknown-none-elf",

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"2122b76e5dff09497c7edf7f184155e456e44209c05e4f8abb01632be7241b56","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"7a7935d96a1a40b56afeadca391c742f7ac3a6e0f1deab1d43430553f71b6d23","build.rs":"6d677e33a1c98d588c97ec7985d4d5c3b954683e0a73c3dc53d79db4fbb5e638","src/lib.rs":"e7976d295371a3c1e0cf31b0d50210cd6b1135caba3a5111403a97ec6175c0a2","src/offset_of.rs":"ea04e76e3ab1fa192618fffb0c6a047795c275f1deaf6c6617245badaba8660c","src/raw_field.rs":"ef54087d5f507c2b639a4f61f2881eb1e41a46e22191ffd0e23b2fe9e3f17c25","src/span_of.rs":"b900faef2b852b52c37c55a172c05c9144bfff7d84dbc06e943fb0453d68adfc"},"package":"5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"}
{"files":{"Cargo.toml":"d1193e8d228ceb5aa5792b8170c0cec8802489d66eb590bae693ae0a009c3bb9","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"a673f0b4b5ac46034590a670572bd1a87837fdedb5170dabbea08d392e6cfa4b","build.rs":"df34c830dbb08eba3474304eed481bc2c8a29e897bc50f46d37b5dbb6e443a2b","src/lib.rs":"cc7f53556da6f53e5818e31330b488ad0de8d58096edf05f9f27e7f1159d1bfe","src/offset_of.rs":"9a2f9e8a7739a615df214738302bb74df584a53485a7f3536c0aca17ce936db3","src/raw_field.rs":"ef54087d5f507c2b639a4f61f2881eb1e41a46e22191ffd0e23b2fe9e3f17c25","src/span_of.rs":"b900faef2b852b52c37c55a172c05c9144bfff7d84dbc06e943fb0453d68adfc"},"package":"d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"}

View File

@ -11,7 +11,7 @@
[package]
name = "memoffset"
version = "0.7.1"
version = "0.8.0"
authors = ["Gilad Naaman <gilad.naaman@gmail.com>"]
description = "offset_of functionality for Rust structs."
readme = "README.md"

View File

@ -7,6 +7,7 @@ C-Like `offset_of` functionality for Rust structs.
Introduces the following macros:
* `offset_of!` for obtaining the offset of a member of a struct.
* `offset_of_tuple!` for obtaining the offset of a member of a tuple. (Requires Rust 1.20+)
* `offset_of_union!` for obtaining the offset of a member of a union.
* `span_of!` for obtaining the range that a field, or fields, span.
`memoffset` works under `no_std` environments.
@ -16,7 +17,7 @@ Add the following dependency to your `Cargo.toml`:
```toml
[dependencies]
memoffset = "0.7"
memoffset = "0.8"
```
These versions will compile fine with rustc versions greater or equal to 1.19.
@ -45,20 +46,39 @@ fn main() {
}
```
## Feature flags ##
## Usage in constants ##
`memoffset` has support for compile-time `offset_of!` on rust>=1.65, or on older nightly compilers.
### Usage in constants ###
`memoffset` has **experimental** support for compile-time `offset_of!` on a nightly compiler.
### Usage on stable Rust ###
Constant evaluation is automatically enabled and avilable on stable compilers starting with rustc 1.65.
In order to use it, you must enable the `unstable_const` crate feature and several compiler features.
This is an incomplete implementation with one caveat:
Due to dependence on [`#![feature(const_refs_to_cell)]`](https://github.com/rust-lang/rust/issues/80384), you cannot get the offset of a `Cell` field in a const-context.
This means that if need to get the offset of a cell, you'll have to remain on nightly for now.
### Usage on recent nightlies ###
If you're using a new-enough nightly and you require the ability to get the offset of a `Cell`,
you'll have to enable the `unstable_const` cargo feature, as well as enabling `const_refs_to_cell` in your crate root.
Do note that `unstable_const` is an unstable feature that is set to be removed in a future version of `memoffset`.
Cargo.toml:
```toml
[dependencies.memoffset]
version = "0.7"
version = "0.8"
features = ["unstable_const"]
```
Your crate root: (`lib.rs`/`main.rs`)
```rust,ignore
#![feature(const_refs_to_cell)]
```
### Usage on older nightlies ###
In order to use it on an older nightly compiler, you must enable the `unstable_const` crate feature and several compiler features.
Your crate root: (`lib.rs`/`main.rs`)
```rust,ignore
#![feature(const_ptr_offset_from, const_refs_to_cell)]

View File

@ -19,4 +19,7 @@ fn main() {
if ac.probe_rustc_version(1, 51) {
println!("cargo:rustc-cfg=raw_ref_macros");
}
if ac.probe_rustc_version(1, 65) {
println!("cargo:rustc-cfg=stable_const");
}
}

View File

@ -57,9 +57,10 @@
#![no_std]
#![cfg_attr(
feature = "unstable_const",
feature(const_ptr_offset_from, const_refs_to_cell)
all(feature = "unstable_const", not(stable_const)),
feature(const_ptr_offset_from)
)]
#![cfg_attr(feature = "unstable_const", feature(const_refs_to_cell))]
#[macro_use]
#[cfg(doctests)]

View File

@ -46,7 +46,7 @@ macro_rules! _memoffset__let_base_ptr {
}
/// Macro to compute the distance between two pointers.
#[cfg(feature = "unstable_const")]
#[cfg(any(feature = "unstable_const", stable_const))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from_unsafe {
@ -58,7 +58,7 @@ macro_rules! _memoffset_offset_from_unsafe {
unsafe { (field as *const u8).offset_from(base as *const u8) as usize }
}};
}
#[cfg(not(feature = "unstable_const"))]
#[cfg(not(any(feature = "unstable_const", stable_const)))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset_offset_from_unsafe {
@ -312,7 +312,7 @@ mod tests {
assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize);
}
#[cfg(feature = "unstable_const")]
#[cfg(any(feature = "unstable_const", stable_const))]
#[test]
fn const_offset() {
#[repr(C)]
@ -337,7 +337,7 @@ mod tests {
assert_eq!([0; offset_of!(Foo, b)].len(), 4);
}
#[cfg(feature = "unstable_const")]
#[cfg(any(feature = "unstable_const", stable_const))]
#[test]
fn const_fn_offset() {
const fn test_fn() -> usize {

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: deny audit
uses: EmbarkStudios/cargo-deny-action@v1
with:

View File

@ -32,8 +32,8 @@ jobs:
strategy:
matrix:
job:
- { os: ubuntu-20.04 , target: x86_64-unknown-linux-gnu }
- { os: ubuntu-20.04, target: x86_64-unknown-linux-musl }
- { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-22.04, target: x86_64-unknown-linux-musl }
- { os: windows-2022, target: x86_64-pc-windows-msvc }
- { os: macos-12, target: x86_64-apple-darwin }
# TODO: Add macos aarch64 here once it becomes available as a runner
@ -57,17 +57,17 @@ jobs:
strategy:
matrix:
job:
- { os: ubuntu-latest, target: i686-unknown-linux-gnu, use-cross: true }
- { os: ubuntu-22.04, target: i686-unknown-linux-gnu, use-cross: true }
#- { os: ubuntu-latest, target: i686-unknown-linux-musl, use-cross: true }
- { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, use-cross: true }
- { os: ubuntu-latest, target: aarch64-unknown-linux-musl, use-cross: true }
- { os: ubuntu-latest, target: aarch64-linux-android, use-cross: true }
- { os: ubuntu-latest, target: arm-unknown-linux-gnueabi, use-cross: true }
- { os: ubuntu-latest, target: arm-unknown-linux-musleabi, use-cross: true }
- { os: ubuntu-latest, target: arm-linux-androideabi, use-cross: true }
- { os: ubuntu-latest, target: arm-unknown-linux-gnueabihf, use-cross: true }
- { os: ubuntu-22.04, target: aarch64-unknown-linux-gnu, use-cross: true }
- { os: ubuntu-22.04, target: aarch64-unknown-linux-musl, use-cross: true }
#- { os: ubuntu-22.04, target: aarch64-linux-android, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-gnueabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-musleabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-linux-androideabi, use-cross: true }
- { os: ubuntu-22.04, target: arm-unknown-linux-gnueabihf, use-cross: true }
# TODO: Remove this when aarch64 macs can be used as runners
- { os: macos-latest, target: aarch64-apple-darwin, use-cross: false }
- { os: macos-12, target: aarch64-apple-darwin, use-cross: false }
steps:
- uses: actions/checkout@v3
- name: Install Rust

View File

@ -24,7 +24,7 @@ repository = "https://github.com/rust-minidump/minidump-writer"
byteorder = "1.3.2"
cfg-if = "1.0"
crash-context = "0.5"
memoffset = "0.7"
memoffset = "0.8"
minidump-common = "0.15"
scroll = "0.11"
tempfile = "3.1.0"
@ -39,7 +39,7 @@ version = "0.3"
features = ["executor"]
[target."cfg(any(target_os = \"linux\", target_os = \"android\"))".dependencies.nix]
version = "0.25"
version = "0.26"
features = [
"mman",
"process",
@ -66,6 +66,7 @@ default-features = false
[target."cfg(target_os = \"windows\")".dependencies.winapi]
version = "0.3"
features = [
"handleapi",
"minwindef",
"processthreadsapi",
"winnt",

View File

@ -88,7 +88,7 @@ mod linux {
fn test_file_id() -> Result<()> {
let ppid = getppid().as_raw();
let exe_link = format!("/proc/{}/exe", ppid);
let exe_name = std::fs::read_link(&exe_link)?.into_os_string();
let exe_name = std::fs::read_link(exe_link)?.into_os_string();
let mut dumper = PtraceDumper::new(getppid().as_raw())?;
let mut found_exe = None;
for (idx, mapping) in dumper.mappings.iter().enumerate() {
@ -207,11 +207,11 @@ mod linux {
fn spawn_mmap_wait() -> Result<()> {
let page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE).unwrap();
let memory_size = page_size.unwrap() as usize;
let memory_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
// Get some memory to be mapped by the child-process
let mapped_mem = unsafe {
mmap(
std::ptr::null_mut(),
None,
memory_size,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE | MapFlags::MAP_ANON,

View File

@ -2,7 +2,7 @@ use crate::{
mem_writer::{Buffer, MemoryArrayWriter, MemoryWriterError},
minidump_format::MDRawDirectory,
};
use std::io::{Error, Seek, SeekFrom, Write};
use std::io::{Error, Seek, Write};
pub type DumpBuf = Buffer;
@ -44,7 +44,7 @@ where
Ok(Self {
curr_idx: 0,
section: dir_section,
destination_start_offset: destination.seek(SeekFrom::Current(0))?,
destination_start_offset: destination.stream_position()?,
destination,
last_position_written_to_file: 0,
})
@ -65,7 +65,7 @@ where
// Now write it to file
// First get all the positions
let curr_file_pos = self.destination.seek(SeekFrom::Current(0))?;
let curr_file_pos = self.destination.stream_position()?;
let idx_pos = self.section.location_of_index(self.curr_idx);
self.curr_idx += 1;

View File

@ -42,21 +42,21 @@ pub struct LinkMap {
}
// COPY from <link.h>
#[derive(Debug, Clone)]
/// This state value describes the mapping change taking place when
/// the `r_brk' address is called.
#[derive(Debug, Clone, Default)]
#[allow(non_camel_case_types, unused)]
#[repr(C)]
enum RState {
/* This state value describes the mapping change taking place when
the `r_brk' address is called. */
RT_CONSISTENT, /* Mapping change is complete. */
RT_ADD, /* Beginning to add a new object. */
RT_DELETE, /* Beginning to remove an object mapping. */
}
impl Default for RState {
fn default() -> Self {
RState::RT_CONSISTENT // RStates are not used anyway
}
/// Mapping change is complete.
#[default]
RT_CONSISTENT,
/// Beginning to add a new object.
RT_ADD,
/// Beginning to remove an object mapping.
RT_DELETE,
}
// COPY from <link.h>
#[derive(Debug, Clone, Default)]
#[repr(C)]

View File

@ -156,7 +156,7 @@ impl MinidumpWriter {
return true;
}
let (stack_ptr, stack_len) = match dumper.get_stack_info(stack_pointer as usize) {
let (stack_ptr, stack_len) = match dumper.get_stack_info(stack_pointer) {
Ok(x) => x,
Err(_) => {
return false;
@ -173,7 +173,7 @@ impl MinidumpWriter {
}
};
let sp_offset = stack_pointer as usize - stack_ptr;
let sp_offset = stack_pointer - stack_ptr;
self.principal_mapping
.as_ref()
.unwrap()

View File

@ -213,7 +213,6 @@ impl PtraceDumper {
if task_path.is_dir() {
std::fs::read_dir(task_path)
.map_err(|e| InitError::IOError(filename, e))?
.into_iter()
.filter_map(|entry| entry.ok()) // Filter out bad entries
.filter_map(|entry| {
entry
@ -481,14 +480,14 @@ impl PtraceDumper {
) -> Option<&'data [u8]> {
if let Some(mut notes) = elf_obj.iter_note_headers(mem_slice) {
while let Some(Ok(note)) = notes.next() {
if note.n_type == elf::note::NT_GNU_BUILD_ID {
if (note.name == "GNU") && (note.n_type == elf::note::NT_GNU_BUILD_ID) {
return Some(note.desc);
}
}
}
if let Some(mut notes) = elf_obj.iter_note_sections(mem_slice, Some(".note.gnu.build-id")) {
while let Some(Ok(note)) = notes.next() {
if note.n_type == elf::note::NT_GNU_BUILD_ID {
if (note.name == "GNU") && (note.n_type == elf::note::NT_GNU_BUILD_ID) {
return Some(note.desc);
}
}

View File

@ -8,9 +8,9 @@ pub fn write(
) -> Result<MDRawDirectory, errors::SectionExceptionStreamError> {
let exception = if let Some(context) = &config.crash_context {
MDException {
exception_code: context.inner.siginfo.ssi_signo as u32,
exception_code: context.inner.siginfo.ssi_signo,
exception_flags: context.inner.siginfo.ssi_code as u32,
exception_address: context.inner.siginfo.ssi_addr as u64,
exception_address: context.inner.siginfo.ssi_addr,
..Default::default()
}
} else {

View File

@ -74,8 +74,8 @@ pub fn write(
// unhelpful.
if config.crash_context.is_some() && thread.thread_id == config.blamed_thread as u32 {
let crash_context = config.crash_context.as_ref().unwrap();
let instruction_ptr = crash_context.get_instruction_pointer() as usize;
let stack_pointer = crash_context.get_stack_pointer() as usize;
let instruction_ptr = crash_context.get_instruction_pointer();
let stack_pointer = crash_context.get_stack_pointer();
fill_thread_stack(
config,
buffer,
@ -142,7 +142,7 @@ pub fn write(
} else {
MaxStackLen::None // default to no maximum for this thread
};
let instruction_ptr = info.get_instruction_pointer() as usize;
let instruction_ptr = info.get_instruction_pointer();
fill_thread_stack(
config,
buffer,

View File

@ -118,7 +118,7 @@ where
let position = buffer.reserve(size) as u32;
Ok(Self {
position: position as u32,
position,
size,
phantom: std::marker::PhantomData,
})

View File

@ -114,8 +114,8 @@ fn test_linux_gate_mapping_id() {
#[test]
fn test_merged_mappings() {
let page_size = nix::unistd::sysconf(nix::unistd::SysconfVar::PAGE_SIZE).unwrap();
let page_size = page_size.unwrap() as usize;
let map_size = 3 * page_size;
let page_size = std::num::NonZeroUsize::new(page_size.unwrap() as usize).unwrap();
let map_size = std::num::NonZeroUsize::new(3 * page_size.get()).unwrap();
let path: &'static str = std::env!("CARGO_BIN_EXE_test");
let file = std::fs::File::open(path).unwrap();
@ -124,7 +124,7 @@ fn test_merged_mappings() {
// enclosed in the other, but with different protections.
let mapped_mem = unsafe {
mmap(
std::ptr::null_mut(),
None,
map_size,
ProtFlags::PROT_READ,
MapFlags::MAP_SHARED,
@ -137,14 +137,14 @@ fn test_merged_mappings() {
// Carve a page out of the first mapping with different permissions.
let _inside_mapping = unsafe {
mmap(
(mapped_mem as usize + 2 * page_size) as *mut libc::c_void,
std::num::NonZeroUsize::new(mapped_mem as usize + 2 * page_size.get()),
page_size,
ProtFlags::PROT_NONE,
MapFlags::MAP_SHARED | MapFlags::MAP_FIXED,
file.as_raw_fd(),
// Map a different offset just to
// better test real-world conditions.
page_size.try_into().unwrap(), // try_into() in order to work for 32 and 64 bit
page_size.get().try_into().unwrap(), // try_into() in order to work for 32 and 64 bit
)
};
@ -153,7 +153,7 @@ fn test_merged_mappings() {
&[
path,
&format!("{}", mapped_mem as usize),
&format!("{}", map_size),
&format!("{map_size}"),
],
);
}
@ -255,7 +255,7 @@ fn test_sanitize_stack_copy() {
}
// The instruction pointer definitely should point into an executable mapping.
let instr_ptr = thread_info.get_instruction_pointer() as usize;
let instr_ptr = thread_info.get_instruction_pointer();
let mapping_info = dumper
.find_mapping_no_bias(instr_ptr)
.expect("Failed to find mapping info");

File diff suppressed because one or more lines are too long

View File

@ -3,18 +3,70 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).
## [0.25.1] - 2022-12-02
## [0.26.2] - 2023-01-18
### Fixed
- Fix `SockaddrIn6` bug that was swapping flowinfo and scope_id byte ordering.
([#1964](https://github.com/nix-rust/nix/pull/1964))
## [0.26.1] - 2022-11-29
### Fixed
- Fix UB with `sys::socket::sockopt::SockType` using `SOCK_PACKET`.
([#1821](https://github.com/nix-rust/nix/pull/1821))
## [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
- Workaround XNU bug causing netmasks returned by `getifaddrs` to misbehave.
([#1788](https://github.com/nix-rust/nix/pull/1788))
- 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
@ -22,13 +74,14 @@ This project adheres to [Semantic Versioning](https://semver.org/).
([#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))
- Fixed using `SockaddrStorage` to store a Unix-domain socket address on Linux.
([#1871](https://github.com/nix-rust/nix/pull/1871))
- Fix UB with `sys::socket::sockopt::SockType` using `SOCK_PACKET`.
([#1821](https://github.com/nix-rust/nix/pull/1821))
- 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
@ -70,6 +123,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.
@ -339,6 +395,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))
@ -364,8 +444,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
@ -421,6 +512,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
@ -484,8 +589,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
@ -598,22 +701,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
@ -741,8 +838,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
@ -767,8 +862,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.
@ -837,6 +930,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.
@ -854,14 +964,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
@ -913,7 +1039,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

View File

@ -11,9 +11,9 @@
[package]
edition = "2018"
rust-version = "1.46"
rust-version = "1.56"
name = "nix"
version = "0.25.1"
version = "0.26.2"
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]

View File

@ -47,6 +47,7 @@ limitations. Support for platforms is split into three tiers:
The following targets are supported by `nix`:
Tier 1:
* aarch64-apple-darwin
* aarch64-unknown-linux-gnu
* arm-unknown-linux-gnueabi
* armv7-unknown-linux-gnueabihf
@ -58,13 +59,11 @@ Tier 1:
* mips64el-unknown-linux-gnuabi64
* mipsel-unknown-linux-gnu
* powerpc64le-unknown-linux-gnu
* x86_64-apple-darwin
* x86_64-unknown-freebsd
* x86_64-unknown-linux-gnu
* x86_64-unknown-linux-musl
Tier 2:
* aarch64-apple-darwin
* aarch64-apple-ios
* aarch64-linux-android
* arm-linux-androideabi
@ -75,6 +74,7 @@ Tier 2:
* s390x-unknown-linux-gnu
* x86_64-apple-ios
* x86_64-linux-android
* x86_64-apple-darwin
* x86_64-unknown-illumos
* x86_64-unknown-netbsd
@ -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

View File

@ -1,13 +1,13 @@
//! List directory contents
use crate::{Error, NixPath, Result};
use crate::errno::Errno;
use crate::fcntl::{self, OFlag};
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;
use std::ffi;
use crate::sys;
use cfg_if::cfg_if;
#[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,7 @@ 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 {
@ -240,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),
@ -253,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
}
}

View File

@ -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;
@ -51,34 +51,6 @@ pub fn errno() -> i32 {
}
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;

View File

@ -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 {

View File

@ -11,9 +11,9 @@ 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)]

View File

@ -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)
}

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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::*;

View File

@ -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)
}

View File

@ -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())

View File

@ -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)

View File

@ -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(),
)
},
}
};

View File

@ -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.

View File

@ -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 {

View File

@ -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)

View File

@ -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());
}

View File

@ -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 {

View File

@ -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::unistd::read;
use crate::Result;
use crate::NixPath;
use crate::errno::Errno;
use crate::unistd::read;
use crate::NixPath;
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;

View File

@ -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)

View File

@ -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)
}

View File

@ -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;

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}

View File

@ -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::*;

View File

@ -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,
)
}

View File

@ -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)
}

View File

@ -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();

View File

@ -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));
}

View File

@ -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`.
///

View File

@ -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

View File

@ -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());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +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::convert::TryFrom;
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
@ -52,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
@ -93,9 +96,13 @@ 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)?;
match <$ty>::try_from(getter.assume_init()) {
@ -105,7 +112,7 @@ macro_rules! getsockopt_impl {
}
}
}
}
};
}
/// Helper to generate the sockopt accessors. See
@ -252,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")))]
@ -269,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")]
@ -326,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!(
@ -411,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!(
@ -432,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, GetStruct<i32>);
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",
@ -536,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",
@ -551,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",
@ -564,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",
@ -577,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",
@ -651,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!
@ -667,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)
}
}
@ -691,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)
}
}
@ -761,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()
}
}
@ -808,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
}
}
@ -820,7 +1178,9 @@ struct SetBool {
impl<'a> Set<'a, bool> for SetBool {
fn new(val: &'a bool) -> SetBool {
SetBool { val: i32::from(*val) }
SetBool {
val: i32::from(*val),
}
}
fn ffi_ptr(&self) -> *const c_void {
@ -855,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()
}
}
@ -902,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
}
}
@ -962,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 {
@ -974,7 +1344,6 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> {
}
}
#[cfg(test)]
mod test {
#[cfg(any(target_os = "android", target_os = "linux"))]
@ -982,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);
@ -994,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();
@ -1006,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();
@ -1027,5 +1419,4 @@ mod test {
assert!(s_listening2);
close(s).unwrap();
}
}

View File

@ -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)

View File

@ -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 {
self.0.f_bfree
}
/// Free 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_free(&self) -> libc::c_ulong {
pub fn blocks_free(&self) -> u32 {
self.0.f_bfree
}
/// Free blocks available to unprivileged user
#[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
#[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 {
self.0.f_files
}
/// Total 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_attr(docsrs, doc(cfg(all())))]
pub fn files(&self) -> libc::c_ulong {
pub fn files(&self) -> u32 {
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 = "ios",
target_os = "macos",
target_os = "android",
target_os = "fuchsia",
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(target_os = "emscripten")]
#[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_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()))
}
}

View File

@ -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() {

View File

@ -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",
@ -1055,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

View File

@ -6,9 +6,12 @@ use std::convert::From;
use std::time::Duration;
use std::{cmp, fmt, ops};
const TIMESPEC_ZERO: libc::timespec = unsafe {
std::mem::transmute([0u8; std::mem::size_of::<libc::timespec>()])
};
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")),
@ -24,7 +27,7 @@ const TIMESPEC_ZERO: libc::timespec = unsafe {
)
))]
pub(crate) mod timer {
use crate::sys::time::{TimeSpec, TIMESPEC_ZERO};
use crate::sys::time::{zero_init_timespec, TimeSpec};
use bitflags::bitflags;
#[derive(Debug, Clone, Copy)]
@ -33,8 +36,8 @@ pub(crate) mod timer {
impl TimerSpec {
pub const fn none() -> Self {
Self(libc::itimerspec {
it_interval: TIMESPEC_ZERO,
it_value: TIMESPEC_ZERO,
it_interval: zero_init_timespec(),
it_value: zero_init_timespec(),
})
}
}
@ -55,7 +58,7 @@ pub(crate) mod timer {
fn from(expiration: Expiration) -> TimerSpec {
match expiration {
Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
it_interval: TIMESPEC_ZERO,
it_interval: zero_init_timespec(),
it_value: *t.as_ref(),
}),
Expiration::IntervalDelayed(start, interval) => {
@ -261,9 +264,8 @@ impl TimeValLike for TimeSpec {
"TimeSpec out of bounds; seconds={}",
seconds
);
let mut ts = TIMESPEC_ZERO;
let mut ts = zero_init_timespec();
ts.tv_sec = seconds as time_t;
ts.tv_nsec = 0;
TimeSpec(ts)
}
@ -296,7 +298,7 @@ impl TimeValLike for TimeSpec {
(TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&secs),
"TimeSpec out of bounds"
);
let mut ts = TIMESPEC_ZERO;
let mut ts = zero_init_timespec();
ts.tv_sec = secs as time_t;
ts.tv_nsec = nanos as timespec_tv_nsec_t;
TimeSpec(ts)
@ -333,7 +335,7 @@ 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 {
let mut ts = TIMESPEC_ZERO;
let mut ts = zero_init_timespec();
ts.tv_sec = seconds;
ts.tv_nsec = nanoseconds;
Self(ts)
@ -359,7 +361,7 @@ impl TimeSpec {
#[cfg_attr(target_env = "musl", allow(deprecated))]
// https://github.com/rust-lang/libc/issues/1848
pub const fn from_duration(duration: Duration) -> Self {
let mut ts = TIMESPEC_ZERO;
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)

View File

@ -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) }
}

View File

@ -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(

View File

@ -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)
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,
)
}
}

View File

@ -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)
}

View File

@ -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;

View File

@ -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))

View File

@ -1,10 +1,10 @@
#[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 crate::errno::Errno;
#[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)
}
}
}

View File

@ -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)
@ -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! {

View File

@ -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);

View File

@ -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,

View File

@ -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"),

View File

@ -263,6 +263,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() {
@ -354,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);
}

View File

@ -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;

View File

@ -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"));

View File

@ -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();
}

View File

@ -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");
}